diff --git a/Dockerfile b/Dockerfile
index d792d2a6563485a1bc2b8fc66023ffecb81f7357..cebc553b54bf5073066084c08d96bcbc76741957 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,6 +19,7 @@ COPY --from=deps /app/refine/node_modules ./node_modules
 
 COPY . .
 
+ENV EXPRESS_PUBLIC_API_URL=/api
 RUN npm run build
 
 FROM base AS runner
diff --git a/openapitools.json b/openapitools.json
new file mode 100644
index 0000000000000000000000000000000000000000..9841a49bcea23d365657ae97cbcc4fcd77580aa3
--- /dev/null
+++ b/openapitools.json
@@ -0,0 +1,7 @@
+{
+  "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
+  "spaces": 2,
+  "generator-cli": {
+    "version": "7.3.0"
+  }
+}
diff --git a/package-lock.json b/package-lock.json
index e46bc7d74278e22e49acef31cf5b1dc780545b7b..c8fdb756615b47af98738ae08c9fbfa398118996 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
         "@mui/lab": "^5.0.0-alpha.85",
         "@mui/material": "^5.8.6",
         "@mui/x-data-grid": "^6.6.0",
-        "@refinedev/cli": "^2.16.24",
+        "@refinedev/cli": "^2.16.1",
         "@refinedev/core": "^4.47.1",
         "@refinedev/devtools": "^1.1.32",
         "@refinedev/inferencer": "^4.5.20",
@@ -31,6 +31,7 @@
         "react-dom": "^18.0.0"
       },
       "devDependencies": {
+        "@openapitools/openapi-generator-cli": "^2.9.0",
         "@types/node": "^18.0.0",
         "@types/react": "^18.0.0",
         "@types/react-dom": "^18.0.0",
@@ -1152,6 +1153,15 @@
         "@jridgewell/sourcemap-codec": "^1.4.14"
       }
     },
+    "node_modules/@lukeed/csprng": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
+      "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/@mui/base": {
       "version": "5.0.0-beta.34",
       "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.34.tgz",
@@ -1462,6 +1472,91 @@
         "react-dom": "^17.0.0 || ^18.0.0"
       }
     },
+    "node_modules/@nestjs/axios": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.1.tgz",
+      "integrity": "sha512-VlOZhAGDmOoFdsmewn8AyClAdGpKXQQaY1+3PGB+g6ceurGIdTxZgRX3VXc1T6Zs60PedWjg3A82TDOB05mrzQ==",
+      "dev": true,
+      "peerDependencies": {
+        "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0",
+        "axios": "^1.3.1",
+        "reflect-metadata": "^0.1.12",
+        "rxjs": "^6.0.0 || ^7.0.0"
+      }
+    },
+    "node_modules/@nestjs/common": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.0.tgz",
+      "integrity": "sha512-DGv34UHsZBxCM3H5QGE2XE/+oLJzz5+714JQjBhjD9VccFlQs3LRxo/epso4l7nJIiNlZkPyIUC8WzfU/5RTsQ==",
+      "dev": true,
+      "dependencies": {
+        "iterare": "1.2.1",
+        "tslib": "2.6.2",
+        "uid": "2.0.2"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/nest"
+      },
+      "peerDependencies": {
+        "class-transformer": "*",
+        "class-validator": "*",
+        "reflect-metadata": "^0.1.12",
+        "rxjs": "^7.1.0"
+      },
+      "peerDependenciesMeta": {
+        "class-transformer": {
+          "optional": true
+        },
+        "class-validator": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@nestjs/core": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.0.tgz",
+      "integrity": "sha512-N06P5ncknW/Pm8bj964WvLIZn2gNhHliCBoAO1LeBvNImYkecqKcrmLbY49Fa1rmMfEM3MuBHeDys3edeuYAOA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "dependencies": {
+        "@nuxtjs/opencollective": "0.3.2",
+        "fast-safe-stringify": "2.1.1",
+        "iterare": "1.2.1",
+        "path-to-regexp": "3.2.0",
+        "tslib": "2.6.2",
+        "uid": "2.0.2"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/nest"
+      },
+      "peerDependencies": {
+        "@nestjs/common": "^10.0.0",
+        "@nestjs/microservices": "^10.0.0",
+        "@nestjs/platform-express": "^10.0.0",
+        "@nestjs/websockets": "^10.0.0",
+        "reflect-metadata": "^0.1.12",
+        "rxjs": "^7.1.0"
+      },
+      "peerDependenciesMeta": {
+        "@nestjs/microservices": {
+          "optional": true
+        },
+        "@nestjs/platform-express": {
+          "optional": true
+        },
+        "@nestjs/websockets": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@nestjs/core/node_modules/path-to-regexp": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz",
+      "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==",
+      "dev": true
+    },
     "node_modules/@next/env": {
       "version": "13.5.6",
       "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz",
@@ -1634,10 +1729,104 @@
         "node": ">= 8"
       }
     },
+    "node_modules/@nuxtjs/opencollective": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz",
+      "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "consola": "^2.15.0",
+        "node-fetch": "^2.6.1"
+      },
+      "bin": {
+        "opencollective": "bin/opencollective.js"
+      },
+      "engines": {
+        "node": ">=8.0.0",
+        "npm": ">=5.0.0"
+      }
+    },
+    "node_modules/@openapitools/openapi-generator-cli": {
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.9.0.tgz",
+      "integrity": "sha512-KQpftKeiMoH5aEI/amOVLFGkGeT3DyA7Atj7v7l8xT3O9xnIUpoDmMg0WBTEh+NHxEwEAITQNDzr+JLjkXVaKw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "dependencies": {
+        "@nestjs/axios": "3.0.1",
+        "@nestjs/common": "10.3.0",
+        "@nestjs/core": "10.3.0",
+        "@nuxtjs/opencollective": "0.3.2",
+        "axios": "1.6.5",
+        "chalk": "4.1.2",
+        "commander": "8.3.0",
+        "compare-versions": "4.1.4",
+        "concurrently": "6.5.1",
+        "console.table": "0.10.0",
+        "fs-extra": "10.1.0",
+        "glob": "7.2.3",
+        "inquirer": "8.2.6",
+        "lodash": "4.17.21",
+        "reflect-metadata": "0.1.13",
+        "rxjs": "7.8.1",
+        "tslib": "2.6.2"
+      },
+      "bin": {
+        "openapi-generator-cli": "main.js"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/openapi_generator"
+      }
+    },
+    "node_modules/@openapitools/openapi-generator-cli/node_modules/axios": {
+      "version": "1.6.5",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
+      "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+      "dev": true,
+      "dependencies": {
+        "follow-redirects": "^1.15.4",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "node_modules/@openapitools/openapi-generator-cli/node_modules/commander": {
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+      "dev": true,
+      "engines": {
+        "node": ">= 12"
+      }
+    },
+    "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/@ory/client": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/@ory/client/-/client-1.6.1.tgz",
-      "integrity": "sha512-CboARAoTtXOFx1fVVPN/IezU5S6uEOtSvI8Y6LkXD6NKiMzJdc9Ezt8m807toI6lCz1Gc+DCD1OX6gnHnMjb4g==",
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/@ory/client/-/client-1.6.2.tgz",
+      "integrity": "sha512-eeSkFZsrX/hLaariBg2I9PQWueE9IVAV3Tps5UE7CYEvrGziFB1zdv8joQDGMss5O3Yv/CSlSf4rOwTeENDqBg==",
       "dependencies": {
         "axios": "^1.6.1"
       }
@@ -1755,16 +1944,14 @@
       "integrity": "sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ=="
     },
     "node_modules/@refinedev/cli": {
-      "version": "2.16.24",
-      "resolved": "https://registry.npmjs.org/@refinedev/cli/-/cli-2.16.24.tgz",
-      "integrity": "sha512-xN7xJMbA8tyHCIvTR6ZuvMNEbEDzjGH3XF4CKhRql7k5Q8TCpWhmUZ2cFHEIa5RpdYaboS7lFAdwwm2uW0rLVQ==",
+      "version": "2.16.1",
+      "resolved": "https://registry.npmjs.org/@refinedev/cli/-/cli-2.16.1.tgz",
+      "integrity": "sha512-1NLXmLqfqsxXVWWgCXshqkgD/5RBhg6UskKHS9gVFTrUL8DinZx+HGbygXfoLraJyC/6Ybh5krRFTE7cAdAY1g==",
       "dependencies": {
-        "@refinedev/devtools-server": "1.1.24",
+        "@refinedev/devtools-server": "1.1.6",
         "boxen": "^5.1.2",
         "cardinal": "^2.1.1",
-        "center-align": "1.0.1",
         "chalk": "^4.1.2",
-        "cli-table3": "^0.6.3",
         "commander": "9.4.1",
         "conf": "^10.2.0",
         "dedent": "^0.7.0",
@@ -1778,19 +1965,18 @@
         "gray-matter": "^4.0.3",
         "handlebars": "^4.7.7",
         "http-proxy-middleware": "^2.0.6",
+        "ink": "^3.2.0",
+        "ink-markdown": "^1.0.1",
+        "ink-table": "^3.0.0",
         "inquirer": "^8.2.5",
         "inquirer-autocomplete-prompt": "^2.0.0",
         "jscodeshift": "0.13.1",
-        "marked": "^4.3.0",
-        "marked-terminal": "^6.0.0",
-        "node-emoji": "^2.1.3",
         "node-env-type": "^0.0.8",
         "node-fetch": "^2.6.7",
         "ora": "^5.4.1",
         "pluralize": "^8.0.0",
         "preferred-pm": "^3.0.3",
         "prettier": "^2.7.1",
-        "semver": "7.3.8",
         "semver-diff": "^3.1.1",
         "temp": "^0.9.4",
         "tslib": "^2.3.1"
@@ -1866,13 +2052,12 @@
       }
     },
     "node_modules/@refinedev/devtools-server": {
-      "version": "1.1.24",
-      "resolved": "https://registry.npmjs.org/@refinedev/devtools-server/-/devtools-server-1.1.24.tgz",
-      "integrity": "sha512-4nKBhOKBOSPdO6LGfZnk0XmJ74TSQ/MQ2h5204aQgM1znPhPNnLERsTzKL6b0vHoli/EKzm0nRFcTfFJ0WOEUg==",
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/@refinedev/devtools-server/-/devtools-server-1.1.6.tgz",
+      "integrity": "sha512-fL+jzKWrsEUqydne0947jzgv69xzvUOhFJ0qER/lLu2+eEitXpCK8/wq5x1Q8wBW0/S2w2FqlF3TNwytidL+iQ==",
       "dependencies": {
-        "@ory/client": "^1.5.2",
-        "@refinedev/devtools-shared": "1.1.3",
-        "@refinedev/devtools-ui": "1.1.17",
+        "@refinedev/devtools-shared": "1.1.2",
+        "@refinedev/devtools-ui": "1.1.6",
         "body-parser": "^1.20.2",
         "boxen": "^5.1.2",
         "chalk": "^4.1.2",
@@ -1887,7 +2072,6 @@
         "jscodeshift": "0.13.1",
         "lodash": "^4.17.21",
         "marked": "^4.3.0",
-        "node-fetch": "^2.6.7",
         "preferred-pm": "^3.0.3",
         "react": "^18.0.0",
         "react-dom": "^18.0.0",
@@ -1907,6 +2091,24 @@
         "react-dom": "^17.0.0 || ^18.0.0"
       }
     },
+    "node_modules/@refinedev/devtools-server/node_modules/@refinedev/devtools-shared": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@refinedev/devtools-shared/-/devtools-shared-1.1.2.tgz",
+      "integrity": "sha512-ze+akDLtCblBBEZuFTYoiAu1CfEdzBRBdttVaLJEAgSNdMva9vpbV/7gG5yTQRIIi4kIdfghphwrGHBxOOKjXQ==",
+      "dependencies": {
+        "@tanstack/react-query": "^4.10.1",
+        "error-stack-parser": "^2.1.4"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "^17.0.0 || ^18.0.0",
+        "@types/react-dom": "^17.0.0 || ^18.0.0",
+        "react": "^17.0.0 || ^18.0.0",
+        "react-dom": "^17.0.0 || ^18.0.0"
+      }
+    },
     "node_modules/@refinedev/devtools-shared": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@refinedev/devtools-shared/-/devtools-shared-1.1.3.tgz",
@@ -1926,14 +2128,14 @@
       }
     },
     "node_modules/@refinedev/devtools-ui": {
-      "version": "1.1.17",
-      "resolved": "https://registry.npmjs.org/@refinedev/devtools-ui/-/devtools-ui-1.1.17.tgz",
-      "integrity": "sha512-bV9FjWBYIB73pwSS/2jBbmWznqxvBHSXXk9cNqY+FhqKHWBUznFs5c64YimCBRZajcdGeFZhiJ8FZhC8l5T8vw==",
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/@refinedev/devtools-ui/-/devtools-ui-1.1.6.tgz",
+      "integrity": "sha512-orW59H3J+ZjZQiN/vyqd0bdOGNL2LVMzRl+8OaUDaLRS/Obd5atMJYHZiaJwEWkiy0OSgqGsmJPmN0Sfca8hHw==",
       "dependencies": {
         "@fireworks-js/react": "^2.10.7",
         "@headlessui/react": "^1.7.17",
-        "@ory/client": "^1.5.2",
-        "@refinedev/devtools-shared": "1.1.3",
+        "@ory/client": "^1.1.25",
+        "@refinedev/devtools-shared": "1.1.2",
         "@tanstack/react-table": "^8.2.6",
         "clsx": "^1.1.1",
         "dayjs": "^1.10.7",
@@ -1954,6 +2156,24 @@
         "react-dom": "^17.0.0 || ^18.0.0"
       }
     },
+    "node_modules/@refinedev/devtools-ui/node_modules/@refinedev/devtools-shared": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@refinedev/devtools-shared/-/devtools-shared-1.1.2.tgz",
+      "integrity": "sha512-ze+akDLtCblBBEZuFTYoiAu1CfEdzBRBdttVaLJEAgSNdMva9vpbV/7gG5yTQRIIi4kIdfghphwrGHBxOOKjXQ==",
+      "dependencies": {
+        "@tanstack/react-query": "^4.10.1",
+        "error-stack-parser": "^2.1.4"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "^17.0.0 || ^18.0.0",
+        "@types/react-dom": "^17.0.0 || ^18.0.0",
+        "react": "^17.0.0 || ^18.0.0",
+        "react-dom": "^17.0.0 || ^18.0.0"
+      }
+    },
     "node_modules/@refinedev/devtools-ui/node_modules/clsx": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
@@ -2202,9 +2422,9 @@
       }
     },
     "node_modules/@remix-run/router": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz",
-      "integrity": "sha512-HOil5aFtme37dVQTB6M34G95kPM3MMuqSmIRVCC52eKV+Y/tGSqw9P3rWhlAx6A+mz+MoX+XxsGsNJbaI5qCgQ==",
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz",
+      "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==",
       "engines": {
         "node": ">=14.0.0"
       }
@@ -2285,11 +2505,11 @@
       }
     },
     "node_modules/@tanstack/react-table": {
-      "version": "8.11.8",
-      "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.11.8.tgz",
-      "integrity": "sha512-NEwvIq4iSiDQozEyvbdiSdCOiLa+g5xHmdEnvwDb98FObcK6YkBOkRrs/CNqrKdDy+/lqoIllIWHk+M80GW6+g==",
+      "version": "8.12.0",
+      "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.12.0.tgz",
+      "integrity": "sha512-LlEQ1Gpz4bfpiET+qmle4BhKDgKN3Y/sssc+O/wLqX8HRtjV+nhusYbllZlutZfMR8oeef83whKTj/VhaV8EeA==",
       "dependencies": {
-        "@tanstack/table-core": "8.11.8"
+        "@tanstack/table-core": "8.12.0"
       },
       "engines": {
         "node": ">=12"
@@ -2304,11 +2524,11 @@
       }
     },
     "node_modules/@tanstack/react-virtual": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.4.tgz",
-      "integrity": "sha512-tiqKW/e2MJVCr7/pRUXulpkyxllaOclkHNfhKTo4pmHjJIqnhMfwIjc1Q1R0Un3PI3kQywywu/791c8z9u0qeA==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.1.2.tgz",
+      "integrity": "sha512-qibmxtctgOZo2I+3Rw5GR9kXgaa15U5r3/idDY1ItUKW15UK7GhCfyIfE6qYuJ1fxQF6dJDsD8SbpPyuJgpxuA==",
       "dependencies": {
-        "@tanstack/virtual-core": "3.0.0"
+        "@tanstack/virtual-core": "3.1.2"
       },
       "funding": {
         "type": "github",
@@ -2320,9 +2540,9 @@
       }
     },
     "node_modules/@tanstack/table-core": {
-      "version": "8.11.8",
-      "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.11.8.tgz",
-      "integrity": "sha512-DECHvtq4YW4U/gqg6etup7ydt/RB1Bi1pJaMpHUXl65ooW1d71Nv7BzD66rUdHrBSNdyiW3PLTPUQlpXjAgDeA==",
+      "version": "8.12.0",
+      "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.12.0.tgz",
+      "integrity": "sha512-cq/ylWVrOwixmwNXQjgZaQw1Izf7+nPxjczum7paAnMtwPg1S2qRAJU+Jb8rEBUWm69voC/zcChmePlk2hc6ug==",
       "engines": {
         "node": ">=12"
       },
@@ -2332,9 +2552,9 @@
       }
     },
     "node_modules/@tanstack/virtual-core": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0.tgz",
-      "integrity": "sha512-SYXOBTjJb05rXa2vl55TTwO40A6wKu0R5i1qQwhJYNDIqaIGF7D0HsLw+pJAyi2OvntlEIVusx3xtbbgSUi6zg==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.1.2.tgz",
+      "integrity": "sha512-DATZJs8iejkIUqXZe6ruDAnjFo78BKnIIgqQZrc7CmEFqfLEN/TPD91n4hRfo6hpRB6xC00bwKxv7vdjFNEmOg==",
       "funding": {
         "type": "github",
         "url": "https://github.com/sponsors/tannerlinsley"
@@ -2365,6 +2585,90 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@types/marked-terminal": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/@types/marked-terminal/-/marked-terminal-3.1.7.tgz",
+      "integrity": "sha512-bKbVK9E6ADmxDsSQAQmEA9NToAfsCTC7TeCiZ5Nl1BCi/IbJqlzSfRTdYrq0PxWL3Lb+dxhWVbHwF9l48neOsA==",
+      "dependencies": {
+        "chalk": "^2.4.1",
+        "marked": "^6.0.0"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+    },
+    "node_modules/@types/marked-terminal/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/marked": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-6.0.0.tgz",
+      "integrity": "sha512-7E3m/xIlymrFL5gWswIT4CheIE3fDeh51NV09M4x8iOc7NDYlyERcQMLAIHcSlrvwliwbPQ4OGD+MpPSYiQcqw==",
+      "bin": {
+        "marked": "bin/marked.js"
+      },
+      "engines": {
+        "node": ">= 16"
+      }
+    },
+    "node_modules/@types/marked-terminal/node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/@types/mdast": {
       "version": "3.0.15",
       "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
@@ -2428,6 +2732,11 @@
       "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
       "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
     },
+    "node_modules/@types/yoga-layout": {
+      "version": "1.9.2",
+      "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz",
+      "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw=="
+    },
     "node_modules/@typescript-eslint/parser": {
       "version": "5.48.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.0.tgz",
@@ -2572,19 +2881,6 @@
         }
       }
     },
-    "node_modules/align-text": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/align-text/-/align-text-1.0.2.tgz",
-      "integrity": "sha512-uBPDs72zrRTdiTBY0YjBbuBOdXtRyT4qsKPb4bL4O7vH4utz/7KjwTJVsVbdThxMbVzkRGAfk8Ml3xoMvXSEYw==",
-      "dependencies": {
-        "kind-of": "^5.0.2",
-        "longest": "^2.0.1",
-        "repeat-string": "^1.6.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/ansi-align": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
@@ -2727,6 +3023,14 @@
         "node": ">=4"
       }
     },
+    "node_modules/astral-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -2751,6 +3055,17 @@
         "node": ">=10.12.0"
       }
     },
+    "node_modules/auto-bind": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz",
+      "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/axios": {
       "version": "1.6.7",
       "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
@@ -2951,9 +3266,9 @@
       }
     },
     "node_modules/browserslist": {
-      "version": "4.22.3",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz",
-      "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==",
+      "version": "4.23.0",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
+      "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
       "funding": [
         {
           "type": "opencollective",
@@ -2969,8 +3284,8 @@
         }
       ],
       "dependencies": {
-        "caniuse-lite": "^1.0.30001580",
-        "electron-to-chromium": "^1.4.648",
+        "caniuse-lite": "^1.0.30001587",
+        "electron-to-chromium": "^1.4.668",
         "node-releases": "^2.0.14",
         "update-browserslist-db": "^1.0.13"
       },
@@ -3080,9 +3395,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001583",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz",
-      "integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==",
+      "version": "1.0.30001591",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz",
+      "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==",
       "funding": [
         {
           "type": "opencollective",
@@ -3119,18 +3434,6 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
-    "node_modules/center-align": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/center-align/-/center-align-1.0.1.tgz",
-      "integrity": "sha512-j6Ba1Vwtu0i9CUfM5VicnMqOsNRMYnNAoTUTB/EzUFhBKkqFPD5UE2WTCSIy49OnbjTEnJ0t2CFPYMbKNrUi/A==",
-      "dependencies": {
-        "align-text": "^1.0.0",
-        "repeat-string": "^1.6.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/chalk": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -3194,6 +3497,11 @@
         "node": "*"
       }
     },
+    "node_modules/ci-info": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
+    },
     "node_modules/class-utils": {
       "version": "0.3.6",
       "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@@ -3278,6 +3586,21 @@
         "@colors/colors": "1.5.0"
       }
     },
+    "node_modules/cli-truncate": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+      "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+      "dependencies": {
+        "slice-ansi": "^3.0.0",
+        "string-width": "^4.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/cli-width": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
@@ -3291,6 +3614,17 @@
       "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
       "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
     },
+    "node_modules/cliui": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
     "node_modules/clone": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
@@ -3312,14 +3646,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/clone-deep/node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/clsx": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
@@ -3328,6 +3654,17 @@
         "node": ">=6"
       }
     },
+    "node_modules/code-excerpt": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-3.0.0.tgz",
+      "integrity": "sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw==",
+      "dependencies": {
+        "convert-to-spaces": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/collection-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -3389,6 +3726,12 @@
       "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
       "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
     },
+    "node_modules/compare-versions": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.4.tgz",
+      "integrity": "sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==",
+      "dev": true
+    },
     "node_modules/component-emitter": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
@@ -3402,6 +3745,61 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
     },
+    "node_modules/concurrently": {
+      "version": "6.5.1",
+      "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.5.1.tgz",
+      "integrity": "sha512-FlSwNpGjWQfRwPLXvJ/OgysbBxPkWpiVjy1042b0U7on7S7qwwMIILRj7WTN1mTgqa582bG6NFuScOoh6Zgdag==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "date-fns": "^2.16.1",
+        "lodash": "^4.17.21",
+        "rxjs": "^6.6.3",
+        "spawn-command": "^0.0.2-1",
+        "supports-color": "^8.1.0",
+        "tree-kill": "^1.2.2",
+        "yargs": "^16.2.0"
+      },
+      "bin": {
+        "concurrently": "bin/concurrently.js"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/concurrently/node_modules/rxjs": {
+      "version": "6.6.7",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+      "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^1.9.0"
+      },
+      "engines": {
+        "npm": ">=2.0.0"
+      }
+    },
+    "node_modules/concurrently/node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/concurrently/node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "dev": true
+    },
     "node_modules/conf": {
       "version": "10.2.0",
       "resolved": "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz",
@@ -3425,6 +3823,24 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/consola": {
+      "version": "2.15.3",
+      "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz",
+      "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==",
+      "dev": true
+    },
+    "node_modules/console.table": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/console.table/-/console.table-0.10.0.tgz",
+      "integrity": "sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==",
+      "dev": true,
+      "dependencies": {
+        "easy-table": "1.1.0"
+      },
+      "engines": {
+        "node": "> 0.10"
+      }
+    },
     "node_modules/content-disposition": {
       "version": "0.5.4",
       "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -3449,6 +3865,14 @@
       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
       "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
     },
+    "node_modules/convert-to-spaces": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz",
+      "integrity": "sha512-cj09EBuObp9gZNQCzc7hByQyrs6jVGE+o9kSJmeUoj+GiPiJvi5LYqEH/Hmme4+MTLHM+Ejtq+FChpjjEnsPdQ==",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
     "node_modules/cookie": {
       "version": "0.5.0",
       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
@@ -3547,6 +3971,22 @@
       "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
       "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
     },
+    "node_modules/date-fns": {
+      "version": "2.30.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+      "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/runtime": "^7.21.0"
+      },
+      "engines": {
+        "node": ">=0.11"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/date-fns"
+      }
+    },
     "node_modules/dayjs": {
       "version": "1.11.10",
       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
@@ -3765,15 +4205,24 @@
       "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
       "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
     },
+    "node_modules/easy-table": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz",
+      "integrity": "sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==",
+      "dev": true,
+      "optionalDependencies": {
+        "wcwidth": ">=1.0.1"
+      }
+    },
     "node_modules/ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.661",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.661.tgz",
-      "integrity": "sha512-AFg4wDHSOk5F+zA8aR+SVIOabu7m0e7BiJnigCvPXzIGy731XENw/lmNxTySpVFtkFEy+eyt4oHhh5FF3NjQNw=="
+      "version": "1.4.682",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.682.tgz",
+      "integrity": "sha512-oCglfs8yYKs9RQjJFOHonSnhikPK3y+0SvSYc/YpYJV//6rqc0/hbwd0c7vgK4vrl6y2gJAwjkhkSGWK+z4KRA=="
     },
     "node_modules/emoji-regex": {
       "version": "8.0.0",
@@ -4171,6 +4620,12 @@
         "node": ">=8.6.0"
       }
     },
+    "node_modules/fast-safe-stringify": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+      "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+      "dev": true
+    },
     "node_modules/fastq": {
       "version": "1.17.0",
       "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz",
@@ -4385,9 +4840,9 @@
       "integrity": "sha512-FyRNiqlgu9ZeFCjfN0UiGUlj5dUWNYLyFaWN/Q8sOMf0E+KGA4dMROaBZpCtym85fChgCspoa3jHoLTRZiy74A=="
     },
     "node_modules/flow-parser": {
-      "version": "0.228.0",
-      "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.228.0.tgz",
-      "integrity": "sha512-xPWkzCO07AnS8X+fQFpWm+tJ+C7aeaiVzJ+rSepbkCXUvUJ6l6squEl63axoMcixyH4wLjmypOzq/+zTD0O93w==",
+      "version": "0.229.2",
+      "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.229.2.tgz",
+      "integrity": "sha512-T72XV2Izvl7yV6dhHhLaJ630Y6vOZJl6dnOS6dN0bPW9ExuREu7xGAf3omtcxX76POTuux9TJPu9ZpS48a/rdw==",
       "engines": {
         "node": ">=0.4.0"
       }
@@ -4539,6 +4994,15 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true,
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
     "node_modules/get-intrinsic": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.3.tgz",
@@ -4714,14 +5178,6 @@
         "node": ">=6.0"
       }
     },
-    "node_modules/gray-matter/node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/handlebars": {
       "version": "4.7.8",
       "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
@@ -5032,6 +5488,14 @@
         "node": ">=0.8.19"
       }
     },
+    "node_modules/indent-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -5046,6 +5510,154 @@
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
+    "node_modules/ink": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ink/-/ink-3.2.0.tgz",
+      "integrity": "sha512-firNp1q3xxTzoItj/eOOSZQnYSlyrWks5llCTVX37nJ59K3eXbQ8PtzCguqo8YI19EELo5QxaKnJd4VxzhU8tg==",
+      "dependencies": {
+        "ansi-escapes": "^4.2.1",
+        "auto-bind": "4.0.0",
+        "chalk": "^4.1.0",
+        "cli-boxes": "^2.2.0",
+        "cli-cursor": "^3.1.0",
+        "cli-truncate": "^2.1.0",
+        "code-excerpt": "^3.0.0",
+        "indent-string": "^4.0.0",
+        "is-ci": "^2.0.0",
+        "lodash": "^4.17.20",
+        "patch-console": "^1.0.0",
+        "react-devtools-core": "^4.19.1",
+        "react-reconciler": "^0.26.2",
+        "scheduler": "^0.20.2",
+        "signal-exit": "^3.0.2",
+        "slice-ansi": "^3.0.0",
+        "stack-utils": "^2.0.2",
+        "string-width": "^4.2.2",
+        "type-fest": "^0.12.0",
+        "widest-line": "^3.1.0",
+        "wrap-ansi": "^6.2.0",
+        "ws": "^7.5.5",
+        "yoga-layout-prebuilt": "^1.9.6"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": ">=16.8.0",
+        "react": ">=16.8.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/ink-markdown": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/ink-markdown/-/ink-markdown-1.0.4.tgz",
+      "integrity": "sha512-MZ0o5wSCp9bTSZkSGAvBE3zd8U6r45z3V5YqNwOXjwaGxS5Mjxz+xHh4HDqtgo+q+aRHqXESpyku946AGVWm0A==",
+      "dependencies": {
+        "@types/marked-terminal": "^3.1.4",
+        "marked": "^9.0.3",
+        "marked-terminal": "^6.0.0"
+      },
+      "peerDependencies": {
+        "ink": ">=2.0.0",
+        "react": ">=16.8.0"
+      }
+    },
+    "node_modules/ink-markdown/node_modules/marked": {
+      "version": "9.1.6",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
+      "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==",
+      "bin": {
+        "marked": "bin/marked.js"
+      },
+      "engines": {
+        "node": ">= 16"
+      }
+    },
+    "node_modules/ink-table": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/ink-table/-/ink-table-3.1.0.tgz",
+      "integrity": "sha512-qxVb4DIaEaJryvF9uZGydnmP9Hkmas3DCKVpEcBYC0E4eJd3qNgNe+PZKuzgCERFe9LfAS1TNWxCr9+AU4v3YA==",
+      "dependencies": {
+        "object-hash": "^2.0.3"
+      },
+      "peerDependencies": {
+        "ink": ">=3.0.0",
+        "react": ">=16.8.0"
+      }
+    },
+    "node_modules/ink/node_modules/react-reconciler": {
+      "version": "0.26.2",
+      "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.26.2.tgz",
+      "integrity": "sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q==",
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "scheduler": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "peerDependencies": {
+        "react": "^17.0.2"
+      }
+    },
+    "node_modules/ink/node_modules/scheduler": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
+      "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1"
+      }
+    },
+    "node_modules/ink/node_modules/type-fest": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.12.0.tgz",
+      "integrity": "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/ink/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/ink/node_modules/ws": {
+      "version": "7.5.9",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+      "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+      "engines": {
+        "node": ">=8.3.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": "^5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/inline-style-parser": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
@@ -5158,6 +5770,17 @@
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
       "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
     },
+    "node_modules/is-ci": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+      "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+      "dependencies": {
+        "ci-info": "^2.0.0"
+      },
+      "bin": {
+        "is-ci": "bin.js"
+      }
+    },
     "node_modules/is-core-module": {
       "version": "2.13.1",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
@@ -5344,6 +5967,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/iterare": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz",
+      "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/jackspeak": {
       "version": "2.3.6",
       "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
@@ -5485,14 +6117,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/jscodeshift/node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/jscodeshift/node_modules/micromatch": {
       "version": "3.1.10",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -5616,9 +6240,9 @@
       }
     },
     "node_modules/kind-of": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-      "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -5689,14 +6313,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/longest": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz",
-      "integrity": "sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/longest-streak": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
@@ -6330,14 +6946,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/nanomatch/node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/negotiator": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -6880,6 +7488,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/patch-console": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-1.0.0.tgz",
+      "integrity": "sha512-nxl9nrnLQmh64iTzMfyylSlRozL7kAXIaxw1fVcLYdyhNkJCRUzirRZTikXGJsg+hc4fqpneTK6iU2H1Q8THSA==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/path-exists": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -7063,9 +7679,9 @@
       }
     },
     "node_modules/preferred-pm": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.2.tgz",
-      "integrity": "sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.3.tgz",
+      "integrity": "sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==",
       "dependencies": {
         "find-up": "^5.0.0",
         "find-yarn-workspace-root2": "1.2.16",
@@ -7327,6 +7943,35 @@
         "pure-color": "^1.2.0"
       }
     },
+    "node_modules/react-devtools-core": {
+      "version": "4.28.5",
+      "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz",
+      "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==",
+      "dependencies": {
+        "shell-quote": "^1.6.1",
+        "ws": "^7"
+      }
+    },
+    "node_modules/react-devtools-core/node_modules/ws": {
+      "version": "7.5.9",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+      "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+      "engines": {
+        "node": ">=8.3.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": "^5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/react-dom": {
       "version": "18.2.0",
       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -7482,11 +8127,11 @@
       }
     },
     "node_modules/react-router": {
-      "version": "6.22.0",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz",
-      "integrity": "sha512-q2yemJeg6gw/YixRlRnVx6IRJWZD6fonnfZhN1JIOhV2iJCPeRNSH3V1ISwHf+JWcESzLC3BOLD1T07tmO5dmg==",
+      "version": "6.22.1",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.1.tgz",
+      "integrity": "sha512-0pdoRGwLtemnJqn1K0XHUbnKiX0S4X8CgvVVmHGOWmofESj31msHo/1YiqcJWK7Wxfq2a4uvvtS01KAQyWK/CQ==",
       "dependencies": {
-        "@remix-run/router": "1.15.0"
+        "@remix-run/router": "1.15.1"
       },
       "engines": {
         "node": ">=14.0.0"
@@ -7496,12 +8141,12 @@
       }
     },
     "node_modules/react-router-dom": {
-      "version": "6.22.0",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz",
-      "integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==",
+      "version": "6.22.1",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.1.tgz",
+      "integrity": "sha512-iwMyyyrbL7zkKY7MRjOVRy+TMnS/OPusaFVxM2P11x9dzSzGmLsebkCvYirGq0DWB9K9hOspHYYtDz33gE5Duw==",
       "dependencies": {
-        "@remix-run/router": "1.15.0",
-        "react-router": "6.22.0"
+        "@remix-run/router": "1.15.1",
+        "react-router": "6.22.1"
       },
       "engines": {
         "node": ">=14.0.0"
@@ -7599,6 +8244,12 @@
         "esprima": "~4.0.0"
       }
     },
+    "node_modules/reflect-metadata": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+      "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+      "dev": true
+    },
     "node_modules/regenerator-runtime": {
       "version": "0.14.1",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
@@ -7692,6 +8343,15 @@
         "node": ">=0.10"
       }
     },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/require-from-string": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -7870,9 +8530,9 @@
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "node_modules/sanitize-html": {
-      "version": "2.11.0",
-      "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
-      "integrity": "sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==",
+      "version": "2.12.1",
+      "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz",
+      "integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==",
       "dependencies": {
         "deepmerge": "^4.2.2",
         "escape-string-regexp": "^4.0.0",
@@ -7910,14 +8570,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/section-matter/node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/semver": {
       "version": "7.3.8",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
@@ -8077,14 +8729,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/shallow-clone/node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/shebang-command": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -8104,6 +8748,14 @@
         "node": ">=8"
       }
     },
+    "node_modules/shell-quote": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+      "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/side-channel": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -8141,6 +8793,19 @@
         "node": ">=8"
       }
     },
+    "node_modules/slice-ansi": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+      "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/snapdragon": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -8302,6 +8967,12 @@
         "url": "https://github.com/sponsors/wooorm"
       }
     },
+    "node_modules/spawn-command": {
+      "version": "0.0.2-1",
+      "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
+      "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==",
+      "dev": true
+    },
     "node_modules/split-on-first": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
@@ -8349,6 +9020,25 @@
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
     },
+    "node_modules/stack-utils": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+      "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+      "dependencies": {
+        "escape-string-regexp": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/stack-utils/node_modules/escape-string-regexp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+      "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/stackframe": {
       "version": "1.3.4",
       "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
@@ -8736,6 +9426,15 @@
       "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
       "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
     },
+    "node_modules/tree-kill": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+      "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+      "dev": true,
+      "bin": {
+        "tree-kill": "cli.js"
+      }
+    },
     "node_modules/trough": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
@@ -8846,6 +9545,18 @@
         "node": ">=0.8.0"
       }
     },
+    "node_modules/uid": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz",
+      "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==",
+      "dev": true,
+      "dependencies": {
+        "@lukeed/csprng": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/undici-types": {
       "version": "5.26.5",
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
@@ -9411,6 +10122,15 @@
         "node": ">=0.4"
       }
     },
+    "node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/yallist": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@@ -9424,6 +10144,33 @@
         "node": ">= 6"
       }
     },
+    "node_modules/yargs": {
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "20.2.9",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+      "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@@ -9435,6 +10182,17 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/yoga-layout-prebuilt": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz",
+      "integrity": "sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==",
+      "dependencies": {
+        "@types/yoga-layout": "1.9.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/zwitch": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
diff --git a/package.json b/package.json
index ccac9c610940ede2a23ab6ff4cc55ff55bda21d2..cc2a3b2635df36ed6699141d27bc8cf437a4b12b 100644
--- a/package.json
+++ b/package.json
@@ -6,11 +6,13 @@
     "node": ">=18.0.0"
   },
   "scripts": {
-    "dev": "cross-env NODE_OPTIONS=--max_old_space_size=4096 refine dev",
+    "prepare": "echo \"export const version=$(npm pkg get version --workspaces=false);\" > src/version.js",
+    "dev": "npm run prepare && cross-env NODE_OPTIONS=--max_old_space_size=4096 refine dev",
     "build": "refine build",
     "start": "refine start",
     "lint": "eslint '**/*.{js,jsx,ts,tsx}'",
-    "refine": "refine"
+    "refine": "refine",
+    "generate": "rm -r src/api/* && npx @openapitools/openapi-generator-cli generate -i ../fdo-manager-service/api/src/main/resources/api.yaml -g typescript-axios -o src/api/"
   },
   "dependencies": {
     "@emotion/react": "^11.8.2",
@@ -19,7 +21,7 @@
     "@mui/lab": "^5.0.0-alpha.85",
     "@mui/material": "^5.8.6",
     "@mui/x-data-grid": "^6.6.0",
-    "@refinedev/cli": "^2.16.24",
+    "@refinedev/cli": "^2.16.1",
     "@refinedev/core": "^4.47.1",
     "@refinedev/devtools": "^1.1.32",
     "@refinedev/inferencer": "^4.5.20",
@@ -36,6 +38,7 @@
     "react-dom": "^18.0.0"
   },
   "devDependencies": {
+    "@openapitools/openapi-generator-cli": "^2.9.0",
     "@types/node": "^18.0.0",
     "@types/react": "^18.0.0",
     "@types/react-dom": "^18.0.0",
diff --git a/pages/404.tsx b/pages/404.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..fdd956bfa4e4349536df720c216fac4041561722
--- /dev/null
+++ b/pages/404.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+import { ErrorComponent } from "../src/components/ErrorComponent";
+import { GetServerSideProps } from "next";
+import { serverSideTranslations } from "next-i18next/serverSideTranslations";
+import { useTranslate } from "@refinedev/core";
+
+
+export default function NotFound(props) {
+  const translate = useTranslate();
+  console.log("NotFOUND: ", props, translate("pages.error.404"));
+  return <ErrorComponent />
+}
+
+export const getStaticProps = async (props) => {
+  const translateProps = await serverSideTranslations(props.locale ?? "en", [
+    "common",
+  ]);
+  console.log("getStaticProps", props, await serverSideTranslations("en", ["common"]));
+  return {
+    props: {
+      ...translateProps,
+      lang: "en",
+    }
+  }
+}
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 98d6bbf2620cb4760c5a82b8051e014055330066..aa02fa32a8e0af6d8a35d66e40b9ce1f36900e77 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -19,11 +19,10 @@ import { Header } from "@components/header";
 import { ColorModeContextProvider } from "@contexts";
 import CssBaseline from "@mui/material/CssBaseline";
 import GlobalStyles from "@mui/material/GlobalStyles";
-import dataProvider from "@refinedev/simple-rest";
+import dataProvider from "../src/providers/dataProvider";
 import { appWithTranslation, useTranslation } from "next-i18next";
 import logo from "../src/components/fdo_logo";
-
-const API_URL = "http://localhost:8081";
+import { API_URL } from "../src/constants";
 
 export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
   noLayout?: boolean;
@@ -105,41 +104,47 @@ const App = (props: React.PropsWithChildren) => {
     },
   };
 
-  return (
-    <>
-      <RefineKbarProvider>
-        <ColorModeContextProvider>
-          <CssBaseline />
-          <GlobalStyles styles={{ html: { WebkitFontSmoothing: "auto" } }} />
-          <RefineSnackbarProvider>
-            <Refine
-              routerProvider={routerProvider}
-              dataProvider={dataProvider(API_URL)}
-              notificationProvider={notificationProvider}
-              authProvider={authProvider}
-              i18nProvider={i18nProvider}
-              options={{
-                disableTelemetry: true,
-                syncWithLocation: true,
-                warnWhenUnsavedChanges: true,
-                useNewQueryKeys: true,
-              }}
-              resources={[
-                {
-                  name: "info",
-                  list: "/info",
-                }
-              ]}
-            >
-              {props.children}
-              <RefineKbar />
-              <UnsavedChangesNotifier />
-            </Refine>
-          </RefineSnackbarProvider>
-        </ColorModeContextProvider>
-      </RefineKbarProvider>
-    </>
-  );
+  return <>
+    <RefineKbarProvider>
+      <ColorModeContextProvider>
+        <CssBaseline />
+        <GlobalStyles styles={{ html: { WebkitFontSmoothing: "auto" } }} />
+        <RefineSnackbarProvider>
+          <Refine
+            routerProvider={routerProvider}
+            dataProvider={dataProvider(API_URL)}
+            notificationProvider={notificationProvider}
+            authProvider={authProvider}
+            i18nProvider={i18nProvider}
+            options={{
+              disableTelemetry: true,
+              syncWithLocation: true,
+              warnWhenUnsavedChanges: true,
+              useNewQueryKeys: true,
+            }}
+            resources={[
+            {
+              name: "fdo",
+              list: "/fdo",
+              show: "/fdo/show/:id",
+              create: "/fdo"
+            }, {
+              name: "repositories",
+              list: "/repositories",
+              show: "/repositories/show/:id"
+            }, {
+              name: "info",
+              list: "/info",
+            }]}
+          >
+            {props.children}
+            <RefineKbar />
+            <UnsavedChangesNotifier />
+          </Refine>
+        </RefineSnackbarProvider>
+      </ColorModeContextProvider>
+    </RefineKbarProvider>
+  </>;
 };
 
 function MyApp({
diff --git a/pages/fdo/index.jsx b/pages/fdo/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..64079b8d3c22c0b191979248a7d9f58644eb2984
--- /dev/null
+++ b/pages/fdo/index.jsx
@@ -0,0 +1,9 @@
+import React from "react";
+
+import { FdoCreate } from "../../src/components/fdos";
+
+const CreateFDO = () => {
+  return <FdoCreate/>
+};
+
+export default CreateFDO;
diff --git a/pages/fdo/show/[id]/index.tsx b/pages/fdo/show/[id]/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7d20b2247ae43dfa6810c556e61959ab0b0621f9
--- /dev/null
+++ b/pages/fdo/show/[id]/index.tsx
@@ -0,0 +1,53 @@
+import React from "react";
+
+import { ErrorComponent } from "../../../../src/components/ErrorComponent";
+import { GetServerSideProps } from "next";
+import { serverSideTranslations } from "next-i18next/serverSideTranslations";
+import { useShow } from "@refinedev/core";
+import { Show } from "@refinedev/mui";
+import { Typography } from "@mui/material";
+import CircularProgress from '@mui/material/CircularProgress';
+import Box from '@mui/material/Box';
+
+const ShowFDO = (props) => {
+  console.log("ShowFDO", props);
+  const { queryResult: { isError, error, isLoading, data }, showId }= useShow({
+    errorNotification: () => false,
+    queryOptions: {
+      retry: false,
+    }
+  });
+
+  if(isError) {
+    console.log("error", error);
+    return <ErrorComponent/>
+  }
+
+  return(
+    <Show
+      isLoading={isLoading}
+      title={<Typography variant="h5">Custom Title</Typography>}
+    >
+      { isLoading && <Box sx={{textAlign: "center"}}><CircularProgress/></Box>}
+    </Show>
+
+  );
+
+};
+
+export default ShowFDO;
+
+export const getServerSideProps: GetServerSideProps<{}> = async (context) => {
+  console.log("getServerSideProps", context);
+  const data = undefined; // TODO
+  const translateProps = await serverSideTranslations(context.locale ?? "en", [
+    "common",
+  ]);
+
+  return {
+    notFound: true,
+    props: {
+      ...translateProps,
+    },
+  };
+};
diff --git a/pages/info/index.jsx b/pages/info/index.jsx
index bd71ad5c21d7cf26e592cf4566a58785dec2c547..27229a56b302dd7baea0587bfa4b7bc68d1de6c9 100644
--- a/pages/info/index.jsx
+++ b/pages/info/index.jsx
@@ -1,18 +1,33 @@
 import React from "react";
+import Stack from '@mui/material/Stack';
+import Paper from '@mui/material/Paper';
+import Box from '@mui/material/Box';
+import { styled } from '@mui/material/styles';
+import { FDO_MANAGER_WEBUI_VERSION } from '../../src/constants';
 
-import { useGo, useList } from "@refinedev/core";
+import { useOne } from "@refinedev/core";
 
-const Info = () => {
-  const { data, isLoading } = useList({resource: "hello"});
+const Item = styled(Paper)(({ theme }) => ({
+  backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
+  ...theme.typography.body2,
+  padding: theme.spacing(1),
+  textAlign: 'left',
+  color: theme.palette.text.secondary,
+}));
 
-  const go = useGo();
+const Info = () => {
+  const { data, isLoading } = useOne({resource: "info", id: false});
 
   if (isLoading) return <div>Loading...</div>;
 
   return (
-    <div>
-      {data?.data?.message}
-    </div>
+    <Box>
+    <Stack>
+      <Item>FDO Manager WebUI Version: {FDO_MANAGER_WEBUI_VERSION}</Item>
+      <Item>FDO Manager Service Version: {data?.data?.fdoServiceVersion}</Item>
+      <Item>FDO Manager SDK Version: {data?.data?.fdoSdkVersion}</Item>
+    </Stack>
+    </Box>
   );
 };
 
diff --git a/pages/repositories/index.jsx b/pages/repositories/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..6607e9646db893cec9339fd8f8b42c2549d9d491
--- /dev/null
+++ b/pages/repositories/index.jsx
@@ -0,0 +1,9 @@
+import React from "react";
+
+import { RepositoriesList } from "../../src/components/repositories";
+
+const ListRepositories = () => {
+  return <RepositoriesList/>
+};
+
+export default ListRepositories;
diff --git a/src/api/.gitignore b/src/api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..149b57654723c14590f35c6c0db8460f19173078
--- /dev/null
+++ b/src/api/.gitignore
@@ -0,0 +1,4 @@
+wwwroot/*.js
+node_modules
+typings
+dist
diff --git a/src/api/.npmignore b/src/api/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..999d88df6939a13529be54ef2e68fb3248257ad8
--- /dev/null
+++ b/src/api/.npmignore
@@ -0,0 +1 @@
+# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm
\ No newline at end of file
diff --git a/src/api/.openapi-generator-ignore b/src/api/.openapi-generator-ignore
new file mode 100644
index 0000000000000000000000000000000000000000..7484ee590a3894506cf063799b885428f95a71be
--- /dev/null
+++ b/src/api/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/src/api/.openapi-generator/FILES b/src/api/.openapi-generator/FILES
new file mode 100644
index 0000000000000000000000000000000000000000..a80cd4f07b06392ec40d85448aa5df7f94cce151
--- /dev/null
+++ b/src/api/.openapi-generator/FILES
@@ -0,0 +1,8 @@
+.gitignore
+.npmignore
+api.ts
+base.ts
+common.ts
+configuration.ts
+git_push.sh
+index.ts
diff --git a/src/api/.openapi-generator/VERSION b/src/api/.openapi-generator/VERSION
new file mode 100644
index 0000000000000000000000000000000000000000..8b23b8d47ce2ae4e1fcc12ff98cf8133391765da
--- /dev/null
+++ b/src/api/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.3.0
\ No newline at end of file
diff --git a/src/api/api.ts b/src/api/api.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0ebd1087ad3c9c82169a0991efa74ba3ece4f03e
--- /dev/null
+++ b/src/api/api.ts
@@ -0,0 +1,1430 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FDO Manager Service API
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1
+ * 
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+import type { Configuration } from './configuration';
+import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
+import globalAxios from 'axios';
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common';
+import type { RequestArgs } from './base';
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from './base';
+
+/**
+ * 
+ * @export
+ * @interface CreateFDOProcess
+ */
+export interface CreateFDOProcess {
+    /**
+     * 
+     * @type {CreateFDOProcessState}
+     * @memberof CreateFDOProcess
+     */
+    'state'?: CreateFDOProcessState;
+    /**
+     * 
+     * @type {string}
+     * @memberof CreateFDOProcess
+     */
+    'processId': string;
+    /**
+     * 
+     * @type {TargetRepositories}
+     * @memberof CreateFDOProcess
+     */
+    'targetRepository': TargetRepositories;
+}
+
+
+/**
+ * 
+ * @export
+ * @enum {string}
+ */
+
+export const CreateFDOProcessState = {
+    Processing: 'processing',
+    Finished: 'finished',
+    Canceled: 'canceled'
+} as const;
+
+export type CreateFDOProcessState = typeof CreateFDOProcessState[keyof typeof CreateFDOProcessState];
+
+
+/**
+ * 
+ * @export
+ * @interface CreateFDORequest
+ */
+export interface CreateFDORequest {
+    /**
+     * 
+     * @type {TargetRepositories}
+     * @memberof CreateFDORequest
+     */
+    'targetRepository': TargetRepositories;
+}
+/**
+ * 
+ * @export
+ * @interface DigitalObject
+ */
+export interface DigitalObject {
+    /**
+     * 
+     * @type {string}
+     * @memberof DigitalObject
+     */
+    'pid': string;
+    /**
+     * 
+     * @type {boolean}
+     * @memberof DigitalObject
+     */
+    'isFdo': boolean;
+    /**
+     * 
+     * @type {string}
+     * @memberof DigitalObject
+     */
+    'dataPid'?: string;
+    /**
+     * 
+     * @type {string}
+     * @memberof DigitalObject
+     */
+    'metadataPid'?: string;
+}
+/**
+ * 
+ * @export
+ * @interface GetInfo200Response
+ */
+export interface GetInfo200Response {
+    /**
+     * 
+     * @type {Info}
+     * @memberof GetInfo200Response
+     */
+    'data': Info;
+    /**
+     * 
+     * @type {Links}
+     * @memberof GetInfo200Response
+     */
+    'links'?: Links;
+}
+/**
+ * 
+ * @export
+ * @interface GetRepository200Response
+ */
+export interface GetRepository200Response {
+    /**
+     * 
+     * @type {Repository}
+     * @memberof GetRepository200Response
+     */
+    'data': Repository;
+    /**
+     * 
+     * @type {Links}
+     * @memberof GetRepository200Response
+     */
+    'links'?: Links;
+}
+/**
+ * 
+ * @export
+ * @interface Hello
+ */
+export interface Hello {
+    /**
+     * 
+     * @type {string}
+     * @memberof Hello
+     */
+    'message'?: string;
+}
+/**
+ * 
+ * @export
+ * @interface Info
+ */
+export interface Info {
+    /**
+     * 
+     * @type {string}
+     * @memberof Info
+     */
+    'fdoServiceVersion'?: string;
+    /**
+     * 
+     * @type {string}
+     * @memberof Info
+     */
+    'fdoSdkVersion'?: string;
+    /**
+     * 
+     * @type {string}
+     * @memberof Info
+     */
+    'serviceProvider'?: string;
+}
+/**
+ * 
+ * @export
+ * @interface Links
+ */
+export interface Links {
+    /**
+     * 
+     * @type {string}
+     * @memberof Links
+     */
+    'self'?: string;
+    /**
+     * 
+     * @type {string}
+     * @memberof Links
+     */
+    'collection'?: string;
+}
+/**
+ * 
+ * @export
+ * @interface ListRepositories200Response
+ */
+export interface ListRepositories200Response {
+    /**
+     * 
+     * @type {Array<Repository>}
+     * @memberof ListRepositories200Response
+     */
+    'data'?: Array<Repository>;
+    /**
+     * 
+     * @type {Links}
+     * @memberof ListRepositories200Response
+     */
+    'links'?: Links;
+}
+/**
+ * 
+ * @export
+ * @interface ModelError
+ */
+export interface ModelError {
+    /**
+     * 
+     * @type {string}
+     * @memberof ModelError
+     */
+    'detail': string;
+    /**
+     * 
+     * @type {string}
+     * @memberof ModelError
+     */
+    'status': string;
+}
+/**
+ * 
+ * @export
+ * @interface OverviewFdoCreate200Response
+ */
+export interface OverviewFdoCreate200Response {
+    /**
+     * 
+     * @type {CreateFDOProcess}
+     * @memberof OverviewFdoCreate200Response
+     */
+    'data': CreateFDOProcess;
+    /**
+     * 
+     * @type {Links}
+     * @memberof OverviewFdoCreate200Response
+     */
+    'links'?: Links;
+}
+/**
+ * 
+ * @export
+ * @interface Repository
+ */
+export interface Repository {
+    /**
+     * 
+     * @type {string}
+     * @memberof Repository
+     */
+    'id'?: string;
+    /**
+     * 
+     * @type {Links}
+     * @memberof Repository
+     */
+    'links'?: Links;
+}
+/**
+ * 
+ * @export
+ * @interface ResolvePID200Response
+ */
+export interface ResolvePID200Response {
+    /**
+     * 
+     * @type {DigitalObject}
+     * @memberof ResolvePID200Response
+     */
+    'data': DigitalObject;
+    /**
+     * 
+     * @type {Links}
+     * @memberof ResolvePID200Response
+     */
+    'links'?: Links;
+}
+/**
+ * 
+ * @export
+ * @interface TargetRepositories
+ */
+export interface TargetRepositories {
+    /**
+     * 
+     * @type {string}
+     * @memberof TargetRepositories
+     */
+    'fdo': string;
+    /**
+     * 
+     * @type {string}
+     * @memberof TargetRepositories
+     */
+    'metadata'?: string;
+    /**
+     * 
+     * @type {string}
+     * @memberof TargetRepositories
+     */
+    'data'?: string;
+}
+/**
+ * 
+ * @export
+ * @interface UpdateStateFdoCreateRequest
+ */
+export interface UpdateStateFdoCreateRequest {
+    /**
+     * 
+     * @type {CreateFDOProcessState}
+     * @memberof UpdateStateFdoCreateRequest
+     */
+    'data': CreateFDOProcessState;
+}
+
+
+/**
+ * 
+ * @export
+ * @interface UploadState
+ */
+export interface UploadState {
+    /**
+     * 
+     * @type {CreateFDOProcessState}
+     * @memberof UploadState
+     */
+    'state'?: CreateFDOProcessState;
+}
+
+
+
+/**
+ * DefaultApi - axios parameter creator
+ * @export
+ */
+export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) {
+    return {
+        /**
+         * 
+         * @summary Create an FDO.
+         * @param {TargetRepositories} repositories 
+         * @param {File} [data] 
+         * @param {File} [metadata] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        createFDO: async (repositories: TargetRepositories, data?: File, metadata?: File, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'repositories' is not null or undefined
+            assertParamExists('createFDO', 'repositories', repositories)
+            const localVarPath = `/fdo`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+            const localVarFormParams = new ((configuration && configuration.formDataCtor) || FormData)();
+
+
+            if (repositories !== undefined) { 
+                localVarFormParams.append('repositories', new Blob([JSON.stringify(repositories)], { type: "application/json", }));
+            }
+    
+            if (data !== undefined) { 
+                localVarFormParams.append('data', data as any);
+            }
+    
+            if (metadata !== undefined) { 
+                localVarFormParams.append('metadata', metadata as any);
+            }
+    
+    
+            localVarHeaderParameter['Content-Type'] = 'multipart/form-data';
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            localVarRequestOptions.data = localVarFormParams;
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Retrieve general information on the service.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getInfo: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/info`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Get the current state of the FDO creation process.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getStateFdoCreate: async (processId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('getStateFdoCreate', 'processId', processId)
+            const localVarPath = `/fdo/create/{processId}/state`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Get the current state of the data file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getStatusFdoCreateData: async (processId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('getStatusFdoCreateData', 'processId', processId)
+            const localVarPath = `/fdo/create/{processId}/data`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Get the current state of the metadata file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getStatusFdoCreateMetadata: async (processId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('getStatusFdoCreateMetadata', 'processId', processId)
+            const localVarPath = `/fdo/create/{processId}/metadata`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Say hello to the server.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        hello: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/hello`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Initiate the process to create an FDO
+         * @param {CreateFDORequest} createFDORequest 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        initiateFdoCreate: async (createFDORequest: CreateFDORequest, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'createFDORequest' is not null or undefined
+            assertParamExists('initiateFdoCreate', 'createFDORequest', createFDORequest)
+            const localVarPath = `/fdo/create`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            localVarHeaderParameter['Content-Type'] = 'application/json';
+
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            localVarRequestOptions.data = serializeDataIfNeeded(createFDORequest, localVarRequestOptions, configuration)
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Get an overview of the FDO creation process.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        overviewFdoCreate: async (processId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('overviewFdoCreate', 'processId', processId)
+            const localVarPath = `/fdo/create/{processId}`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Resolve a pid.
+         * @param {string} pid Persistent Identifier
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        resolvePID: async (pid: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'pid' is not null or undefined
+            assertParamExists('resolvePID', 'pid', pid)
+            const localVarPath = `/pid/{pid}`
+                .replace(`{${"pid"}}`, encodeURIComponent(String(pid)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Update the current state of the FDO creation process. Use this to cancel or conclude the creation process
+         * @param {string} processId Repository ID
+         * @param {UpdateStateFdoCreateRequest} [updateStateFdoCreateRequest] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        updateStateFdoCreate: async (processId: string, updateStateFdoCreateRequest?: UpdateStateFdoCreateRequest, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('updateStateFdoCreate', 'processId', processId)
+            const localVarPath = `/fdo/create/{processId}/state`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            localVarHeaderParameter['Content-Type'] = 'application/json';
+
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            localVarRequestOptions.data = serializeDataIfNeeded(updateStateFdoCreateRequest, localVarRequestOptions, configuration)
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Upload the data file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {File} body 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        uploadFdoCreateData: async (processId: string, body: File, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('uploadFdoCreateData', 'processId', processId)
+            // verify required parameter 'body' is not null or undefined
+            assertParamExists('uploadFdoCreateData', 'body', body)
+            const localVarPath = `/fdo/create/{processId}/data`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            localVarHeaderParameter['Content-Type'] = 'application/octet-stream';
+
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration)
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary Upload the metadata file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {File} body 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        uploadFdoCreateMetadata: async (processId: string, body: File, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'processId' is not null or undefined
+            assertParamExists('uploadFdoCreateMetadata', 'processId', processId)
+            // verify required parameter 'body' is not null or undefined
+            assertParamExists('uploadFdoCreateMetadata', 'body', body)
+            const localVarPath = `/fdo/create/{processId}/metadata`
+                .replace(`{${"processId"}}`, encodeURIComponent(String(processId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            localVarHeaderParameter['Content-Type'] = 'application/octet-stream';
+
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration)
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+    }
+};
+
+/**
+ * DefaultApi - functional programming interface
+ * @export
+ */
+export const DefaultApiFp = function(configuration?: Configuration) {
+    const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration)
+    return {
+        /**
+         * 
+         * @summary Create an FDO.
+         * @param {TargetRepositories} repositories 
+         * @param {File} [data] 
+         * @param {File} [metadata] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async createFDO(repositories: TargetRepositories, data?: File, metadata?: File, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.createFDO(repositories, data, metadata, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.createFDO']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Retrieve general information on the service.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async getInfo(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetInfo200Response>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.getInfo(options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.getInfo']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Get the current state of the FDO creation process.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async getStateFdoCreate(processId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.getStateFdoCreate(processId, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.getStateFdoCreate']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Get the current state of the data file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async getStatusFdoCreateData(processId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.getStatusFdoCreateData(processId, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.getStatusFdoCreateData']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Get the current state of the metadata file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async getStatusFdoCreateMetadata(processId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.getStatusFdoCreateMetadata(processId, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.getStatusFdoCreateMetadata']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Say hello to the server.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async hello(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Hello>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.hello(options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.hello']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Initiate the process to create an FDO
+         * @param {CreateFDORequest} createFDORequest 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async initiateFdoCreate(createFDORequest: CreateFDORequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.initiateFdoCreate(createFDORequest, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.initiateFdoCreate']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Get an overview of the FDO creation process.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async overviewFdoCreate(processId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<OverviewFdoCreate200Response>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.overviewFdoCreate(processId, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.overviewFdoCreate']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Resolve a pid.
+         * @param {string} pid Persistent Identifier
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async resolvePID(pid: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ResolvePID200Response>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.resolvePID(pid, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.resolvePID']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Update the current state of the FDO creation process. Use this to cancel or conclude the creation process
+         * @param {string} processId Repository ID
+         * @param {UpdateStateFdoCreateRequest} [updateStateFdoCreateRequest] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async updateStateFdoCreate(processId: string, updateStateFdoCreateRequest?: UpdateStateFdoCreateRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.updateStateFdoCreate(processId, updateStateFdoCreateRequest, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.updateStateFdoCreate']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Upload the data file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {File} body 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async uploadFdoCreateData(processId: string, body: File, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.uploadFdoCreateData(processId, body, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.uploadFdoCreateData']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary Upload the metadata file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {File} body 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async uploadFdoCreateMetadata(processId: string, body: File, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.uploadFdoCreateMetadata(processId, body, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['DefaultApi.uploadFdoCreateMetadata']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+    }
+};
+
+/**
+ * DefaultApi - factory interface
+ * @export
+ */
+export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+    const localVarFp = DefaultApiFp(configuration)
+    return {
+        /**
+         * 
+         * @summary Create an FDO.
+         * @param {TargetRepositories} repositories 
+         * @param {File} [data] 
+         * @param {File} [metadata] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        createFDO(repositories: TargetRepositories, data?: File, metadata?: File, options?: any): AxiosPromise<void> {
+            return localVarFp.createFDO(repositories, data, metadata, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Retrieve general information on the service.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getInfo(options?: any): AxiosPromise<GetInfo200Response> {
+            return localVarFp.getInfo(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Get the current state of the FDO creation process.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getStateFdoCreate(processId: string, options?: any): AxiosPromise<object> {
+            return localVarFp.getStateFdoCreate(processId, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Get the current state of the data file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getStatusFdoCreateData(processId: string, options?: any): AxiosPromise<object> {
+            return localVarFp.getStatusFdoCreateData(processId, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Get the current state of the metadata file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getStatusFdoCreateMetadata(processId: string, options?: any): AxiosPromise<object> {
+            return localVarFp.getStatusFdoCreateMetadata(processId, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Say hello to the server.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        hello(options?: any): AxiosPromise<Hello> {
+            return localVarFp.hello(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Initiate the process to create an FDO
+         * @param {CreateFDORequest} createFDORequest 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        initiateFdoCreate(createFDORequest: CreateFDORequest, options?: any): AxiosPromise<void> {
+            return localVarFp.initiateFdoCreate(createFDORequest, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Get an overview of the FDO creation process.
+         * @param {string} processId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        overviewFdoCreate(processId: string, options?: any): AxiosPromise<OverviewFdoCreate200Response> {
+            return localVarFp.overviewFdoCreate(processId, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Resolve a pid.
+         * @param {string} pid Persistent Identifier
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        resolvePID(pid: string, options?: any): AxiosPromise<ResolvePID200Response> {
+            return localVarFp.resolvePID(pid, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Update the current state of the FDO creation process. Use this to cancel or conclude the creation process
+         * @param {string} processId Repository ID
+         * @param {UpdateStateFdoCreateRequest} [updateStateFdoCreateRequest] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        updateStateFdoCreate(processId: string, updateStateFdoCreateRequest?: UpdateStateFdoCreateRequest, options?: any): AxiosPromise<object> {
+            return localVarFp.updateStateFdoCreate(processId, updateStateFdoCreateRequest, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Upload the data file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {File} body 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        uploadFdoCreateData(processId: string, body: File, options?: any): AxiosPromise<object> {
+            return localVarFp.uploadFdoCreateData(processId, body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary Upload the metadata file of the FDO.
+         * @param {string} processId Repository ID
+         * @param {File} body 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        uploadFdoCreateMetadata(processId: string, body: File, options?: any): AxiosPromise<object> {
+            return localVarFp.uploadFdoCreateMetadata(processId, body, options).then((request) => request(axios, basePath));
+        },
+    };
+};
+
+/**
+ * DefaultApi - object-oriented interface
+ * @export
+ * @class DefaultApi
+ * @extends {BaseAPI}
+ */
+export class DefaultApi extends BaseAPI {
+    /**
+     * 
+     * @summary Create an FDO.
+     * @param {TargetRepositories} repositories 
+     * @param {File} [data] 
+     * @param {File} [metadata] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public createFDO(repositories: TargetRepositories, data?: File, metadata?: File, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).createFDO(repositories, data, metadata, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Retrieve general information on the service.
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public getInfo(options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).getInfo(options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Get the current state of the FDO creation process.
+     * @param {string} processId Repository ID
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public getStateFdoCreate(processId: string, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).getStateFdoCreate(processId, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Get the current state of the data file of the FDO.
+     * @param {string} processId Repository ID
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public getStatusFdoCreateData(processId: string, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).getStatusFdoCreateData(processId, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Get the current state of the metadata file of the FDO.
+     * @param {string} processId Repository ID
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public getStatusFdoCreateMetadata(processId: string, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).getStatusFdoCreateMetadata(processId, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Say hello to the server.
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public hello(options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).hello(options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Initiate the process to create an FDO
+     * @param {CreateFDORequest} createFDORequest 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public initiateFdoCreate(createFDORequest: CreateFDORequest, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).initiateFdoCreate(createFDORequest, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Get an overview of the FDO creation process.
+     * @param {string} processId Repository ID
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public overviewFdoCreate(processId: string, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).overviewFdoCreate(processId, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Resolve a pid.
+     * @param {string} pid Persistent Identifier
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public resolvePID(pid: string, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).resolvePID(pid, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Update the current state of the FDO creation process. Use this to cancel or conclude the creation process
+     * @param {string} processId Repository ID
+     * @param {UpdateStateFdoCreateRequest} [updateStateFdoCreateRequest] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public updateStateFdoCreate(processId: string, updateStateFdoCreateRequest?: UpdateStateFdoCreateRequest, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).updateStateFdoCreate(processId, updateStateFdoCreateRequest, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Upload the data file of the FDO.
+     * @param {string} processId Repository ID
+     * @param {File} body 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public uploadFdoCreateData(processId: string, body: File, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).uploadFdoCreateData(processId, body, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary Upload the metadata file of the FDO.
+     * @param {string} processId Repository ID
+     * @param {File} body 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof DefaultApi
+     */
+    public uploadFdoCreateMetadata(processId: string, body: File, options?: RawAxiosRequestConfig) {
+        return DefaultApiFp(this.configuration).uploadFdoCreateMetadata(processId, body, options).then((request) => request(this.axios, this.basePath));
+    }
+}
+
+
+
+/**
+ * RepositoriesApi - axios parameter creator
+ * @export
+ */
+export const RepositoriesApiAxiosParamCreator = function (configuration?: Configuration) {
+    return {
+        /**
+         * 
+         * @summary Get information on a single repository.
+         * @param {string} repositoryId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getRepository: async (repositoryId: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'repositoryId' is not null or undefined
+            assertParamExists('getRepository', 'repositoryId', repositoryId)
+            const localVarPath = `/repositories/{repositoryId}`
+                .replace(`{${"repositoryId"}}`, encodeURIComponent(String(repositoryId)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary List trusted repositories.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        listRepositories: async (options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/repositories`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+    }
+};
+
+/**
+ * RepositoriesApi - functional programming interface
+ * @export
+ */
+export const RepositoriesApiFp = function(configuration?: Configuration) {
+    const localVarAxiosParamCreator = RepositoriesApiAxiosParamCreator(configuration)
+    return {
+        /**
+         * 
+         * @summary Get information on a single repository.
+         * @param {string} repositoryId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async getRepository(repositoryId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetRepository200Response>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.getRepository(repositoryId, options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['RepositoriesApi.getRepository']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+        /**
+         * 
+         * @summary List trusted repositories.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async listRepositories(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ListRepositories200Response>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.listRepositories(options);
+            const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+            const localVarOperationServerBasePath = operationServerMap['RepositoriesApi.listRepositories']?.[localVarOperationServerIndex]?.url;
+            return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+        },
+    }
+};
+
+/**
+ * RepositoriesApi - factory interface
+ * @export
+ */
+export const RepositoriesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+    const localVarFp = RepositoriesApiFp(configuration)
+    return {
+        /**
+         * 
+         * @summary Get information on a single repository.
+         * @param {string} repositoryId Repository ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        getRepository(repositoryId: string, options?: any): AxiosPromise<GetRepository200Response> {
+            return localVarFp.getRepository(repositoryId, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary List trusted repositories.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        listRepositories(options?: any): AxiosPromise<ListRepositories200Response> {
+            return localVarFp.listRepositories(options).then((request) => request(axios, basePath));
+        },
+    };
+};
+
+/**
+ * RepositoriesApi - object-oriented interface
+ * @export
+ * @class RepositoriesApi
+ * @extends {BaseAPI}
+ */
+export class RepositoriesApi extends BaseAPI {
+    /**
+     * 
+     * @summary Get information on a single repository.
+     * @param {string} repositoryId Repository ID
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof RepositoriesApi
+     */
+    public getRepository(repositoryId: string, options?: RawAxiosRequestConfig) {
+        return RepositoriesApiFp(this.configuration).getRepository(repositoryId, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * 
+     * @summary List trusted repositories.
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof RepositoriesApi
+     */
+    public listRepositories(options?: RawAxiosRequestConfig) {
+        return RepositoriesApiFp(this.configuration).listRepositories(options).then((request) => request(this.axios, this.basePath));
+    }
+}
+
+
+
diff --git a/src/api/base.ts b/src/api/base.ts
new file mode 100644
index 0000000000000000000000000000000000000000..78b555a5bbdea94f2117d09ff016d5d2c12e9cfe
--- /dev/null
+++ b/src/api/base.ts
@@ -0,0 +1,86 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FDO Manager Service API
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1
+ * 
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+import type { Configuration } from './configuration';
+// Some imports not used depending on template conditions
+// @ts-ignore
+import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
+import globalAxios from 'axios';
+
+export const BASE_PATH = "http://localhost:8080".replace(/\/+$/, "");
+
+/**
+ *
+ * @export
+ */
+export const COLLECTION_FORMATS = {
+    csv: ",",
+    ssv: " ",
+    tsv: "\t",
+    pipes: "|",
+};
+
+/**
+ *
+ * @export
+ * @interface RequestArgs
+ */
+export interface RequestArgs {
+    url: string;
+    options: RawAxiosRequestConfig;
+}
+
+/**
+ *
+ * @export
+ * @class BaseAPI
+ */
+export class BaseAPI {
+    protected configuration: Configuration | undefined;
+
+    constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
+        if (configuration) {
+            this.configuration = configuration;
+            this.basePath = configuration.basePath ?? basePath;
+        }
+    }
+};
+
+/**
+ *
+ * @export
+ * @class RequiredError
+ * @extends {Error}
+ */
+export class RequiredError extends Error {
+    constructor(public field: string, msg?: string) {
+        super(msg);
+        this.name = "RequiredError"
+    }
+}
+
+interface ServerMap {
+    [key: string]: {
+        url: string,
+        description: string,
+    }[];
+}
+
+/**
+ *
+ * @export
+ */
+export const operationServerMap: ServerMap = {
+}
diff --git a/src/api/common.ts b/src/api/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e97d5bff68a02511621c8f102eb9371944ccf99c
--- /dev/null
+++ b/src/api/common.ts
@@ -0,0 +1,150 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FDO Manager Service API
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1
+ * 
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+import type { Configuration } from "./configuration";
+import type { RequestArgs } from "./base";
+import type { AxiosInstance, AxiosResponse } from 'axios';
+import { RequiredError } from "./base";
+
+/**
+ *
+ * @export
+ */
+export const DUMMY_BASE_URL = 'https://example.com'
+
+/**
+ *
+ * @throws {RequiredError}
+ * @export
+ */
+export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) {
+    if (paramValue === null || paramValue === undefined) {
+        throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`);
+    }
+}
+
+/**
+ *
+ * @export
+ */
+export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) {
+    if (configuration && configuration.apiKey) {
+        const localVarApiKeyValue = typeof configuration.apiKey === 'function'
+            ? await configuration.apiKey(keyParamName)
+            : await configuration.apiKey;
+        object[keyParamName] = localVarApiKeyValue;
+    }
+}
+
+/**
+ *
+ * @export
+ */
+export const setBasicAuthToObject = function (object: any, configuration?: Configuration) {
+    if (configuration && (configuration.username || configuration.password)) {
+        object["auth"] = { username: configuration.username, password: configuration.password };
+    }
+}
+
+/**
+ *
+ * @export
+ */
+export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) {
+    if (configuration && configuration.accessToken) {
+        const accessToken = typeof configuration.accessToken === 'function'
+            ? await configuration.accessToken()
+            : await configuration.accessToken;
+        object["Authorization"] = "Bearer " + accessToken;
+    }
+}
+
+/**
+ *
+ * @export
+ */
+export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) {
+    if (configuration && configuration.accessToken) {
+        const localVarAccessTokenValue = typeof configuration.accessToken === 'function'
+            ? await configuration.accessToken(name, scopes)
+            : await configuration.accessToken;
+        object["Authorization"] = "Bearer " + localVarAccessTokenValue;
+    }
+}
+
+function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void {
+    if (parameter == null) return;
+    if (typeof parameter === "object") {
+        if (Array.isArray(parameter)) {
+            (parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
+        } 
+        else {
+            Object.keys(parameter).forEach(currentKey => 
+                setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
+            );
+        }
+    } 
+    else {
+        if (urlSearchParams.has(key)) {
+            urlSearchParams.append(key, parameter);
+        } 
+        else {
+            urlSearchParams.set(key, parameter);
+        }
+    }
+}
+
+/**
+ *
+ * @export
+ */
+export const setSearchParams = function (url: URL, ...objects: any[]) {
+    const searchParams = new URLSearchParams(url.search);
+    setFlattenedQueryParams(searchParams, objects);
+    url.search = searchParams.toString();
+}
+
+/**
+ *
+ * @export
+ */
+export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) {
+    const nonString = typeof value !== 'string';
+    const needsSerialization = nonString && configuration && configuration.isJsonMime
+        ? configuration.isJsonMime(requestOptions.headers['Content-Type'])
+        : nonString;
+    return needsSerialization
+        ? JSON.stringify(value !== undefined ? value : {})
+        : (value || "");
+}
+
+/**
+ *
+ * @export
+ */
+export const toPathString = function (url: URL) {
+    return url.pathname + url.search + url.hash
+}
+
+/**
+ *
+ * @export
+ */
+export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
+    return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+        const axiosRequestArgs = {...axiosArgs.options, url: (axios.defaults.baseURL ? '' : configuration?.basePath ?? basePath) + axiosArgs.url};
+        return axios.request<T, R>(axiosRequestArgs);
+    };
+}
diff --git a/src/api/configuration.ts b/src/api/configuration.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cc56d0239aa38c10cee9f1a074c1ad27514f82f6
--- /dev/null
+++ b/src/api/configuration.ts
@@ -0,0 +1,110 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FDO Manager Service API
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1
+ * 
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+export interface ConfigurationParameters {
+    apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
+    username?: string;
+    password?: string;
+    accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
+    basePath?: string;
+    serverIndex?: number;
+    baseOptions?: any;
+    formDataCtor?: new () => any;
+}
+
+export class Configuration {
+    /**
+     * parameter for apiKey security
+     * @param name security name
+     * @memberof Configuration
+     */
+    apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
+    /**
+     * parameter for basic security
+     *
+     * @type {string}
+     * @memberof Configuration
+     */
+    username?: string;
+    /**
+     * parameter for basic security
+     *
+     * @type {string}
+     * @memberof Configuration
+     */
+    password?: string;
+    /**
+     * parameter for oauth2 security
+     * @param name security name
+     * @param scopes oauth2 scope
+     * @memberof Configuration
+     */
+    accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
+    /**
+     * override base path
+     *
+     * @type {string}
+     * @memberof Configuration
+     */
+    basePath?: string;
+    /**
+     * override server index
+     *
+     * @type {number}
+     * @memberof Configuration
+     */
+    serverIndex?: number;
+    /**
+     * base options for axios calls
+     *
+     * @type {any}
+     * @memberof Configuration
+     */
+    baseOptions?: any;
+    /**
+     * The FormData constructor that will be used to create multipart form data
+     * requests. You can inject this here so that execution environments that
+     * do not support the FormData class can still run the generated client.
+     *
+     * @type {new () => FormData}
+     */
+    formDataCtor?: new () => any;
+
+    constructor(param: ConfigurationParameters = {}) {
+        this.apiKey = param.apiKey;
+        this.username = param.username;
+        this.password = param.password;
+        this.accessToken = param.accessToken;
+        this.basePath = param.basePath;
+        this.serverIndex = param.serverIndex;
+        this.baseOptions = param.baseOptions;
+        this.formDataCtor = param.formDataCtor;
+    }
+
+    /**
+     * Check if the given MIME is a JSON MIME.
+     * JSON MIME examples:
+     *   application/json
+     *   application/json; charset=UTF8
+     *   APPLICATION/JSON
+     *   application/vnd.company+json
+     * @param mime - MIME (Multipurpose Internet Mail Extensions)
+     * @return True if the given MIME is JSON, false otherwise.
+     */
+    public isJsonMime(mime: string): boolean {
+        const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
+        return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
+    }
+}
diff --git a/src/api/git_push.sh b/src/api/git_push.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f53a75d4fabe760cce49eddfd62fcc702938ea90
--- /dev/null
+++ b/src/api/git_push.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
+#
+# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
+
+git_user_id=$1
+git_repo_id=$2
+release_note=$3
+git_host=$4
+
+if [ "$git_host" = "" ]; then
+    git_host="github.com"
+    echo "[INFO] No command line input provided. Set \$git_host to $git_host"
+fi
+
+if [ "$git_user_id" = "" ]; then
+    git_user_id="GIT_USER_ID"
+    echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
+fi
+
+if [ "$git_repo_id" = "" ]; then
+    git_repo_id="GIT_REPO_ID"
+    echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
+fi
+
+if [ "$release_note" = "" ]; then
+    release_note="Minor update"
+    echo "[INFO] No command line input provided. Set \$release_note to $release_note"
+fi
+
+# Initialize the local directory as a Git repository
+git init
+
+# Adds the files in the local repository and stages them for commit.
+git add .
+
+# Commits the tracked changes and prepares them to be pushed to a remote repository.
+git commit -m "$release_note"
+
+# Sets the new remote
+git_remote=$(git remote)
+if [ "$git_remote" = "" ]; then # git remote not defined
+
+    if [ "$GIT_TOKEN" = "" ]; then
+        echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
+        git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
+    else
+        git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
+    fi
+
+fi
+
+git pull origin master
+
+# Pushes (Forces) the changes in the local repository up to the remote repository
+echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
+git push origin master 2>&1 | grep -v 'To https'
diff --git a/src/api/index.ts b/src/api/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4e2f60d5034ada947d9aacb2ea429638c108c8d6
--- /dev/null
+++ b/src/api/index.ts
@@ -0,0 +1,18 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FDO Manager Service API
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1
+ * 
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+export * from "./api";
+export * from "./configuration";
+
diff --git a/src/components/ErrorComponent.tsx b/src/components/ErrorComponent.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..81c133819f8a34e25922e24609131899fc40f5b3
--- /dev/null
+++ b/src/components/ErrorComponent.tsx
@@ -0,0 +1,88 @@
+import React, { useEffect, useState } from "react";
+import { useGo, useResource, useRouterType } from "@refinedev/core";
+import { RefineErrorPageProps } from "@refinedev/ui-types";
+import { useNavigation, useTranslate } from "@refinedev/core";
+
+import Stack from "@mui/material/Stack";
+import Button from "@mui/material/Button";
+import Tooltip from "@mui/material/Tooltip";
+import Typography from "@mui/material/Typography";
+import Grid from "@mui/material/Grid";
+
+import Info from "@mui/icons-material/Info";
+
+export const ErrorComponent: React.FC<RefineErrorPageProps> = ({status=404, back=undefined}) => {
+    //const [errorMessage, setErrorMessage] = useState<string>();
+    const { push } = useNavigation();
+    const go = useGo();
+    const routerType = useRouterType();
+
+    //const { resource, action } = useResource();
+
+    const translate = useTranslate();
+
+    /*
+    useEffect(() => {
+        if (resource && action) {
+            setErrorMessage(
+                translate(
+                    "pages.error.info",
+                    {
+                        action,
+                        resource: resource?.name,
+                    },
+                    `You may have forgotten to add the "${action}" component to "${resource?.name}" resource.`,
+                ),
+            );
+        }
+    }, [action, resource]);
+    */
+
+    return (
+        <Grid
+            display="flex"
+            justifyContent="center"
+            alignItems="center"
+            mt={20}
+        >
+            <Grid
+                container
+                direction="column"
+                display="flex"
+                alignItems="center"
+            >
+                <Typography variant="h1">{status}</Typography>
+                <Stack direction="row" spacing="2">
+                    <Typography>
+                        {translate(
+                            "pages.error.404",
+                            "Sorry, the page you visited does not exist.",
+                        )}
+                    </Typography>
+
+                    {/*
+                    {errorMessage && (
+                        <Tooltip title={errorMessage}>
+                            <Info data-testid="error-component-tooltip" />
+                        </Tooltip>
+                    )}
+                    */}
+                </Stack>
+                { back &&
+                  <Button
+                      onClick={() => {
+                          if (routerType === "legacy") {
+                              push(back);
+                          } else {
+                              go({ to: back });
+                          }
+                      }}
+                  >
+                      {translate("pages.error.backHome", "Back Home")}
+                  </Button>
+                }
+            </Grid>
+        </Grid>
+    );
+};
+
diff --git a/src/components/fdos/create.tsx b/src/components/fdos/create.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b4dfa9ab8aefc850643cdf1f6e433d656599319e
--- /dev/null
+++ b/src/components/fdos/create.tsx
@@ -0,0 +1,202 @@
+import { IResourceComponentsProps } from "@refinedev/core";
+import { useList, HttpError } from "@refinedev/core";
+import { Create, SaveButton } from "@refinedev/mui";
+import { useTheme } from "@mui/material/styles";
+
+import Box from "@mui/material/Box";
+import TextField from "@mui/material/TextField";
+import InputLabel from '@mui/material/InputLabel';
+import Typography from "@mui/material/Typography";
+import Autocomplete from "@mui/material/Autocomplete";
+import Button from "@mui/material/Button";
+import Step from "@mui/material/Step";
+import StepButton from "@mui/material/StepButton";
+import Stepper from "@mui/material/Stepper";
+import MenuItem from '@mui/material/MenuItem';
+import Select, { SelectChangeEvent } from '@mui/material/Select';
+import FormHelperText from '@mui/material/FormHelperText';
+import FormControl from '@mui/material/FormControl';
+import useMediaQuery from "@mui/material/useMediaQuery";
+import { styled } from '@mui/material/styles';
+import CloudUploadIcon from '@mui/icons-material/CloudUpload';
+
+import { useStepsForm } from "@refinedev/react-hook-form";
+
+import { Controller } from "react-hook-form";
+
+import { IRepository } from "../../interfaces";
+import { RepositoriesList } from "../repositories";
+
+const stepTitles = ["Repository", "Metadata", "Data"];
+
+
+
+const StepRepository: React.FC<IResourceComponentsProps> = ({control, register, errors}) => {
+
+  const { data, isLoading, isError } = useList<IRepository, HttpError>({
+    resource: "repositories"
+  });
+  if (isLoading) {
+    return "Loading";
+  }
+  return (
+    <FormControl fullWidth>
+      <InputLabel id="repository-select-label">Repository</InputLabel>
+        <Controller control={control}
+          rules={{required: "This field is required"}}
+          name="repository"
+          render={({field}) => {
+            return (
+              <Select
+                {...field}
+                error={!!errors.repository}
+                labelId="repository-select-label"
+                id="repository-select"
+                label="Repository"
+              >
+                { data.data.map((item, idx) => <MenuItem key={idx} value={item.id}>{item.id}</MenuItem>)}
+              </Select>
+
+          )}}/>
+      <FormHelperText>{errors.repository?.message}</FormHelperText>
+    </FormControl>
+  );
+}
+
+interface IRepositoryFormValues {
+    repository: string
+}
+
+const VisuallyHiddenInput = styled('input')({
+  clip: 'rect(0 0 0 0)',
+  clipPath: 'inset(50%)',
+  height: 1,
+  overflow: 'hidden',
+  position: 'absolute',
+  bottom: 0,
+  left: 0,
+  whiteSpace: 'nowrap',
+  width: 1,
+});
+
+
+const StepMetadata: React.FC<IResourceComponentsProps> = ({control, register, errors}) => {
+    return <FileUpload register={register} errors={errors} name="fdo_metadata" label="Upload metadata file"/>
+}
+
+
+const FileUpload: React.FC<IResourceComponentsProps> = ({register, errors, name, label}) => {
+
+
+  return (
+    <FormControl error={!!errors[name]} fullWidth>
+    <span>
+          <Button
+            component="label"
+            role={undefined}
+            variant="contained"
+            tabIndex={-1}
+            startIcon={<CloudUploadIcon />}
+          >
+          {label}
+      <VisuallyHiddenInput {...register(name, {required: "This field is required."})} type="file"/>
+      </Button>
+      </span>
+      <FormHelperText>{errors[name]?.message}</FormHelperText>
+    </FormControl>
+  );
+}
+
+const StepData: React.FC<IResourceComponentsProps> = ({register, errors}) => {
+    return <FileUpload register={register} errors={errors} name="fdo_data" label="Upload data file"/>
+}
+
+export const FdoCreate: React.FC<IResourceComponentsProps> = () => {
+  const {
+    saveButtonProps,
+    refineCore: { formLoading, onFinish },
+    register,
+    handleSubmit,
+    control,
+    formState: { errors },
+    steps: { currentStep, gotoStep },
+  } = useStepsForm<IRepository, HttpError, IRepositoryFormValues>({defaultValues: {repository: ""}});
+
+  const onSubmit = (data) => {
+      console.log("data", data);
+
+      onFinish([{ fdo: data.repository }, data.fdo_data[0], data.fdo_metadata[0]]);
+  }
+  const theme = useTheme();
+  const isSmallOrLess = useMediaQuery(theme.breakpoints.down("sm"));
+
+  const renderFormByStep = (step: number) => {
+    switch (step) {
+      case 0:
+        return (
+          <StepRepository control={control} register={register} errors={errors}/>
+        );
+      case 1:
+        return (
+          <StepMetadata control={control} register={register} errors={errors}/>
+        );
+      case 2:
+        return (
+          <StepData control={control} register={register} errors={errors}/>
+        );
+    }
+  };
+
+  return (
+    <Create
+      title={<Typography variant="h5">Create FDO</Typography>}
+      isLoading={formLoading}
+      saveButtonProps={saveButtonProps}
+      footerButtons={
+        <>
+          {currentStep > 0 && (
+            <Button
+              onClick={() => {
+                gotoStep(currentStep - 1);
+              }}
+            >
+              Previous
+            </Button>
+          )}
+          {currentStep < stepTitles.length - 1 && (
+            <Button
+              onClick={() => {
+                gotoStep(currentStep + 1);
+              }}
+            >
+              Next
+            </Button>
+          )}
+          {currentStep === stepTitles.length - 1 && (
+            <SaveButton onClick={handleSubmit(onSubmit)} />
+          )}
+        </>
+      }
+    >
+      <Box
+        component="form"
+        sx={{ display: "flex", flexDirection: "column" }}
+        autoComplete="off"
+      >
+        <Stepper
+          nonLinear
+          activeStep={currentStep}
+          orientation={isSmallOrLess ? "vertical" : "horizontal"}
+        >
+          {stepTitles.map((label, index) => (
+            <Step key={label}>
+              <StepButton onClick={() => gotoStep(index)}>{label}</StepButton>
+            </Step>
+          ))}
+        </Stepper>
+        <br />
+        {renderFormByStep(currentStep)}
+      </Box>
+    </Create>
+  );
+};
diff --git a/src/components/fdos/index.ts b/src/components/fdos/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6262006e3197dfeaecd04da42fb01ef618816cf
--- /dev/null
+++ b/src/components/fdos/index.ts
@@ -0,0 +1 @@
+export * from "./create";
diff --git a/src/components/repositories/index.ts b/src/components/repositories/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..36a92846e2d7c427fc6d9ba205a29ccb7c113231
--- /dev/null
+++ b/src/components/repositories/index.ts
@@ -0,0 +1,2 @@
+export * from "./list";
+export * from "./show";
diff --git a/src/components/repositories/list.tsx b/src/components/repositories/list.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7cda314266d3bdf521d754eb77f844f05670f669
--- /dev/null
+++ b/src/components/repositories/list.tsx
@@ -0,0 +1,29 @@
+import { IResourceComponentsProps } from "@refinedev/core";
+import { MuiInferencer } from "@refinedev/inferencer/mui";
+
+import { List, useDataGrid } from "@refinedev/mui";
+
+import {
+    DataGrid,
+    GridColDef,
+    GridValueFormatterParams,
+} from "@mui/x-data-grid";
+
+import IRepository from "../interfaces/IRepository";
+
+
+const columns: GridColDef<IRepository>[] = [
+  { field: "id", headerName: "ID", type: "string", width: 200, renderCell: (params) => {
+    return <a href={"./repositories/" + params.value}>{params.value}</a>
+  }},
+];
+
+export const RepositoriesList: React.FC<IResourceComponentsProps> = ({repositories}) => {
+ const { dataGridProps } = useDataGrid<IRepository>();
+
+  return (
+    <List>
+      <DataGrid {...dataGridProps} columns={columns} autoHeight />
+    </List>
+  );
+};
diff --git a/src/components/repositories/show.tsx b/src/components/repositories/show.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..584c2cf78e833173dc3e13f507172542c3b426f3
--- /dev/null
+++ b/src/components/repositories/show.tsx
@@ -0,0 +1,6 @@
+import { IResourceComponentsProps } from "@refinedev/core";
+import { MuiInferencer } from "@refinedev/inferencer/mui";
+
+export const RepositoriesShow: React.FC<IResourceComponentsProps> = () => {
+    return <MuiInferencer />;
+};
diff --git a/src/constants.js b/src/constants.js
new file mode 100644
index 0000000000000000000000000000000000000000..fadcae5d33b2b7949ec9df75dc44174360016c9c
--- /dev/null
+++ b/src/constants.js
@@ -0,0 +1,3 @@
+import { version } from "./version";
+export const API_URL = process.env.NEXT_PUBLIC_API_URL || "/api";
+export const FDO_MANAGER_WEBUI_VERSION = version;
diff --git a/src/interfaces/IRepository.tsx b/src/interfaces/IRepository.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e24e81a5039ea7844dd8dea693e01caad802256b
--- /dev/null
+++ b/src/interfaces/IRepository.tsx
@@ -0,0 +1,3 @@
+default export interface IRepository {
+  id: string;
+}
diff --git a/src/interfaces/index.d.ts b/src/interfaces/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cf81a18a5bcd43492b2bd10f0fec87a4f5b5214a
--- /dev/null
+++ b/src/interfaces/index.d.ts
@@ -0,0 +1 @@
+export * from "./IRepository";
diff --git a/src/providers/dataProvider.tsx b/src/providers/dataProvider.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f39901a636be3b90cea71db6549614b3c84a2b1f
--- /dev/null
+++ b/src/providers/dataProvider.tsx
@@ -0,0 +1,83 @@
+import { DataProvider, useOne } from "@refinedev/core";
+import dataProvider from "@refinedev/simple-rest";
+import { Configuration, RepositoriesApi, DefaultApi, GetInfo200Response, ListRepositories200Response} from "../api";
+import axios from "axios";
+
+const getNewlyCreated = async (newLocation) => {
+  return await axios.get(newLocation);
+}
+
+const apiDataProvider = (apiUrl: string): DataProvider => {
+  const config:Configuration = new Configuration({basePath: apiUrl});
+  const apiResources = {
+      "default": new DefaultApi(config),
+      "repositories": new RepositoriesApi(config),
+  }
+
+  const apiOperations = {
+      "repositories": {
+          "list": apiResources["repositories"].listRepositories,
+          "get": apiResources["repositories"].getRepository,
+      },
+      "info": {
+          "get": apiResources["default"].getInfo,
+      },
+      "fdo": {
+          "get": apiResources["default"].resolvePID,
+          "create": apiResources["default"].createFDO,
+      }
+  }
+
+  const callOperation = async (resource, operation, kwargs) => {
+      const resourceObj = apiResources[resource] || apiResources["default"];
+      const func = apiOperations[resource][operation];
+      if (func && ( operation === "get" || operation === "list")) {
+          if (kwargs.id) {
+              return (await func.apply(resourceObj, [kwargs.id])).data;
+          } else {
+              return (await func.apply(resourceObj)).data;
+          }
+      } else if (func && operation === "create") {
+          return await func.apply(resourceObj, kwargs.variables);
+      }
+      throw new Error("Not implemented");
+  }
+
+  const _fallBack = dataProvider(apiUrl);
+
+  return  {
+      getOne: async ({resource, id, meta}) => {
+          console.log("getOne", resource, id, meta);
+          const data = await callOperation(resource, "get", {id, meta});
+          return { data: data.data };
+      },
+      create: async ({resource, variables, meta}) => {
+          console.log("create", resource, variables);
+          const response = await callOperation(resource, "create", {variables});
+          if (response.status === 201) {
+              const newLocation = response.headers.location;
+              console.log("newLocation", newLocation);
+              const newData = await getNewlyCreated(newLocation);
+              console.log("newData", newData);
+
+
+          } else {
+              // TODO
+          }
+          console.log("create.response", response);
+      },
+      update: async () => {
+          throw new Error("Not implemented");
+      },
+      deleteOne: async () => {
+          throw new Error("Not implemented");
+      },
+      getList: async ({ resource, pagination, sorters, filters, meta }) => {
+          const data = (await callOperation(resource, "list", {pagination, sorters, filters, meta})).data;
+          return {data: data, total: data.length }
+      },
+      getApiUrl: () => apiUrl,
+  };
+};
+
+export default apiDataProvider;
diff --git a/src/version.js b/src/version.js
new file mode 100644
index 0000000000000000000000000000000000000000..418f9935746149d46f9c17f443de636d122737e3
--- /dev/null
+++ b/src/version.js
@@ -0,0 +1 @@
+export const version="0.1.0";