inital commit
This commit is contained in:
commit
80e708d05a
|
@ -0,0 +1 @@
|
|||
/target
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
[package]
|
||||
name = "starchart"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
axum = "0.6"
|
||||
aide = { version = "0.11", features = [
|
||||
"axum",
|
||||
"axum-extra",
|
||||
"redoc",
|
||||
"macros",
|
||||
"axum-ws",
|
||||
"axum-multipart",
|
||||
"axum-headers",
|
||||
"axum-extra-cookie",
|
||||
"axum-extra-cookie-private",
|
||||
"axum-extra-form",
|
||||
"axum-extra-query",
|
||||
] }
|
||||
rust-embed = { version = "8" }
|
||||
confy = "0.5"
|
||||
schemars = { version = "0.8", features = ["derive_json_schema", "uuid1"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = [
|
||||
"env-filter",
|
||||
"fmt",
|
||||
"ansi",
|
||||
] }
|
||||
once_cell = "1"
|
||||
sqlx = { version = "0.7", features = ["runtime-tokio", "tls-rustls", "postgres", "macros"] }
|
||||
serde = "1.0.186"
|
||||
serde_derive = "1.0.186"
|
||||
axum-jsonschema = { version = "0.6.0", features = ["aide"] }
|
||||
axum-macros = "0.3.8"
|
||||
tinyrand = "0.5.0"
|
||||
tinyrand-std = "0.5.0"
|
||||
mime_guess = "2.0.4"
|
||||
hyper = "0.14.27"
|
|
@ -0,0 +1,5 @@
|
|||
// generated by `sqlx migrate build-script`
|
||||
fn main() {
|
||||
// trigger recompilation when a new migration is added
|
||||
println!("cargo:rerun-if-changed=migrations");
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
create table stars (
|
||||
id Integer Primary Key Generated Always as Identity,
|
||||
color varchar(7) not null
|
||||
);
|
||||
|
||||
alter table stars
|
||||
add constraint color_hex_constraint
|
||||
check (color ~* '^#[a-f0-9]{2}[a-f0-9]{2}[a-f0-9]{2}$');
|
|
@ -0,0 +1,18 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub db_url: String,
|
||||
}
|
||||
|
||||
pub static CONFIG: Lazy<Config> =
|
||||
Lazy::new(|| confy::load("starchart", Some("config")).expect("failed to load config"));
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
db_url: "postgres://starchart:hunter2@localhost/starchart".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
static DB_CONN: OnceCell<PgPool> = OnceCell::const_new();
|
||||
|
||||
pub async fn pool() -> &'static sqlx::postgres::PgPool {
|
||||
DB_CONN
|
||||
.get_or_init(|| async {
|
||||
PgPoolOptions::new()
|
||||
.min_connections(1)
|
||||
.max_connections(5)
|
||||
.connect(&crate::config::CONFIG.db_url)
|
||||
.await
|
||||
.expect("failed to connect to database")
|
||||
})
|
||||
.await
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use aide::{
|
||||
axum::{routing::get, ApiRouter, IntoApiResponse},
|
||||
openapi::OpenApi,
|
||||
redoc::Redoc,
|
||||
};
|
||||
use axum::{response::IntoResponse, Extension};
|
||||
|
||||
use crate::extractors::Json;
|
||||
|
||||
pub fn routes() -> ApiRouter {
|
||||
ApiRouter::new()
|
||||
.route("/openapi.json", get(openapi_json))
|
||||
.route(
|
||||
"/",
|
||||
get(Redoc::new("/docs/openapi.json")
|
||||
.with_title("starchart docs")
|
||||
.axum_handler()),
|
||||
)
|
||||
}
|
||||
|
||||
async fn openapi_json(Extension(api): Extension<Arc<OpenApi>>) -> impl IntoApiResponse {
|
||||
Json(api).into_response()
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
use aide::operation::OperationIo;
|
||||
use axum_macros::FromRequest;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(OperationIo, FromRequest)]
|
||||
#[from_request(via(axum_jsonschema::Json))]
|
||||
#[aide(
|
||||
input_with = "axum_jsonschema::Json<T>",
|
||||
output_with = "axum_jsonschema::Json<T>",
|
||||
json_schema
|
||||
)]
|
||||
pub struct Json<T>(pub T);
|
||||
|
||||
impl<T> axum::response::IntoResponse for Json<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
axum::Json(self.0).into_response()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
use aide::axum::ApiRouter;
|
||||
use axum::{
|
||||
body::{boxed, Full},
|
||||
response::{Html, IntoResponse, Response},
|
||||
routing::get,
|
||||
};
|
||||
use hyper::{header, StatusCode, Uri};
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
pub fn routes() -> ApiRouter {
|
||||
ApiRouter::new()
|
||||
.route("/*file", get(static_handler))
|
||||
.route("/", get(index))
|
||||
}
|
||||
|
||||
async fn index() -> Html<&'static str> {
|
||||
Html(include_str!("../web/dist/index.html"))
|
||||
}
|
||||
|
||||
async fn static_handler(uri: Uri) -> impl IntoResponse {
|
||||
let path = uri.path().trim_start_matches('/');
|
||||
|
||||
if path.starts_with("/api/") {
|
||||
return StatusCode::NOT_FOUND.into_response();
|
||||
}
|
||||
|
||||
match Assets::get(path) {
|
||||
Some(v) => {
|
||||
tracing::debug!("found file: {}", path);
|
||||
let body = boxed(Full::from(v.data));
|
||||
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
||||
|
||||
Response::builder()
|
||||
.header(header::CONTENT_TYPE, mime.as_ref())
|
||||
.body(body)
|
||||
.unwrap()
|
||||
}
|
||||
// return index.html, vue router will handle the rest
|
||||
None => index().await.into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "web/dist/"]
|
||||
struct Assets;
|
|
@ -0,0 +1,56 @@
|
|||
use aide::{axum::ApiRouter, openapi::OpenApi};
|
||||
use axum::Extension;
|
||||
use std::{
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
sync::Arc,
|
||||
};
|
||||
use tracing::info;
|
||||
use tracing_subscriber::fmt::SubscriberBuilder;
|
||||
|
||||
pub mod config;
|
||||
pub mod db;
|
||||
pub mod docs;
|
||||
pub mod extractors;
|
||||
mod frontend;
|
||||
pub mod stars;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
SubscriberBuilder::default().pretty().init();
|
||||
info!("running migrations! please wait...");
|
||||
sqlx::migrate!("./migrations").run(db::pool().await).await?;
|
||||
info!("migrations done! 😎");
|
||||
start_server().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn generate_server() -> Result<axum::Router, Box<dyn std::error::Error>> {
|
||||
aide::gen::on_error(|error| panic!("{}", error));
|
||||
aide::gen::extract_schemas(true);
|
||||
let mut open_api = OpenApi::default();
|
||||
aide::gen::on_error(|error| panic!("{}", error));
|
||||
Ok(ApiRouter::new()
|
||||
.nest_api_service("/api/v1/stars", stars::routes())
|
||||
.nest_api_service("/docs", docs::routes())
|
||||
.nest_api_service("/", frontend::routes())
|
||||
.finish_api_with(&mut open_api, |docs| {
|
||||
docs.title("starchart")
|
||||
.summary("now you can discover a star!")
|
||||
.contact(aide::openapi::Contact {
|
||||
name: Some("zoe".into()),
|
||||
url: Some("https://zoe.kittycat.homes".into()),
|
||||
..Default::default()
|
||||
})
|
||||
.version("0.1.0")
|
||||
})
|
||||
.layer(Extension(Arc::new(open_api))))
|
||||
}
|
||||
|
||||
async fn start_server() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let app = generate_server().await?;
|
||||
let addr = SocketAddr::new(std::net::IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7056);
|
||||
axum::Server::bind(&addr)
|
||||
.serve(app.into_make_service())
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
use aide::axum::{
|
||||
routing::{get_with, post_with},
|
||||
ApiRouter,
|
||||
};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
http::StatusCode,
|
||||
Json,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
|
||||
mod size;
|
||||
|
||||
pub fn routes() -> ApiRouter {
|
||||
ApiRouter::new()
|
||||
.api_route(
|
||||
"/discover",
|
||||
post_with(discover, |docs| {
|
||||
docs.response::<200, Json<Star>>()
|
||||
.summary("add a new planet")
|
||||
.id("discover")
|
||||
.tag("stars")
|
||||
}),
|
||||
)
|
||||
.api_route(
|
||||
"/chart",
|
||||
get_with(chart, |docs| {
|
||||
docs.response::<200, Json<Vec<Protostar>>>()
|
||||
.summary("the whole chart")
|
||||
.id("chart")
|
||||
.tag("stars")
|
||||
}),
|
||||
)
|
||||
.api_route_with(
|
||||
"/visit/",
|
||||
get_with(visit, |docs| {
|
||||
docs.response::<200, Json<Star>>()
|
||||
.summary("visit a single planet")
|
||||
.id("visit")
|
||||
.tag("stars")
|
||||
}),
|
||||
|docs| docs,
|
||||
)
|
||||
}
|
||||
|
||||
/// this gets stored in the db,
|
||||
/// the other stuff is generated using
|
||||
/// the id as a seed
|
||||
#[derive(Serialize, FromRow, Clone, Deserialize, JsonSchema)]
|
||||
pub struct Protostar {
|
||||
pub id: i32,
|
||||
/// hex code of the stars color
|
||||
pub color: String,
|
||||
}
|
||||
|
||||
impl Protostar {
|
||||
fn seed(&self) -> u64 {
|
||||
self.id.abs() as u64
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct Star {
|
||||
pub size: size::Size,
|
||||
pub core: Protostar,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct DiscoveryLog {
|
||||
pub color: String,
|
||||
}
|
||||
|
||||
impl Into<Star> for Protostar {
|
||||
fn into(self) -> Star {
|
||||
let seed = self.seed();
|
||||
Star {
|
||||
core: self,
|
||||
size: size::Size::random(seed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// discover a new star in the solar system
|
||||
async fn discover(Json(log): Json<DiscoveryLog>) -> Result<Json<Star>, StatusCode> {
|
||||
let query = "INSERT INTO stars (color) VALUES ($1) RETURNING id, color";
|
||||
|
||||
let protostar: Protostar = sqlx::query_as(query)
|
||||
.bind(log.color)
|
||||
.fetch_one(crate::db::pool().await)
|
||||
.await
|
||||
.or(Err(StatusCode::INTERNAL_SERVER_ERROR))?;
|
||||
let star: Star = protostar.into();
|
||||
Ok(Json(star))
|
||||
}
|
||||
|
||||
/// show all stars
|
||||
async fn chart() -> Json<Vec<Protostar>> {
|
||||
let query = "SELECT * FROM stars ORDER BY id DESC";
|
||||
let protostars: Vec<Protostar> = sqlx::query_as(query)
|
||||
.fetch_all(crate::db::pool().await)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
Json(protostars)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
struct VisitorData {
|
||||
/// the planet to visit
|
||||
planet_id: i32,
|
||||
}
|
||||
|
||||
async fn visit(data: Query<VisitorData>) -> Result<Json<Star>, StatusCode> {
|
||||
let query = "SELECT * FROM stars WHERE id = ($1)";
|
||||
let star: Protostar = sqlx::query_as(query)
|
||||
.bind(data.planet_id)
|
||||
.fetch_one(crate::db::pool().await)
|
||||
.await
|
||||
.unwrap();
|
||||
//.or(Err(StatusCode::NOT_FOUND))?;
|
||||
let star: Star = star.into();
|
||||
Ok(Json(star))
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
use tinyrand::{RandRange, Seeded, StdRand};
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(JsonSchema, Serialize, Deserialize)]
|
||||
pub struct Size {
|
||||
pub small_item_multiplier: u8,
|
||||
pub large_item_multiplier: u8,
|
||||
pub small_item: String,
|
||||
pub large_item: String,
|
||||
}
|
||||
|
||||
impl Size {
|
||||
pub fn random(seed: u64) -> Self {
|
||||
let mut rand = StdRand::seed(seed);
|
||||
|
||||
// multipliers:
|
||||
// this planet is as large as 10 x item
|
||||
let small_item_multiplier: usize = rand.next_range(1..100);
|
||||
let large_item_multiplier: usize = rand.next_range(1..100);
|
||||
Self {
|
||||
small_item_multiplier: small_item_multiplier as u8,
|
||||
large_item_multiplier: large_item_multiplier as u8,
|
||||
small_item: "rats".into(),
|
||||
large_item: "ohios".into(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
|
@ -0,0 +1,19 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/typescript/recommended",
|
||||
"plugin:prettier/recommended",
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
},
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
},
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -0,0 +1,24 @@
|
|||
# starchart
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "starchart",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"swagger-gen": "rm -rf ./src/swagger && openapi-generator-cli generate -g typescript-fetch -i http://localhost:7056/docs/openapi.json -o src/swagger/"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.8.3",
|
||||
"vue": "^3.2.13",
|
||||
"vue-router": "^4.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||
"@vue/cli-plugin-router": "~5.0.0",
|
||||
"@vue/cli-plugin-typescript": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"@vue/eslint-config-typescript": "^9.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"pinia": "^2.1.6",
|
||||
"prettier": "^2.4.1",
|
||||
"sass": "^1.32.7",
|
||||
"sass-loader": "^12.0.0",
|
||||
"typescript": "~4.5.5",
|
||||
"vue-router": "^4.2.4"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<nav>
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</nav>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
nav {
|
||||
padding: 30px;
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
|
||||
&.router-link-exact-active {
|
||||
color: #42b983;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,13 @@
|
|||
import { Configuration } from "@/swagger";
|
||||
|
||||
// is this production or dev?
|
||||
function is_dev(): boolean {
|
||||
return process.env.NODE_ENV === "development";
|
||||
}
|
||||
|
||||
export function conf(): Configuration {
|
||||
return new Configuration({
|
||||
// what url to send requests to
|
||||
basePath: is_dev() ? "http://127.0.0.1:7056" : window.location.origin,
|
||||
});
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
|
@ -0,0 +1,124 @@
|
|||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-cli documentation</a
|
||||
>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>babel</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>typescript</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>eslint</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
||||
>Forum</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
||||
>Community Chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
||||
>Twitter</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>vue-devtools</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-loader</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>awesome-vue</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "HelloWorld",
|
||||
props: {
|
||||
msg: String,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,11 @@
|
|||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import "vue-router";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
|
||||
const pinia = createPinia();
|
||||
const app = createApp(App).use(router);
|
||||
|
||||
app.use(pinia);
|
||||
app.mount("#app");
|
|
@ -0,0 +1,26 @@
|
|||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
||||
import HomeView from "../views/HomeView.vue";
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: "/",
|
||||
name: "home",
|
||||
component: HomeView,
|
||||
},
|
||||
{
|
||||
path: "/about",
|
||||
name: "about",
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
routes,
|
||||
});
|
||||
|
||||
export default router;
|
|
@ -0,0 +1,6 @@
|
|||
/* eslint-disable */
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
import { conf } from "@/api";
|
||||
import { Protostar, StarsApi } from "@/swagger";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
type ChartInfoState = {
|
||||
loading: boolean;
|
||||
protostars: Protostar[];
|
||||
};
|
||||
|
||||
export const useChartStore = defineStore({
|
||||
id: "chart",
|
||||
state: () =>
|
||||
({
|
||||
loading: true,
|
||||
protostars: [],
|
||||
} as ChartInfoState),
|
||||
actions: {
|
||||
async fetchChart() {
|
||||
this.loading = true;
|
||||
this.protostars = await new StarsApi(conf())
|
||||
.chart()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
return this.protostars;
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const useVisitStore = defineStore({
|
||||
id: "chart",
|
||||
state: () =>
|
||||
({
|
||||
loading: true,
|
||||
protostars: [],
|
||||
} as ChartInfoState),
|
||||
actions: {
|
||||
async fetchChart() {
|
||||
this.loading = true;
|
||||
this.protostars = await new StarsApi(conf())
|
||||
.chart()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
return this.protostars;
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
.openapi-generator-ignore
|
||||
apis/StarsApi.ts
|
||||
apis/index.ts
|
||||
index.ts
|
||||
models/DiscoveryLog.ts
|
||||
models/Protostar.ts
|
||||
models/Size.ts
|
||||
models/Star.ts
|
||||
models/VisitorData.ts
|
||||
models/index.ts
|
||||
runtime.ts
|
|
@ -0,0 +1 @@
|
|||
6.6.0
|
|
@ -0,0 +1,138 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
DiscoveryLog,
|
||||
Star,
|
||||
} from '../models';
|
||||
import {
|
||||
DiscoveryLogFromJSON,
|
||||
DiscoveryLogToJSON,
|
||||
StarFromJSON,
|
||||
StarToJSON,
|
||||
} from '../models';
|
||||
|
||||
export interface DiscoverRequest {
|
||||
discoveryLog: DiscoveryLog;
|
||||
}
|
||||
|
||||
export interface VisitRequest {
|
||||
planetId: any;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class StarsApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
* the whole chart
|
||||
*/
|
||||
async chartRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<any>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/v1/stars/chart`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
if (this.isJsonMime(response.headers.get('content-type'))) {
|
||||
return new runtime.JSONApiResponse<any>(response);
|
||||
} else {
|
||||
return new runtime.TextApiResponse(response) as any;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* the whole chart
|
||||
*/
|
||||
async chart(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<any> {
|
||||
const response = await this.chartRaw(initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* add a new planet
|
||||
*/
|
||||
async discoverRaw(requestParameters: DiscoverRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Star>> {
|
||||
if (requestParameters.discoveryLog === null || requestParameters.discoveryLog === undefined) {
|
||||
throw new runtime.RequiredError('discoveryLog','Required parameter requestParameters.discoveryLog was null or undefined when calling discover.');
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters['Content-Type'] = 'application/json';
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/v1/stars/discover`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: DiscoveryLogToJSON(requestParameters.discoveryLog),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => StarFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* add a new planet
|
||||
*/
|
||||
async discover(requestParameters: DiscoverRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Star> {
|
||||
const response = await this.discoverRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* visit a single planet
|
||||
*/
|
||||
async visitRaw(requestParameters: VisitRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Star>> {
|
||||
if (requestParameters.planetId === null || requestParameters.planetId === undefined) {
|
||||
throw new runtime.RequiredError('planetId','Required parameter requestParameters.planetId was null or undefined when calling visit.');
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters.planetId !== undefined) {
|
||||
queryParameters['planet_id'] = requestParameters.planetId;
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/v1/stars/visit/`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => StarFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* visit a single planet
|
||||
*/
|
||||
async visit(requestParameters: VisitRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Star> {
|
||||
const response = await this.visitRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './StarsApi';
|
|
@ -0,0 +1,5 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './runtime';
|
||||
export * from './apis';
|
||||
export * from './models';
|
|
@ -0,0 +1,66 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { exists, mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface DiscoveryLog
|
||||
*/
|
||||
export interface DiscoveryLog {
|
||||
/**
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof DiscoveryLog
|
||||
*/
|
||||
color: any | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the DiscoveryLog interface.
|
||||
*/
|
||||
export function instanceOfDiscoveryLog(value: object): boolean {
|
||||
let isInstance = true;
|
||||
isInstance = isInstance && "color" in value;
|
||||
|
||||
return isInstance;
|
||||
}
|
||||
|
||||
export function DiscoveryLogFromJSON(json: any): DiscoveryLog {
|
||||
return DiscoveryLogFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function DiscoveryLogFromJSONTyped(json: any, ignoreDiscriminator: boolean): DiscoveryLog {
|
||||
if ((json === undefined) || (json === null)) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'color': json['color'],
|
||||
};
|
||||
}
|
||||
|
||||
export function DiscoveryLogToJSON(value?: DiscoveryLog | null): any {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
|
||||
'color': value.color,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { exists, mapValues } from '../runtime';
|
||||
/**
|
||||
* this gets stored in the db, the other stuff is generated using the id as a seed
|
||||
* @export
|
||||
* @interface Protostar
|
||||
*/
|
||||
export interface Protostar {
|
||||
/**
|
||||
* hex code of the stars color
|
||||
* @type {any}
|
||||
* @memberof Protostar
|
||||
*/
|
||||
color: any | null;
|
||||
/**
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof Protostar
|
||||
*/
|
||||
id: any | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the Protostar interface.
|
||||
*/
|
||||
export function instanceOfProtostar(value: object): boolean {
|
||||
let isInstance = true;
|
||||
isInstance = isInstance && "color" in value;
|
||||
isInstance = isInstance && "id" in value;
|
||||
|
||||
return isInstance;
|
||||
}
|
||||
|
||||
export function ProtostarFromJSON(json: any): Protostar {
|
||||
return ProtostarFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ProtostarFromJSONTyped(json: any, ignoreDiscriminator: boolean): Protostar {
|
||||
if ((json === undefined) || (json === null)) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'color': json['color'],
|
||||
'id': json['id'],
|
||||
};
|
||||
}
|
||||
|
||||
export function ProtostarToJSON(value?: Protostar | null): any {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
|
||||
'color': value.color,
|
||||
'id': value.id,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { exists, mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface Size
|
||||
*/
|
||||
export interface Size {
|
||||
/**
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof Size
|
||||
*/
|
||||
largeItem: any | null;
|
||||
/**
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof Size
|
||||
*/
|
||||
largeItemMultiplier: any | null;
|
||||
/**
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof Size
|
||||
*/
|
||||
smallItem: any | null;
|
||||
/**
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof Size
|
||||
*/
|
||||
smallItemMultiplier: any | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the Size interface.
|
||||
*/
|
||||
export function instanceOfSize(value: object): boolean {
|
||||
let isInstance = true;
|
||||
isInstance = isInstance && "largeItem" in value;
|
||||
isInstance = isInstance && "largeItemMultiplier" in value;
|
||||
isInstance = isInstance && "smallItem" in value;
|
||||
isInstance = isInstance && "smallItemMultiplier" in value;
|
||||
|
||||
return isInstance;
|
||||
}
|
||||
|
||||
export function SizeFromJSON(json: any): Size {
|
||||
return SizeFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function SizeFromJSONTyped(json: any, ignoreDiscriminator: boolean): Size {
|
||||
if ((json === undefined) || (json === null)) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'largeItem': json['large_item'],
|
||||
'largeItemMultiplier': json['large_item_multiplier'],
|
||||
'smallItem': json['small_item'],
|
||||
'smallItemMultiplier': json['small_item_multiplier'],
|
||||
};
|
||||
}
|
||||
|
||||
export function SizeToJSON(value?: Size | null): any {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
|
||||
'large_item': value.largeItem,
|
||||
'large_item_multiplier': value.largeItemMultiplier,
|
||||
'small_item': value.smallItem,
|
||||
'small_item_multiplier': value.smallItemMultiplier,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { exists, mapValues } from '../runtime';
|
||||
import type { Protostar } from './Protostar';
|
||||
import {
|
||||
ProtostarFromJSON,
|
||||
ProtostarFromJSONTyped,
|
||||
ProtostarToJSON,
|
||||
} from './Protostar';
|
||||
import type { Size } from './Size';
|
||||
import {
|
||||
SizeFromJSON,
|
||||
SizeFromJSONTyped,
|
||||
SizeToJSON,
|
||||
} from './Size';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface Star
|
||||
*/
|
||||
export interface Star {
|
||||
/**
|
||||
*
|
||||
* @type {Protostar}
|
||||
* @memberof Star
|
||||
*/
|
||||
core: Protostar;
|
||||
/**
|
||||
*
|
||||
* @type {Size}
|
||||
* @memberof Star
|
||||
*/
|
||||
size: Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the Star interface.
|
||||
*/
|
||||
export function instanceOfStar(value: object): boolean {
|
||||
let isInstance = true;
|
||||
isInstance = isInstance && "core" in value;
|
||||
isInstance = isInstance && "size" in value;
|
||||
|
||||
return isInstance;
|
||||
}
|
||||
|
||||
export function StarFromJSON(json: any): Star {
|
||||
return StarFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function StarFromJSONTyped(json: any, ignoreDiscriminator: boolean): Star {
|
||||
if ((json === undefined) || (json === null)) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'core': ProtostarFromJSON(json['core']),
|
||||
'size': SizeFromJSON(json['size']),
|
||||
};
|
||||
}
|
||||
|
||||
export function StarToJSON(value?: Star | null): any {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
|
||||
'core': ProtostarToJSON(value.core),
|
||||
'size': SizeToJSON(value.size),
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { exists, mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface VisitorData
|
||||
*/
|
||||
export interface VisitorData {
|
||||
/**
|
||||
* the planet to visit
|
||||
* @type {any}
|
||||
* @memberof VisitorData
|
||||
*/
|
||||
planetId: any | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the VisitorData interface.
|
||||
*/
|
||||
export function instanceOfVisitorData(value: object): boolean {
|
||||
let isInstance = true;
|
||||
isInstance = isInstance && "planetId" in value;
|
||||
|
||||
return isInstance;
|
||||
}
|
||||
|
||||
export function VisitorDataFromJSON(json: any): VisitorData {
|
||||
return VisitorDataFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function VisitorDataFromJSONTyped(json: any, ignoreDiscriminator: boolean): VisitorData {
|
||||
if ((json === undefined) || (json === null)) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'planetId': json['planet_id'],
|
||||
};
|
||||
}
|
||||
|
||||
export function VisitorDataToJSON(value?: VisitorData | null): any {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
|
||||
'planet_id': value.planetId,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './DiscoveryLog';
|
||||
export * from './Protostar';
|
||||
export * from './Size';
|
||||
export * from './Star';
|
||||
export * from './VisitorData';
|
|
@ -0,0 +1,425 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* starchart
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export const BASE_PATH = "http://localhost".replace(/\/+$/, "");
|
||||
|
||||
export interface ConfigurationParameters {
|
||||
basePath?: string; // override base path
|
||||
fetchApi?: FetchAPI; // override for fetch implementation
|
||||
middleware?: Middleware[]; // middleware to apply before/after fetch requests
|
||||
queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings
|
||||
username?: string; // parameter for basic security
|
||||
password?: string; // parameter for basic security
|
||||
apiKey?: string | ((name: string) => string); // parameter for apiKey security
|
||||
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string | Promise<string>); // parameter for oauth2 security
|
||||
headers?: HTTPHeaders; //header params we want to use on every request
|
||||
credentials?: RequestCredentials; //value for the credentials param we want to use on each request
|
||||
}
|
||||
|
||||
export class Configuration {
|
||||
constructor(private configuration: ConfigurationParameters = {}) {}
|
||||
|
||||
set config(configuration: Configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
get basePath(): string {
|
||||
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
||||
}
|
||||
|
||||
get fetchApi(): FetchAPI | undefined {
|
||||
return this.configuration.fetchApi;
|
||||
}
|
||||
|
||||
get middleware(): Middleware[] {
|
||||
return this.configuration.middleware || [];
|
||||
}
|
||||
|
||||
get queryParamsStringify(): (params: HTTPQuery) => string {
|
||||
return this.configuration.queryParamsStringify || querystring;
|
||||
}
|
||||
|
||||
get username(): string | undefined {
|
||||
return this.configuration.username;
|
||||
}
|
||||
|
||||
get password(): string | undefined {
|
||||
return this.configuration.password;
|
||||
}
|
||||
|
||||
get apiKey(): ((name: string) => string) | undefined {
|
||||
const apiKey = this.configuration.apiKey;
|
||||
if (apiKey) {
|
||||
return typeof apiKey === 'function' ? apiKey : () => apiKey;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get accessToken(): ((name?: string, scopes?: string[]) => string | Promise<string>) | undefined {
|
||||
const accessToken = this.configuration.accessToken;
|
||||
if (accessToken) {
|
||||
return typeof accessToken === 'function' ? accessToken : async () => accessToken;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get headers(): HTTPHeaders | undefined {
|
||||
return this.configuration.headers;
|
||||
}
|
||||
|
||||
get credentials(): RequestCredentials | undefined {
|
||||
return this.configuration.credentials;
|
||||
}
|
||||
}
|
||||
|
||||
export const DefaultConfig = new Configuration();
|
||||
|
||||
/**
|
||||
* This is the base class for all generated API classes.
|
||||
*/
|
||||
export class BaseAPI {
|
||||
|
||||
private static readonly jsonRegex = new RegExp('^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$', 'i');
|
||||
private middleware: Middleware[];
|
||||
|
||||
constructor(protected configuration = DefaultConfig) {
|
||||
this.middleware = configuration.middleware;
|
||||
}
|
||||
|
||||
withMiddleware<T extends BaseAPI>(this: T, ...middlewares: Middleware[]) {
|
||||
const next = this.clone<T>();
|
||||
next.middleware = next.middleware.concat(...middlewares);
|
||||
return next;
|
||||
}
|
||||
|
||||
withPreMiddleware<T extends BaseAPI>(this: T, ...preMiddlewares: Array<Middleware['pre']>) {
|
||||
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
||||
return this.withMiddleware<T>(...middlewares);
|
||||
}
|
||||
|
||||
withPostMiddleware<T extends BaseAPI>(this: T, ...postMiddlewares: Array<Middleware['post']>) {
|
||||
const middlewares = postMiddlewares.map((post) => ({ post }));
|
||||
return this.withMiddleware<T>(...middlewares);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected isJsonMime(mime: string | null | undefined): boolean {
|
||||
if (!mime) {
|
||||
return false;
|
||||
}
|
||||
return BaseAPI.jsonRegex.test(mime);
|
||||
}
|
||||
|
||||
protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise<Response> {
|
||||
const { url, init } = await this.createFetchParams(context, initOverrides);
|
||||
const response = await this.fetchApi(url, init);
|
||||
if (response && (response.status >= 200 && response.status < 300)) {
|
||||
return response;
|
||||
}
|
||||
throw new ResponseError(response, 'Response returned an error code');
|
||||
}
|
||||
|
||||
private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) {
|
||||
let url = this.configuration.basePath + context.path;
|
||||
if (context.query !== undefined && Object.keys(context.query).length !== 0) {
|
||||
// only add the querystring to the URL if there are query parameters.
|
||||
// this is done to avoid urls ending with a "?" character which buggy webservers
|
||||
// do not handle correctly sometimes.
|
||||
url += '?' + this.configuration.queryParamsStringify(context.query);
|
||||
}
|
||||
|
||||
const headers = Object.assign({}, this.configuration.headers, context.headers);
|
||||
Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {});
|
||||
|
||||
const initOverrideFn =
|
||||
typeof initOverrides === "function"
|
||||
? initOverrides
|
||||
: async () => initOverrides;
|
||||
|
||||
const initParams = {
|
||||
method: context.method,
|
||||
headers,
|
||||
body: context.body,
|
||||
credentials: this.configuration.credentials,
|
||||
};
|
||||
|
||||
const overriddenInit: RequestInit = {
|
||||
...initParams,
|
||||
...(await initOverrideFn({
|
||||
init: initParams,
|
||||
context,
|
||||
}))
|
||||
};
|
||||
|
||||
const init: RequestInit = {
|
||||
...overriddenInit,
|
||||
body:
|
||||
isFormData(overriddenInit.body) ||
|
||||
overriddenInit.body instanceof URLSearchParams ||
|
||||
isBlob(overriddenInit.body)
|
||||
? overriddenInit.body
|
||||
: JSON.stringify(overriddenInit.body),
|
||||
};
|
||||
|
||||
return { url, init };
|
||||
}
|
||||
|
||||
private fetchApi = async (url: string, init: RequestInit) => {
|
||||
let fetchParams = { url, init };
|
||||
for (const middleware of this.middleware) {
|
||||
if (middleware.pre) {
|
||||
fetchParams = await middleware.pre({
|
||||
fetch: this.fetchApi,
|
||||
...fetchParams,
|
||||
}) || fetchParams;
|
||||
}
|
||||
}
|
||||
let response: Response | undefined = undefined;
|
||||
try {
|
||||
response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
|
||||
} catch (e) {
|
||||
for (const middleware of this.middleware) {
|
||||
if (middleware.onError) {
|
||||
response = await middleware.onError({
|
||||
fetch: this.fetchApi,
|
||||
url: fetchParams.url,
|
||||
init: fetchParams.init,
|
||||
error: e,
|
||||
response: response ? response.clone() : undefined,
|
||||
}) || response;
|
||||
}
|
||||
}
|
||||
if (response === undefined) {
|
||||
if (e instanceof Error) {
|
||||
throw new FetchError(e, 'The request failed and the interceptors did not return an alternative response');
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const middleware of this.middleware) {
|
||||
if (middleware.post) {
|
||||
response = await middleware.post({
|
||||
fetch: this.fetchApi,
|
||||
url: fetchParams.url,
|
||||
init: fetchParams.init,
|
||||
response: response.clone(),
|
||||
}) || response;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shallow clone of `this` by constructing a new instance
|
||||
* and then shallow cloning data members.
|
||||
*/
|
||||
private clone<T extends BaseAPI>(this: T): T {
|
||||
const constructor = this.constructor as any;
|
||||
const next = new constructor(this.configuration);
|
||||
next.middleware = this.middleware.slice();
|
||||
return next;
|
||||
}
|
||||
};
|
||||
|
||||
function isBlob(value: any): value is Blob {
|
||||
return typeof Blob !== 'undefined' && value instanceof Blob;
|
||||
}
|
||||
|
||||
function isFormData(value: any): value is FormData {
|
||||
return typeof FormData !== "undefined" && value instanceof FormData;
|
||||
}
|
||||
|
||||
export class ResponseError extends Error {
|
||||
override name: "ResponseError" = "ResponseError";
|
||||
constructor(public response: Response, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export class FetchError extends Error {
|
||||
override name: "FetchError" = "FetchError";
|
||||
constructor(public cause: Error, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export class RequiredError extends Error {
|
||||
override name: "RequiredError" = "RequiredError";
|
||||
constructor(public field: string, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export const COLLECTION_FORMATS = {
|
||||
csv: ",",
|
||||
ssv: " ",
|
||||
tsv: "\t",
|
||||
pipes: "|",
|
||||
};
|
||||
|
||||
export type FetchAPI = WindowOrWorkerGlobalScope['fetch'];
|
||||
|
||||
export type Json = any;
|
||||
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
||||
export type HTTPHeaders = { [key: string]: string };
|
||||
export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | Set<string | number | null | boolean> | HTTPQuery };
|
||||
export type HTTPBody = Json | FormData | URLSearchParams;
|
||||
export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody };
|
||||
export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original';
|
||||
|
||||
export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise<RequestInit>
|
||||
|
||||
export interface FetchParams {
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
}
|
||||
|
||||
export interface RequestOpts {
|
||||
path: string;
|
||||
method: HTTPMethod;
|
||||
headers: HTTPHeaders;
|
||||
query?: HTTPQuery;
|
||||
body?: HTTPBody;
|
||||
}
|
||||
|
||||
export function exists(json: any, key: string) {
|
||||
const value = json[key];
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
export function querystring(params: HTTPQuery, prefix: string = ''): string {
|
||||
return Object.keys(params)
|
||||
.map(key => querystringSingleKey(key, params[key], prefix))
|
||||
.filter(part => part.length > 0)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array<string | number | null | boolean> | Set<string | number | null | boolean> | HTTPQuery, keyPrefix: string = ''): string {
|
||||
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
||||
if (value instanceof Array) {
|
||||
const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue)))
|
||||
.join(`&${encodeURIComponent(fullKey)}=`);
|
||||
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
||||
}
|
||||
if (value instanceof Set) {
|
||||
const valueAsArray = Array.from(value);
|
||||
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
||||
}
|
||||
if (value instanceof Object) {
|
||||
return querystring(value as HTTPQuery, fullKey);
|
||||
}
|
||||
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
||||
}
|
||||
|
||||
export function mapValues(data: any, fn: (item: any) => any) {
|
||||
return Object.keys(data).reduce(
|
||||
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
export function canConsumeForm(consumes: Consume[]): boolean {
|
||||
for (const consume of consumes) {
|
||||
if ('multipart/form-data' === consume.contentType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export interface Consume {
|
||||
contentType: string;
|
||||
}
|
||||
|
||||
export interface RequestContext {
|
||||
fetch: FetchAPI;
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
}
|
||||
|
||||
export interface ResponseContext {
|
||||
fetch: FetchAPI;
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
response: Response;
|
||||
}
|
||||
|
||||
export interface ErrorContext {
|
||||
fetch: FetchAPI;
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
error: unknown;
|
||||
response?: Response;
|
||||
}
|
||||
|
||||
export interface Middleware {
|
||||
pre?(context: RequestContext): Promise<FetchParams | void>;
|
||||
post?(context: ResponseContext): Promise<Response | void>;
|
||||
onError?(context: ErrorContext): Promise<Response | void>;
|
||||
}
|
||||
|
||||
export interface ApiResponse<T> {
|
||||
raw: Response;
|
||||
value(): Promise<T>;
|
||||
}
|
||||
|
||||
export interface ResponseTransformer<T> {
|
||||
(json: any): T;
|
||||
}
|
||||
|
||||
export class JSONApiResponse<T> {
|
||||
constructor(public raw: Response, private transformer: ResponseTransformer<T> = (jsonValue: any) => jsonValue) {}
|
||||
|
||||
async value(): Promise<T> {
|
||||
return this.transformer(await this.raw.json());
|
||||
}
|
||||
}
|
||||
|
||||
export class VoidApiResponse {
|
||||
constructor(public raw: Response) {}
|
||||
|
||||
async value(): Promise<void> {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class BlobApiResponse {
|
||||
constructor(public raw: Response) {}
|
||||
|
||||
async value(): Promise<Blob> {
|
||||
return await this.raw.blob();
|
||||
};
|
||||
}
|
||||
|
||||
export class TextApiResponse {
|
||||
constructor(public raw: Response) {}
|
||||
|
||||
async value(): Promise<string> {
|
||||
return await this.raw.text();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,18 @@
|
|||
<template>
|
||||
<div class="home">
|
||||
<img alt="Vue logo" src="../assets/logo.png" />
|
||||
<HelloWorld msg="Welcome to Your Vue.js App" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from "@/components/HelloWorld.vue";
|
||||
|
||||
export default {
|
||||
name: "HomeView",
|
||||
components: {
|
||||
HelloWorld,
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"useDefineForClassFields": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
const { defineConfig } = require("@vue/cli-service");
|
||||
module.exports = defineConfig({
|
||||
transpileDependencies: true,
|
||||
});
|
Loading…
Reference in New Issue