From c1fce2f4e0c9eab5e43e18c6b85d7ff252022da5 Mon Sep 17 00:00:00 2001 From: "go.tanaka" Date: Mon, 17 Jun 2024 11:17:51 +0900 Subject: [PATCH 1/3] add commands --- package-lock.json | 598 +++++++++++++++++++++++++++++---- package.json | 1 + src/cmd/actor.ts | 5 +- src/cmd/command.ts | 138 ++++++++ src/cmd/commands/initialize.ts | 22 ++ src/cmd/graph.ts | 5 +- src/cmd/info.ts | 3 +- src/cmd/init.ts | 46 +-- src/cmd/list.ts | 3 +- src/cmd/state.ts | 3 +- src/cmd/usecase.ts | 5 +- src/cmd/view.ts | 9 +- src/model/JsonSchema.ts | 1 - src/model/RDRA.ts | 43 ++- src/model/actor/Actor.ts | 25 +- src/model/actor/Overview.ts | 4 + src/model/business/Business.ts | 4 +- src/util/Yaml.ts | 8 +- 18 files changed, 786 insertions(+), 137 deletions(-) create mode 100644 src/cmd/command.ts create mode 100644 src/cmd/commands/initialize.ts diff --git a/package-lock.json b/package-lock.json index 421eae5..8ec5a26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,10 +5,12 @@ "requires": true, "packages": { "": { + "name": "rdra", "version": "0.0.9", "license": "Apache-2.0", "dependencies": { "@aduh95/viz.js": "^3.5.0", + "@inquirer/prompts": "^5.0.5", "ajv": "^8.10.0", "chalk": "^4.1.2", "cli-table": "^0.3.11", @@ -624,6 +626,193 @@ "node": ">=12" } }, + "node_modules/@inquirer/checkbox": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.3.5.tgz", + "integrity": "sha512-3V0OSykTkE/38GG1DhxRGLBmqefgzRg2EK5A375zz+XEvIWfAHcac31e+zlBDPypRHxhmXc/Oh6v9eOPbH3nAg==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.9.tgz", + "integrity": "sha512-UF09aejxCi4Xqm6N/jJAiFXArXfi9al52AFaSD+2uIHnhZGtd1d6lIGTRMPouVSJxbGEi+HkOWSYaiEY/+szUw==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.2.tgz", + "integrity": "sha512-K8SuNX45jEFlX3EBJpu9B+S2TISzMPGXZIuJ9ME924SqbdW6Pt6fIkKvXg7mOEOKJ4WxpQsxj0UTfcL/A434Ww==", + "dependencies": { + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.12.13", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.9.tgz", + "integrity": "sha512-5xCD7CoCh993YqXcsZPt45qkE3gl+03Yfv9vmAkptRi4nrzaUDmyhgBzndKdRG8SrKbQLBmOtztnRLGxvG/ahg==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/expand": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.9.tgz", + "integrity": "sha512-ymnR8qu2ie/3JpOeyZ3QSGJ+ai8qqtjBwopxLjzIZm7mZVKT6SV1sURzijkOLRgGUHwPemOfYX5biqXuqhpoBg==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", + "integrity": "sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.1.9.tgz", + "integrity": "sha512-1xTCHmIe48x9CG1+8glAHrVVdH+QfYhzgBUbgyoVpp5NovnXgRcjSn/SNulepxf9Ol8HDq3gzw3ZCAUr+h1Eyg==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/password": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.9.tgz", + "integrity": "sha512-QPtVcT12Fkn0TyuZJelR7QOtc5l1d/6pB5EfkHOivTzC6QTFxRCHl+Gx7Q3E2U/kgJeCCmDov6itDFggk9nkgA==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/prompts": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.0.5.tgz", + "integrity": "sha512-LV2XZzc8ls4zhUzYNSpsXcnA8djOptY4G01lFzp3Bey6E1oiZMzIU25N9cb5AOwNz6pqDXpjLwRFQmLQ8h6PaQ==", + "dependencies": { + "@inquirer/checkbox": "^2.3.5", + "@inquirer/confirm": "^3.1.9", + "@inquirer/editor": "^2.1.9", + "@inquirer/expand": "^2.1.9", + "@inquirer/input": "^2.1.9", + "@inquirer/password": "^2.1.9", + "@inquirer/rawlist": "^2.1.9", + "@inquirer/select": "^2.3.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.9.tgz", + "integrity": "sha512-GuMmfa/v1ZJqEWSkUx1hMxzs5/0DCUP0S8IicV/wu8QrbjfBOh+7mIQgtsvh8IJ3sRkRcQ+9wh9CE9jiYqyMgw==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/select": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.3.5.tgz", + "integrity": "sha512-IyBj8oEtmdF2Gx4FJTPtEya37MD6s0KATKsHqgmls0lK7EQbhYSq9GQlcFq6cBsYe/cgQ0Fg2cCqYYPi/d/fxQ==", + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.3.tgz", + "integrity": "sha512-xTUt0NulylX27/zMx04ZYar/kr1raaiFTVvQ5feljQsiAgdm0WPj4S73/ye0fbslh+15QrIuDvfCXTek7pMY5A==", + "engines": { + "node": ">=18" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -640,6 +829,28 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -1070,11 +1281,21 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/prettier": { "version": "2.4.4", @@ -1088,6 +1309,11 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, "node_modules/@types/yargs": { "version": "17.0.1", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.1.tgz", @@ -1192,7 +1418,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -1244,15 +1469,6 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1487,6 +1703,11 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -1499,6 +1720,17 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-table": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", @@ -1510,6 +1742,14 @@ "node": ">= 0.2.0" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -1895,6 +2135,19 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2137,7 +2390,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -2981,19 +3233,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", @@ -3254,6 +3493,14 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3340,6 +3587,14 @@ "node": ">= 0.8.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -3627,8 +3882,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/saxes": { "version": "5.0.1", @@ -3715,7 +3969,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/stack-utils": { @@ -3894,6 +4148,17 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -4107,7 +4372,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -4137,6 +4401,11 @@ "node": ">=4.2.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -4845,6 +5114,150 @@ "@cspotcode/source-map-consumer": "0.8.0" } }, + "@inquirer/checkbox": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.3.5.tgz", + "integrity": "sha512-3V0OSykTkE/38GG1DhxRGLBmqefgzRg2EK5A375zz+XEvIWfAHcac31e+zlBDPypRHxhmXc/Oh6v9eOPbH3nAg==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + } + }, + "@inquirer/confirm": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.9.tgz", + "integrity": "sha512-UF09aejxCi4Xqm6N/jJAiFXArXfi9al52AFaSD+2uIHnhZGtd1d6lIGTRMPouVSJxbGEi+HkOWSYaiEY/+szUw==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3" + } + }, + "@inquirer/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.2.tgz", + "integrity": "sha512-K8SuNX45jEFlX3EBJpu9B+S2TISzMPGXZIuJ9ME924SqbdW6Pt6fIkKvXg7mOEOKJ4WxpQsxj0UTfcL/A434Ww==", + "requires": { + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.12.13", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "@inquirer/editor": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.9.tgz", + "integrity": "sha512-5xCD7CoCh993YqXcsZPt45qkE3gl+03Yfv9vmAkptRi4nrzaUDmyhgBzndKdRG8SrKbQLBmOtztnRLGxvG/ahg==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "external-editor": "^3.1.0" + } + }, + "@inquirer/expand": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.9.tgz", + "integrity": "sha512-ymnR8qu2ie/3JpOeyZ3QSGJ+ai8qqtjBwopxLjzIZm7mZVKT6SV1sURzijkOLRgGUHwPemOfYX5biqXuqhpoBg==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "chalk": "^4.1.2" + } + }, + "@inquirer/figures": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", + "integrity": "sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==" + }, + "@inquirer/input": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.1.9.tgz", + "integrity": "sha512-1xTCHmIe48x9CG1+8glAHrVVdH+QfYhzgBUbgyoVpp5NovnXgRcjSn/SNulepxf9Ol8HDq3gzw3ZCAUr+h1Eyg==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3" + } + }, + "@inquirer/password": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.9.tgz", + "integrity": "sha512-QPtVcT12Fkn0TyuZJelR7QOtc5l1d/6pB5EfkHOivTzC6QTFxRCHl+Gx7Q3E2U/kgJeCCmDov6itDFggk9nkgA==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "ansi-escapes": "^4.3.2" + } + }, + "@inquirer/prompts": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.0.5.tgz", + "integrity": "sha512-LV2XZzc8ls4zhUzYNSpsXcnA8djOptY4G01lFzp3Bey6E1oiZMzIU25N9cb5AOwNz6pqDXpjLwRFQmLQ8h6PaQ==", + "requires": { + "@inquirer/checkbox": "^2.3.5", + "@inquirer/confirm": "^3.1.9", + "@inquirer/editor": "^2.1.9", + "@inquirer/expand": "^2.1.9", + "@inquirer/input": "^2.1.9", + "@inquirer/password": "^2.1.9", + "@inquirer/rawlist": "^2.1.9", + "@inquirer/select": "^2.3.5" + } + }, + "@inquirer/rawlist": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.9.tgz", + "integrity": "sha512-GuMmfa/v1ZJqEWSkUx1hMxzs5/0DCUP0S8IicV/wu8QrbjfBOh+7mIQgtsvh8IJ3sRkRcQ+9wh9CE9jiYqyMgw==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3", + "chalk": "^4.1.2" + } + }, + "@inquirer/select": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.3.5.tgz", + "integrity": "sha512-IyBj8oEtmdF2Gx4FJTPtEya37MD6s0KATKsHqgmls0lK7EQbhYSq9GQlcFq6cBsYe/cgQ0Fg2cCqYYPi/d/fxQ==", + "requires": { + "@inquirer/core": "^8.2.2", + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + } + }, + "@inquirer/type": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.3.tgz", + "integrity": "sha512-xTUt0NulylX27/zMx04ZYar/kr1raaiFTVvQ5feljQsiAgdm0WPj4S73/ye0fbslh+15QrIuDvfCXTek7pMY5A==" + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -4856,6 +5269,27 @@ "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } } }, "@istanbuljs/schema": { @@ -5232,11 +5666,21 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "requires": { + "@types/node": "*" + } + }, "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", - "dev": true + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/prettier": { "version": "2.4.4", @@ -5250,6 +5694,11 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, "@types/yargs": { "version": "17.0.1", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.1.tgz", @@ -5331,7 +5780,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "requires": { "type-fest": "^0.21.3" } @@ -5365,15 +5813,6 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -5552,6 +5991,11 @@ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -5564,6 +6008,11 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==" + }, "cli-table": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", @@ -5572,6 +6021,11 @@ "colors": "1.0.3" } }, + "cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==" + }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -5864,6 +6318,16 @@ "jest-message-util": "^27.5.1" } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6048,7 +6512,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -6705,16 +7168,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", @@ -6916,6 +7369,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6987,6 +7445,11 @@ "word-wrap": "~1.2.3" } }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -7192,8 +7655,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "saxes": { "version": "5.0.1", @@ -7262,7 +7724,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "stack-utils": { @@ -7396,6 +7858,14 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -7532,8 +8002,7 @@ "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" }, "typedarray-to-buffer": { "version": "3.1.5", @@ -7550,6 +8019,11 @@ "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", diff --git a/package.json b/package.json index 2c241a8..6b02eb5 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ }, "dependencies": { "@aduh95/viz.js": "^3.5.0", + "@inquirer/prompts": "^5.0.5", "ajv": "^8.10.0", "chalk": "^4.1.2", "cli-table": "^0.3.11", diff --git a/src/cmd/actor.ts b/src/cmd/actor.ts index bd6e6f1..ee751e4 100644 --- a/src/cmd/actor.ts +++ b/src/cmd/actor.ts @@ -40,8 +40,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { @@ -51,4 +50,4 @@ export const handler: BaseHandler = async (argv) => { } outputAllActors(model) -} \ No newline at end of file +} diff --git a/src/cmd/command.ts b/src/cmd/command.ts new file mode 100644 index 0000000..b2fe1ce --- /dev/null +++ b/src/cmd/command.ts @@ -0,0 +1,138 @@ +import { BaseBuilder, BaseHandler } from './util/types' +import { Yaml } from '../util/Yaml' +import { RDRA } from '../model/RDRA' +import { ErrorCollector } from '../util/ErrorCollector' +import { error } from './output/console' +import { checkFileExists, getSourcePath } from './util/options' +import { outputAllActors } from './output/actor' +import { outputAllUseCases } from './output/usecase' +import { outputAllState } from './output/state' +import { outputAllView } from './output/view' +import select from '@inquirer/select' + + +export const command = 'command' +export const desc = 'Choose a command to execute' + + +export const builder: BaseBuilder = (yargs) => + yargs + .options({ + file: { type: 'string', alias: 'f', conflicts: 'value' } + }) + .positional('value', { type: 'string' }) + .check((argv, _options) => { + const { file, value } = argv + checkFileExists(file, value) + return argv + }) + + +export const handler: BaseHandler = async (argv) => { + const { file, value } = argv + const sourcePath = getSourcePath(file, value) + let errors = [] + + // Parse YAML + const yaml = new Yaml() + const source = yaml.load(sourcePath) + errors = yaml.validate(source) + if (errors.length > 0) { + errors.forEach(err => { + error(err) + }) + process.exit(1) + } + + // RDRA Model + const model = RDRA.resolve(source) + errors = ErrorCollector.collect(model) + if (errors.length > 0) { + errors.forEach(err => { + error(err) + }) + process.exit(1) + } + + // Show commands + selectMenu(sourcePath) + +} + +const selectMenu = async (sourcePath:string) => { + const yaml = new Yaml() + const source = yaml.load(sourcePath) + const model = RDRA.resolve(source) + const layers = ['actor', 'division', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview', 'QUIT'] + const selected = await select({ + message: 'Please Select', + choices: layers.map(layer => ({ name: layer, value: layer })), + pageSize: 3 + }) + switch (selected) { + case 'actor': + outputAllActors(model) + await selectMenu(sourcePath) + break + case 'buc': + await selectMenu(sourcePath) + break + case 'activity': + await selectMenu(sourcePath) + break + case 'usecase': + outputAllUseCases(model) + await selectMenu(sourcePath) + break + case 'state': + outputAllState(model) + await selectMenu(sourcePath) + break + case 'view': + outputAllView(model) + await selectMenu(sourcePath) + break + case 'information': + await selectMenu(sourcePath) + break + case 'overview': + // const overview = new Overview(model) + // overview.output() + // break + default: + exit(); + break + } + +} + +const exit = () => { + process.exit(0) +} + +type Command = { + id: string; + name: string; + args?: string[]; + exec: () => void; +} + +type Choice = { + value: string; + command_id: string; +}; + +// const selectLayer = async () => { +// const layers = ['init', 'actor', 'division', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview', 'quit'] +// return select({ +// message: 'Please Select', +// choices: layers.map(layer => ({ name: layer, value: layer })) +// }) +// +// } + +// const layers = [ +// 'actor', 'business', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview' +// ] + +// const availableCommands: Command[] = diff --git a/src/cmd/commands/initialize.ts b/src/cmd/commands/initialize.ts new file mode 100644 index 0000000..d031666 --- /dev/null +++ b/src/cmd/commands/initialize.ts @@ -0,0 +1,22 @@ +import { input } from '@inquirer/prompts' +import { RDRA } from '../../model/RDRA' +import { Overview } from '../../model/actor/Overview' +import { Actor } from '../../model/actor/Actor' +import { Yaml } from '../../util/Yaml' + +export const initialize = async (sourcePath: string) => { + const business = await input({ message: 'ビジネス領域を入力してください' }) + const system = await input({ message: 'システム名を入力してください' }) + const actors = await input({ message: 'システムの利用者を入力してください(カンマで複数入力)' }) + + const model = new RDRA( + Overview.create(business, system), + Actor.create( + actors.split(',') + .map((name: string) => { + return { name: name.trim() } + }) + ) + ) + Yaml.export(sourcePath, model.toJSON()) +} diff --git a/src/cmd/graph.ts b/src/cmd/graph.ts index acf6435..b288ecb 100644 --- a/src/cmd/graph.ts +++ b/src/cmd/graph.ts @@ -48,8 +48,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { @@ -283,4 +282,4 @@ ${edges} }` fs.writeFileSync(`output/st_${group.name}.svg`, vizRenderStringSync(code)) -} \ No newline at end of file +} diff --git a/src/cmd/info.ts b/src/cmd/info.ts index 2934cdc..9ac8934 100644 --- a/src/cmd/info.ts +++ b/src/cmd/info.ts @@ -41,8 +41,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/init.ts b/src/cmd/init.ts index 789ff28..9a0b401 100644 --- a/src/cmd/init.ts +++ b/src/cmd/init.ts @@ -1,7 +1,7 @@ import { BaseBuilder, BaseHandler } from './util/types' import * as fs from 'fs' -import { heredoc } from '../util/heredoc' import { info } from './output/console' +import { initialize } from './commands/initialize' export const command = 'init' export const desc = 'Create YAML to start creating RDRA model' @@ -15,47 +15,7 @@ export const handler: BaseHandler = async (argv) => { if (fs.existsSync(path)) { path = path + '.' + new Date().toISOString().split('.')[0] } - const content = heredoc` -overview: - business: xxx会社 - system: 出退勤管理システム -actor: - - 社員 - -information: - - name: 社員 - - name: 出退勤記録 - -state: - - group: 出退勤 - value: - - name: 出勤 - usecase: - - name: 退勤する - next_state: 退勤 - - name: 退勤 - usecase: - - name: 出勤する - next_state: 出勤 - -usecase: - - name: 出勤する - information: - - 出退勤記録 - view: - - 出勤記録 - - name: 退勤する - information: - - 出退勤記録 - view: - - 退勤記録 - - name: 社員登録 - information: - - 社員 - view: - - 社員管理 - ` - fs.writeFileSync(path, content) + initialize(path) info(`File generated: ${path}`) -} \ No newline at end of file +} diff --git a/src/cmd/list.ts b/src/cmd/list.ts index cd83560..a89e18a 100644 --- a/src/cmd/list.ts +++ b/src/cmd/list.ts @@ -44,8 +44,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/state.ts b/src/cmd/state.ts index 2606793..0ba9eac 100644 --- a/src/cmd/state.ts +++ b/src/cmd/state.ts @@ -39,8 +39,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/usecase.ts b/src/cmd/usecase.ts index a49347e..8b3b96f 100644 --- a/src/cmd/usecase.ts +++ b/src/cmd/usecase.ts @@ -39,8 +39,7 @@ export const handler: UcHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { console.log(errors) @@ -58,4 +57,4 @@ export const handler: UcHandler = async (argv) => { } outputAllUseCases(model, buc) -} \ No newline at end of file +} diff --git a/src/cmd/view.ts b/src/cmd/view.ts index 806334e..03e9fb1 100644 --- a/src/cmd/view.ts +++ b/src/cmd/view.ts @@ -1,11 +1,9 @@ import { BaseBuilder, BaseHandler } from './util/types' import { checkFileExists, getSourcePath } from './util/options' import { Yaml } from '../util/Yaml' -import { br, error, info, title } from './output/console' +import { error } from './output/console' import { RDRA } from '../model/RDRA' import { ErrorCollector } from '../util/ErrorCollector' -import tableB, { table } from 'table-b' -import invariant from 'tiny-invariant' import { outputAllView } from './output/view' export const command = 'view [value]' @@ -42,8 +40,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const rdra = new RDRA() - const model = rdra.resolve(input) + const model = RDRA.resolve(input) errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { @@ -55,4 +52,4 @@ export const handler: BaseHandler = async (argv) => { // ------------------------------ // View outputAllView(model) -} \ No newline at end of file +} diff --git a/src/model/JsonSchema.ts b/src/model/JsonSchema.ts index bbcffa0..0da33cd 100644 --- a/src/model/JsonSchema.ts +++ b/src/model/JsonSchema.ts @@ -37,7 +37,6 @@ export type JsonSchemaInformationValue = { variation?: string } - export type JsonSchemaUsecase = { name: string view: string[] | null diff --git a/src/model/RDRA.ts b/src/model/RDRA.ts index a389ee9..a2f86db 100644 --- a/src/model/RDRA.ts +++ b/src/model/RDRA.ts @@ -8,7 +8,13 @@ import { Variation } from './variation/Variation' import { Condition } from './condition/Condition' import { StateTransition } from './state/StateTransition' import { Business } from './business/Business' -import { JsonSchema } from './JsonSchema' +import { + JsonSchema, + JsonSchemaActor, JsonSchemaBusiness, JsonSchemaCondition, + JsonSchemaExternalActor, + JsonSchemaInformation, + JsonSchemaOverview, JsonSchemaState, JsonSchemaUsecase, JsonSchemaVariation +} from './JsonSchema' export type ErrorReport = string[] @@ -27,7 +33,40 @@ export type RelationalModel = { export class RDRA { - resolve(source: JsonSchema): RelationalModel { + private _overview: Overview + private _actor: Actor + + constructor(overview: Overview, actor: Actor) { + this._overview = overview + this._actor = actor + } + + get overview(): Overview { + return this._overview + } + + get actor(): Actor { + return this._actor + } + + toJSON(): JsonSchema { + return { + overview: { + business: this._overview.business, + system: this._overview.system, + }, + actor: this._actor.toJSON(), + external_actor: [], + information: [], + usecase: [], + business: [], + state: [], + variation: [], + condition: [], + } + } + + static resolve(source: JsonSchema): RelationalModel { const overview = Overview.resolve(source.overview) // -------------------------------------- diff --git a/src/model/actor/Actor.ts b/src/model/actor/Actor.ts index c89f40a..b7090a5 100644 --- a/src/model/actor/Actor.ts +++ b/src/model/actor/Actor.ts @@ -14,8 +14,23 @@ export class Actor { this._instances = instances } + public toJSON(): (JsonSchemaActor | string)[] { + return this._instances.map(it => { + if (it.description == undefined) return it.name + return { + name: it.name, + description: it.description + } + }) + } + + static create(args : { name: string, description?: string}[]): Actor { + const instances = args.map(it => new ActorInstance(it.name, it.description)) + return new Actor(instances) + } + static resolve(source: JsonSchemaActor[]): Actor { - const actor = new Actor(source.map(it => new ActorInstance(it.name, it.description ?? null))) + const actor = new Actor(source.map(it => new ActorInstance(it.name, it.description ?? undefined))) const counted = actor._names.countValues() counted.forEach((value, key) => { if (value > 1) actor._errors.push(`アクター[${key}]が重複しています。`) @@ -44,9 +59,9 @@ export class Actor { export class ActorInstance { private readonly _name: string - private readonly _description: string | null + private readonly _description?: string - constructor(name: string, description: string | null) { + constructor(name: string, description?: string) { this._name = name this._description = description } @@ -55,7 +70,7 @@ export class ActorInstance { return this._name } - get description(): string | null { + get description(): string | undefined { return this._description } -} \ No newline at end of file +} diff --git a/src/model/actor/Overview.ts b/src/model/actor/Overview.ts index f46bf4c..6ad626e 100644 --- a/src/model/actor/Overview.ts +++ b/src/model/actor/Overview.ts @@ -12,6 +12,10 @@ export class Overview { this._system = system } + static create(business: string, system: string): Overview { + return new Overview(business, system) + } + static resolve(source: JsonSchemaOverview): Overview { return new Overview(source.business, source.system) } diff --git a/src/model/business/Business.ts b/src/model/business/Business.ts index f5c4615..4868328 100644 --- a/src/model/business/Business.ts +++ b/src/model/business/Business.ts @@ -1,6 +1,6 @@ import '../array.extensions' import invariant from 'tiny-invariant' -import { JsonSchemaBusiness, SourceBucJSON } from '../JsonSchema' +import { JsonSchemaBusiness } from '../JsonSchema' import { ErrorReport } from '../RDRA' import { Actor } from '../actor/Actor' import { Usecase } from '../usecase/Usecase' @@ -165,4 +165,4 @@ export class Activity { get usecase(): string[] | null { return this._usecase } -} \ No newline at end of file +} diff --git a/src/util/Yaml.ts b/src/util/Yaml.ts index f4b6417..36b7f0d 100644 --- a/src/util/Yaml.ts +++ b/src/util/Yaml.ts @@ -2,6 +2,7 @@ import * as fs from 'fs' import * as schema from '../schema.json' import * as YAML from 'yaml' import Ajv, { ValidateFunction } from 'ajv/dist/2020' +import { JsonSchema } from '../model/JsonSchema' export class Yaml { @@ -17,6 +18,11 @@ export class Yaml { return YAML.parse(source) } + static export(output: string, source: JsonSchema): void { + const content = YAML.stringify(source) + fs.writeFileSync(output, content) + } + validate(input: any): string[] { this._validate(input) @@ -28,4 +34,4 @@ export class Yaml { } return errors } -} \ No newline at end of file +} From 571b896f15973a6459d023726c9bb78141d17896 Mon Sep 17 00:00:00 2001 From: "go.tanaka" Date: Tue, 18 Jun 2024 16:09:29 +0900 Subject: [PATCH 2/3] add commands for actor --- src/cmd/actor.ts | 7 ++- src/cmd/command.ts | 84 +++++++----------------------- src/cmd/commands/actor/create.ts | 20 ++++++++ src/cmd/commands/actor/delete.ts | 18 +++++++ src/cmd/commands/actor/index.ts | 88 ++++++++++++++++++++++++++++++++ src/cmd/commands/actor/list.ts | 13 +++++ src/cmd/commands/actor/show.ts | 2 + src/cmd/commands/actor/update.ts | 26 ++++++++++ src/cmd/graph.ts | 7 ++- src/cmd/info.ts | 7 ++- src/cmd/init.ts | 2 - src/cmd/list.ts | 7 ++- src/cmd/state.ts | 7 ++- src/cmd/usecase.ts | 7 ++- src/cmd/view.ts | 7 ++- src/model/RDRA.ts | 27 +++++++--- src/model/actor/Actor.ts | 27 ++++++++++ src/util/Yaml.ts | 17 +++--- 18 files changed, 264 insertions(+), 109 deletions(-) create mode 100644 src/cmd/commands/actor/create.ts create mode 100644 src/cmd/commands/actor/delete.ts create mode 100644 src/cmd/commands/actor/index.ts create mode 100644 src/cmd/commands/actor/list.ts create mode 100644 src/cmd/commands/actor/show.ts create mode 100644 src/cmd/commands/actor/update.ts diff --git a/src/cmd/actor.ts b/src/cmd/actor.ts index ee751e4..4eaa664 100644 --- a/src/cmd/actor.ts +++ b/src/cmd/actor.ts @@ -29,9 +29,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -40,7 +39,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/command.ts b/src/cmd/command.ts index b2fe1ce..d6b3ad6 100644 --- a/src/cmd/command.ts +++ b/src/cmd/command.ts @@ -1,14 +1,10 @@ import { BaseBuilder, BaseHandler } from './util/types' import { Yaml } from '../util/Yaml' -import { RDRA } from '../model/RDRA' import { ErrorCollector } from '../util/ErrorCollector' import { error } from './output/console' import { checkFileExists, getSourcePath } from './util/options' -import { outputAllActors } from './output/actor' -import { outputAllUseCases } from './output/usecase' -import { outputAllState } from './output/state' -import { outputAllView } from './output/view' import select from '@inquirer/select' +import { selectActorMenu } from './commands/actor' export const command = 'command' @@ -34,9 +30,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const source = yaml.load(sourcePath) - errors = yaml.validate(source) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -44,8 +39,7 @@ export const handler: BaseHandler = async (argv) => { process.exit(1) } - // RDRA Model - const model = RDRA.resolve(source) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { @@ -59,80 +53,40 @@ export const handler: BaseHandler = async (argv) => { } -const selectMenu = async (sourcePath:string) => { - const yaml = new Yaml() - const source = yaml.load(sourcePath) - const model = RDRA.resolve(source) - const layers = ['actor', 'division', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview', 'QUIT'] +export const selectMenu = async (sourcePath: string) => { + const menu = ['actor', 'division', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview', 'Quit'] const selected = await select({ - message: 'Please Select', - choices: layers.map(layer => ({ name: layer, value: layer })), - pageSize: 3 - }) + message: 'Please Select', + choices: menu.map(layer => ({ name: layer, value: layer })), + pageSize: 5, + }, + { + clearPromptOnDone: true, + }) switch (selected) { case 'actor': - outputAllActors(model) - await selectMenu(sourcePath) + await selectActorMenu(sourcePath) + break + case 'division': break case 'buc': - await selectMenu(sourcePath) break case 'activity': - await selectMenu(sourcePath) break case 'usecase': - outputAllUseCases(model) - await selectMenu(sourcePath) break case 'state': - outputAllState(model) - await selectMenu(sourcePath) break case 'view': - outputAllView(model) - await selectMenu(sourcePath) break case 'information': - await selectMenu(sourcePath) break case 'overview': - // const overview = new Overview(model) - // overview.output() - // break + break default: - exit(); + process.exit(0) break } + await selectMenu(sourcePath) } - -const exit = () => { - process.exit(0) -} - -type Command = { - id: string; - name: string; - args?: string[]; - exec: () => void; -} - -type Choice = { - value: string; - command_id: string; -}; - -// const selectLayer = async () => { -// const layers = ['init', 'actor', 'division', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview', 'quit'] -// return select({ -// message: 'Please Select', -// choices: layers.map(layer => ({ name: layer, value: layer })) -// }) -// -// } - -// const layers = [ -// 'actor', 'business', 'buc', 'activity', 'usecase', 'state', 'view', 'information', 'overview' -// ] - -// const availableCommands: Command[] = diff --git a/src/cmd/commands/actor/create.ts b/src/cmd/commands/actor/create.ts new file mode 100644 index 0000000..7d4be6d --- /dev/null +++ b/src/cmd/commands/actor/create.ts @@ -0,0 +1,20 @@ +import { input } from '@inquirer/prompts' +import { Yaml } from '../../../util/Yaml' +import { RDRA } from '../../../model/RDRA' + +export const createActor = async (sourcePath: string) => { + const name = await input({ message: '名前を入力してください' }, { clearPromptOnDone: true }) + const description = await input({ message: '説明を入力してください' }, { clearPromptOnDone: true }) + + const yaml = new Yaml(sourcePath) + const rdra = RDRA.from(yaml.getModel()) + const errors = rdra.addActor(name, description) + if (errors.length > 0) { + errors.forEach((error) => { + console.log(error) + }) + return + } + Yaml.export(sourcePath, rdra.toJSON()) + console.log('Actorを追加しました。名前:' + name, '説明:' + description) +} diff --git a/src/cmd/commands/actor/delete.ts b/src/cmd/commands/actor/delete.ts new file mode 100644 index 0000000..9b4326f --- /dev/null +++ b/src/cmd/commands/actor/delete.ts @@ -0,0 +1,18 @@ +import { list } from './list' +import { Yaml } from '../../../util/Yaml' +import { RDRA } from '../../../model/RDRA' + +export const deleteActor = async (sourcePath: string) => { + const selected = await list(sourcePath) + const yaml = new Yaml(sourcePath) + const rdra = RDRA.from(yaml.getModel()) + const errors = rdra.deleteActor(selected) + if (errors.length > 0) { + errors.forEach((error) => { + console.log(error) + }) + return + } + Yaml.export(sourcePath, rdra.toJSON()) + console.log('Actorを削除しました。名前:' + selected) +} diff --git a/src/cmd/commands/actor/index.ts b/src/cmd/commands/actor/index.ts new file mode 100644 index 0000000..eeb8f7c --- /dev/null +++ b/src/cmd/commands/actor/index.ts @@ -0,0 +1,88 @@ +import { createActor } from './create' +import select from '@inquirer/select' +import { exit, selectMenu } from '../../command' +import { Yaml } from '../../../util/Yaml' +import { Actor } from '../../../model/actor/Actor' +import { showActor } from './show' +import { updateActor } from './update' +import { deleteActor } from './delete' + +export const actorCommands = { + create: { + command: createActor, + description: 'Create a new actor', + } + , + show: { + command: showActor, + description: 'Show an actor', + }, + update: { + command: updateActor, + description: 'Update an actor', + }, + delete: { + command: deleteActor, + description: 'Delete an actor', + } +} + +class Row { + constructor(public name: string, public description: string | undefined) { + this.name = name as string + this.description = description + } +} + +function tableView(actor: Actor) { + console.table(actor.instances.map(it => new Row(it.name, it.description))) +} + +export const selectActorMenu = async (sourcePath: string) => { + const yaml = new Yaml(sourcePath) + const actor = yaml.getModel().actor + tableView(actor) + + const menu = [actorCommands.create.description] + if (actor.instances.length > 0) { + menu.push( + actorCommands.show.description, + actorCommands.update.description, + actorCommands.delete.description + ) + } + menu.push('Go back', 'Quit') + + const selected = await select({ + message: 'Please Select', + choices: menu.map(m => ({ name: m, value: m })), + pageSize: 3 + }, + { + clearPromptOnDone: true, + }) + switch (selected) { + case actorCommands.create.description: + await actorCommands.create.command(sourcePath) + await selectActorMenu(sourcePath) + break + case actorCommands.show.description: + await actorCommands.show.command(sourcePath) + await selectActorMenu(sourcePath) + break + case actorCommands.update.description: + await actorCommands.update.command(sourcePath) + await selectActorMenu(sourcePath) + break + case actorCommands.delete.description: + await actorCommands.delete.command(sourcePath) + await selectActorMenu(sourcePath) + break + case 'Go back': + await selectMenu(sourcePath) + break + default: + process.exit(0) + break + } +} diff --git a/src/cmd/commands/actor/list.ts b/src/cmd/commands/actor/list.ts new file mode 100644 index 0000000..ee4b2cb --- /dev/null +++ b/src/cmd/commands/actor/list.ts @@ -0,0 +1,13 @@ +import select from '@inquirer/select' +import { Yaml } from '../../../util/Yaml' + +export const list = (sourcePath: string) => { + return select({ + message: 'Select an actor', + choices: new Yaml(sourcePath).getModel().actor.names.map(it => ({ name: it, value: it })), + }, + { + clearPromptOnDone: true, + }) +} + diff --git a/src/cmd/commands/actor/show.ts b/src/cmd/commands/actor/show.ts new file mode 100644 index 0000000..737015d --- /dev/null +++ b/src/cmd/commands/actor/show.ts @@ -0,0 +1,2 @@ + +export const showActor = async (sourcePath: string) => {} diff --git a/src/cmd/commands/actor/update.ts b/src/cmd/commands/actor/update.ts new file mode 100644 index 0000000..3bc0811 --- /dev/null +++ b/src/cmd/commands/actor/update.ts @@ -0,0 +1,26 @@ +import { input } from '@inquirer/prompts' +import { Yaml } from '../../../util/Yaml' +import { RDRA } from '../../../model/RDRA' +import { list } from './list' + +export const updateActor = async (sourcePath: string) => { + const selected = await list(sourcePath) + const newName = await input({ message: '名前を入力してください' }, { clearPromptOnDone: true }) + const newDescription = await input({ message: '説明を入力してください' }, { clearPromptOnDone: true }) + if (!newName) { + console.log('名前は必須です。') + return + } + + const yaml = new Yaml(sourcePath) + const rdra = RDRA.from(yaml.getModel()) + const errors = rdra.updateActor(selected, newName, newDescription) + if (errors.length > 0) { + errors.forEach((error) => { + console.log(error) + }) + return + } + Yaml.export(sourcePath, rdra.toJSON()) + console.log('Actorを更新しました。名前:' + newName, '説明:' + newDescription) +} diff --git a/src/cmd/graph.ts b/src/cmd/graph.ts index b288ecb..ff2ebee 100644 --- a/src/cmd/graph.ts +++ b/src/cmd/graph.ts @@ -37,9 +37,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -48,7 +47,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/info.ts b/src/cmd/info.ts index 9ac8934..324583a 100644 --- a/src/cmd/info.ts +++ b/src/cmd/info.ts @@ -30,9 +30,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -41,7 +40,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/init.ts b/src/cmd/init.ts index 9a0b401..d56622b 100644 --- a/src/cmd/init.ts +++ b/src/cmd/init.ts @@ -1,6 +1,5 @@ import { BaseBuilder, BaseHandler } from './util/types' import * as fs from 'fs' -import { info } from './output/console' import { initialize } from './commands/initialize' export const command = 'init' @@ -17,5 +16,4 @@ export const handler: BaseHandler = async (argv) => { } initialize(path) - info(`File generated: ${path}`) } diff --git a/src/cmd/list.ts b/src/cmd/list.ts index a89e18a..0bbef9f 100644 --- a/src/cmd/list.ts +++ b/src/cmd/list.ts @@ -33,9 +33,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -44,7 +43,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/state.ts b/src/cmd/state.ts index 0ba9eac..fdec092 100644 --- a/src/cmd/state.ts +++ b/src/cmd/state.ts @@ -28,9 +28,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -39,7 +38,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/cmd/usecase.ts b/src/cmd/usecase.ts index 8b3b96f..b661c10 100644 --- a/src/cmd/usecase.ts +++ b/src/cmd/usecase.ts @@ -30,16 +30,15 @@ export const handler: UcHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { console.log(errors) process.exit(1) } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { console.log(errors) diff --git a/src/cmd/view.ts b/src/cmd/view.ts index 03e9fb1..69dc501 100644 --- a/src/cmd/view.ts +++ b/src/cmd/view.ts @@ -29,9 +29,8 @@ export const handler: BaseHandler = async (argv) => { let errors = [] // Parse YAML - const yaml = new Yaml() - const input = yaml.load(sourcePath) - errors = yaml.validate(input) + const yaml = new Yaml(sourcePath) + errors = yaml.validate() if (errors.length > 0) { errors.forEach(err => { error(err) @@ -40,7 +39,7 @@ export const handler: BaseHandler = async (argv) => { } // RDRA Model - const model = RDRA.resolve(input) + const model = yaml.getModel() errors = ErrorCollector.collect(model) if (errors.length > 0) { errors.forEach(err => { diff --git a/src/model/RDRA.ts b/src/model/RDRA.ts index a2f86db..4add993 100644 --- a/src/model/RDRA.ts +++ b/src/model/RDRA.ts @@ -8,13 +8,7 @@ import { Variation } from './variation/Variation' import { Condition } from './condition/Condition' import { StateTransition } from './state/StateTransition' import { Business } from './business/Business' -import { - JsonSchema, - JsonSchemaActor, JsonSchemaBusiness, JsonSchemaCondition, - JsonSchemaExternalActor, - JsonSchemaInformation, - JsonSchemaOverview, JsonSchemaState, JsonSchemaUsecase, JsonSchemaVariation -} from './JsonSchema' +import { JsonSchema } from './JsonSchema' export type ErrorReport = string[] @@ -41,6 +35,25 @@ export class RDRA { this._actor = actor } + static from(model: RelationalModel): RDRA { + return new RDRA(model.overview, model.actor) + } + + addActor(name: string, description?: string): string [] { + this._actor = this._actor.add(name, description) + return this._actor.errors + } + + updateActor(oldName: string, newName: string, description?: string): string [] { + this._actor = this._actor.update(oldName, newName, description) + return this._actor.errors + } + + deleteActor(name: string): string [] { + this._actor = this._actor.delete(name) + return this._actor.errors + } + get overview(): Overview { return this._overview } diff --git a/src/model/actor/Actor.ts b/src/model/actor/Actor.ts index b7090a5..e88e3b5 100644 --- a/src/model/actor/Actor.ts +++ b/src/model/actor/Actor.ts @@ -29,6 +29,33 @@ export class Actor { return new Actor(instances) } + add(name: string, description?: string) { + if (this._names.includes(name)) { + this._errors.push(`アクター[${name}]が重複しています。`) + return this + } + + const newInstance = new ActorInstance(name, description) + const instances = this._instances + instances.push(newInstance) + return new Actor(instances) + } + + update(oldName: string, newName: string, description?: string) { + const newInstances = this._instances.map(it => { + if (it.name == oldName) { + return new ActorInstance(newName, description) + } + return new ActorInstance(it.name, it.description) + }) + return new Actor(newInstances) + } + + delete(name: string) { + const newInstances = this._instances.filter(it => it.name != name) + return new Actor(newInstances) + } + static resolve(source: JsonSchemaActor[]): Actor { const actor = new Actor(source.map(it => new ActorInstance(it.name, it.description ?? undefined))) const counted = actor._names.countValues() diff --git a/src/util/Yaml.ts b/src/util/Yaml.ts index 36b7f0d..0ce5ff5 100644 --- a/src/util/Yaml.ts +++ b/src/util/Yaml.ts @@ -3,19 +3,18 @@ import * as schema from '../schema.json' import * as YAML from 'yaml' import Ajv, { ValidateFunction } from 'ajv/dist/2020' import { JsonSchema } from '../model/JsonSchema' +import { RDRA, RelationalModel } from '../model/RDRA' export class Yaml { private readonly _validate: ValidateFunction + private readonly _source: any - constructor() { + constructor(sourcePath: string) { const ajv = new Ajv({ allowUnionTypes: true }) this._validate = ajv.compile(schema) - } - - load(sourcePath: string): any { const source = fs.readFileSync(sourcePath, 'utf-8') - return YAML.parse(source) + this._source = YAML.parse(source) } static export(output: string, source: JsonSchema): void { @@ -23,8 +22,8 @@ export class Yaml { fs.writeFileSync(output, content) } - validate(input: any): string[] { - this._validate(input) + validate(): string[] { + this._validate(this._source) let errors:string[] = [] if (this._validate.errors) { @@ -34,4 +33,8 @@ export class Yaml { } return errors } + + getModel() : RelationalModel{ + return RDRA.resolve(this._source) + } } From beef0ffd47ed86b163f9a8eca3f24c99f6e48bc7 Mon Sep 17 00:00:00 2001 From: "go.tanaka" Date: Tue, 18 Jun 2024 16:33:14 +0900 Subject: [PATCH 3/3] refactoring --- src/cmd/commands/actor/create.ts | 16 ++++++++-------- src/cmd/commands/actor/delete.ts | 16 ++++++++-------- src/cmd/commands/actor/index.ts | 2 +- src/cmd/commands/actor/update.ts | 16 ++++++++-------- src/model/RDRA.ts | 9 +++------ src/util/ErrorCollector.ts | 19 +++++++++++++++++-- 6 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/cmd/commands/actor/create.ts b/src/cmd/commands/actor/create.ts index 7d4be6d..e38a55e 100644 --- a/src/cmd/commands/actor/create.ts +++ b/src/cmd/commands/actor/create.ts @@ -1,6 +1,7 @@ import { input } from '@inquirer/prompts' import { Yaml } from '../../../util/Yaml' import { RDRA } from '../../../model/RDRA' +import { ErrorCollector } from '../../../util/ErrorCollector' export const createActor = async (sourcePath: string) => { const name = await input({ message: '名前を入力してください' }, { clearPromptOnDone: true }) @@ -8,13 +9,12 @@ export const createActor = async (sourcePath: string) => { const yaml = new Yaml(sourcePath) const rdra = RDRA.from(yaml.getModel()) - const errors = rdra.addActor(name, description) - if (errors.length > 0) { - errors.forEach((error) => { - console.log(error) - }) - return - } - Yaml.export(sourcePath, rdra.toJSON()) + rdra.addActor(name, description) + + const json = rdra.toJSON(); + const err = ErrorCollector.printJsonErrors(json) + if (err) return + + Yaml.export(sourcePath, json) console.log('Actorを追加しました。名前:' + name, '説明:' + description) } diff --git a/src/cmd/commands/actor/delete.ts b/src/cmd/commands/actor/delete.ts index 9b4326f..6ccb135 100644 --- a/src/cmd/commands/actor/delete.ts +++ b/src/cmd/commands/actor/delete.ts @@ -1,18 +1,18 @@ import { list } from './list' import { Yaml } from '../../../util/Yaml' import { RDRA } from '../../../model/RDRA' +import { ErrorCollector } from '../../../util/ErrorCollector' export const deleteActor = async (sourcePath: string) => { const selected = await list(sourcePath) const yaml = new Yaml(sourcePath) const rdra = RDRA.from(yaml.getModel()) - const errors = rdra.deleteActor(selected) - if (errors.length > 0) { - errors.forEach((error) => { - console.log(error) - }) - return - } - Yaml.export(sourcePath, rdra.toJSON()) + rdra.deleteActor(selected) + + const json = rdra.toJSON() + const err = ErrorCollector.printJsonErrors(json) + if (err) return + + Yaml.export(sourcePath, json) console.log('Actorを削除しました。名前:' + selected) } diff --git a/src/cmd/commands/actor/index.ts b/src/cmd/commands/actor/index.ts index eeb8f7c..6e7ad0d 100644 --- a/src/cmd/commands/actor/index.ts +++ b/src/cmd/commands/actor/index.ts @@ -1,6 +1,6 @@ import { createActor } from './create' import select from '@inquirer/select' -import { exit, selectMenu } from '../../command' +import { selectMenu } from '../../command' import { Yaml } from '../../../util/Yaml' import { Actor } from '../../../model/actor/Actor' import { showActor } from './show' diff --git a/src/cmd/commands/actor/update.ts b/src/cmd/commands/actor/update.ts index 3bc0811..58f7779 100644 --- a/src/cmd/commands/actor/update.ts +++ b/src/cmd/commands/actor/update.ts @@ -2,6 +2,7 @@ import { input } from '@inquirer/prompts' import { Yaml } from '../../../util/Yaml' import { RDRA } from '../../../model/RDRA' import { list } from './list' +import { ErrorCollector } from '../../../util/ErrorCollector' export const updateActor = async (sourcePath: string) => { const selected = await list(sourcePath) @@ -14,13 +15,12 @@ export const updateActor = async (sourcePath: string) => { const yaml = new Yaml(sourcePath) const rdra = RDRA.from(yaml.getModel()) - const errors = rdra.updateActor(selected, newName, newDescription) - if (errors.length > 0) { - errors.forEach((error) => { - console.log(error) - }) - return - } - Yaml.export(sourcePath, rdra.toJSON()) + rdra.updateActor(selected, newName, newDescription) + + const json = rdra.toJSON() + const err = ErrorCollector.printJsonErrors(json) + if (err) return + + Yaml.export(sourcePath, json) console.log('Actorを更新しました。名前:' + newName, '説明:' + newDescription) } diff --git a/src/model/RDRA.ts b/src/model/RDRA.ts index 4add993..658a0c6 100644 --- a/src/model/RDRA.ts +++ b/src/model/RDRA.ts @@ -39,19 +39,16 @@ export class RDRA { return new RDRA(model.overview, model.actor) } - addActor(name: string, description?: string): string [] { + addActor(name: string, description?: string) { this._actor = this._actor.add(name, description) - return this._actor.errors } - updateActor(oldName: string, newName: string, description?: string): string [] { + updateActor(oldName: string, newName: string, description?: string) { this._actor = this._actor.update(oldName, newName, description) - return this._actor.errors } - deleteActor(name: string): string [] { + deleteActor(name: string) { this._actor = this._actor.delete(name) - return this._actor.errors } get overview(): Overview { diff --git a/src/util/ErrorCollector.ts b/src/util/ErrorCollector.ts index 3116be9..68ae8db 100644 --- a/src/util/ErrorCollector.ts +++ b/src/util/ErrorCollector.ts @@ -1,5 +1,5 @@ import invariant from 'tiny-invariant' -import { RelationalModel } from '../model/RDRA' +import { RDRA, RelationalModel } from '../model/RDRA' import { Actor } from '../model/actor/Actor' import { ExternalActor } from '../model/actor/ExternalActor' import { State } from '../model/state/State' @@ -9,9 +9,24 @@ import { Variation } from '../model/variation/Variation' import { Condition } from '../model/condition/Condition' import { Business } from '../model/business/Business' import { Usecase } from '../model/usecase/Usecase' +import { JsonSchema } from '../model/JsonSchema' +import { error } from '../cmd/output/console' export class ErrorCollector { + static printJsonErrors(json: JsonSchema): boolean { + const model = RDRA.resolve(json) + const errors = ErrorCollector.collect(model) + if (errors.length > 0) { + errors.forEach(err => { + error(err + '\n') + }) + return true + } + // no errors + return false + } + static collect(model: RelationalModel): string[] { let errors: string[] = [] if (this.hasError(model.actor)) { @@ -62,4 +77,4 @@ export class ErrorCollector { return source.errors.length > 0 } -} \ No newline at end of file +}