Compare commits
58 changed files with 941 additions and 3941 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
|
@ -1776,44 +1776,6 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-embed"
|
|
||||||
version = "6.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b68543d5527e158213414a92832d2aab11a84d2571a5eb021ebe22c43aab066"
|
|
||||||
dependencies = [
|
|
||||||
"hex",
|
|
||||||
"mime_guess",
|
|
||||||
"poem",
|
|
||||||
"rust-embed-impl",
|
|
||||||
"rust-embed-utils",
|
|
||||||
"tokio",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-embed-impl"
|
|
||||||
version = "6.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rust-embed-utils",
|
|
||||||
"syn",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-embed-utils"
|
|
||||||
version = "7.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731"
|
|
||||||
dependencies = [
|
|
||||||
"sha2",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -2089,7 +2051,6 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"rstest",
|
"rstest",
|
||||||
"rust-embed",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ license = "MIT"
|
||||||
description = "Static site management system"
|
description = "Static site management system"
|
||||||
|
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
default-run = "talon"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
poem = "1.3.55"
|
poem = "1.3.55"
|
||||||
|
|
@ -52,7 +51,6 @@ async-compression = { version = "0.3.15", features = [
|
||||||
clap = { version = "4.1.8", features = ["derive"] }
|
clap = { version = "4.1.8", features = ["derive"] }
|
||||||
shadow-rs = "0.21.0"
|
shadow-rs = "0.21.0"
|
||||||
walkdir = "2.3.2"
|
walkdir = "2.3.2"
|
||||||
rust-embed = { version = "6.6.1", features = ["poem-ex"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rstest = "0.16.0"
|
rstest = "0.16.0"
|
||||||
|
|
|
||||||
28
Justfile
28
Justfile
|
|
@ -1,28 +0,0 @@
|
||||||
ok: lint test
|
|
||||||
|
|
||||||
lint:
|
|
||||||
cargo fmt --all
|
|
||||||
cargo clippy --all --all-features -- -D warnings
|
|
||||||
|
|
||||||
test:
|
|
||||||
cargo test --workspace
|
|
||||||
|
|
||||||
# Run the Talon server
|
|
||||||
run:
|
|
||||||
cargo run -- run -d tmp
|
|
||||||
|
|
||||||
# Generate the openapi.json documentation
|
|
||||||
oai-doc:
|
|
||||||
cargo run --bin openapi
|
|
||||||
|
|
||||||
# Generate the JS API client
|
|
||||||
oai-client:
|
|
||||||
openapi-generator-cli generate -i openapi.json -g typescript-fetch -o ui/talon-client -p "npmName=talon-client"
|
|
||||||
|
|
||||||
# Start the dev server for the sidebar menu
|
|
||||||
menu-dev:
|
|
||||||
cd ui/menu && npm run dev
|
|
||||||
|
|
||||||
# Build the sidebar menu -> ui/menu/dist/talon.js
|
|
||||||
menu-build:
|
|
||||||
cd ui/menu && npm run build
|
|
||||||
836
openapi.json
836
openapi.json
|
|
@ -1,836 +0,0 @@
|
||||||
{
|
|
||||||
"openapi": "3.0.0",
|
|
||||||
"info": {
|
|
||||||
"title": "Talon",
|
|
||||||
"description": "API for the Talon static site management system",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"license": {
|
|
||||||
"name": "MIT License"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"servers": [],
|
|
||||||
"tags": [],
|
|
||||||
"paths": {
|
|
||||||
"/website/{subdomain}": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get a website",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Website"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"put": {
|
|
||||||
"summary": "Create a new website",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/WebsiteNew"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuthorization": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"patch": {
|
|
||||||
"summary": "Update website",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/WebsiteUpdate"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuthorization": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"delete": {
|
|
||||||
"summary": "Delete website",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuthorization": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/websites": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get all publicly listed websites",
|
|
||||||
"description": "Returns all publicly listed websites (visibility != `hidden`)",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "visibility",
|
|
||||||
"schema": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Visibility"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "hidden"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"in": "query",
|
|
||||||
"description": "Mimimum visibility of the websites",
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/Website"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/websitesAll": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get all websites",
|
|
||||||
"description": "Returns all websites from Talon's database (including hidden ones, if the current user\nhas access to them). This endpoint requires authentication (use the `/websites` endpoint\nfor unauthenticated users).",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "visibility",
|
|
||||||
"schema": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Visibility"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "hidden"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"in": "query",
|
|
||||||
"description": "Mimimum visibility of the websites",
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/Website"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuthorization": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/website/{subdomain}/versions": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get website versions",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/Version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/website/{subdomain}/version/{version}": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get version",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"delete": {
|
|
||||||
"summary": "Delete version",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuthorization": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/website/{subdomain}/version/{version}/files": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get version files",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/VersionFile"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/website/{subdomain}/upload": {
|
|
||||||
"post": {
|
|
||||||
"summary": "Upload a new version",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "subdomain",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fallback",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "query",
|
|
||||||
"description": "Fallback page\n\nThe fallback page gets returned when the requested page does not exist",
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "spa",
|
|
||||||
"schema": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"in": "query",
|
|
||||||
"description": "SPA mode (return fallback page with OK status)",
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version_data",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"in": "query",
|
|
||||||
"description": "Associated version data\n\nThis is an arbitrary string map that can hold build information and other stuff\nand will be displayed in the site info dialog.",
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/octet-stream": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "binary"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuthorization": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/file/{hash}": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Retrieve a file",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "hash",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"explode": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "File content",
|
|
||||||
"content": {
|
|
||||||
"application/octet-stream": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "binary"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"headers": {
|
|
||||||
"etag": {
|
|
||||||
"description": "File hash",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"last-modified": {
|
|
||||||
"description": "Date when the file was last modified",
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/info": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get information about your server",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json; charset=utf-8": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Info"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"components": {
|
|
||||||
"schemas": {
|
|
||||||
"Info": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Server information",
|
|
||||||
"required": [
|
|
||||||
"stats",
|
|
||||||
"version",
|
|
||||||
"uptime"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"stats": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Stats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Stats about your instance"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/VersionInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Version information"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uptime": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint64",
|
|
||||||
"description": "Current uptime of the server in seconds"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"SourceIcon": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"link",
|
|
||||||
"git",
|
|
||||||
"github",
|
|
||||||
"gitlab",
|
|
||||||
"gitea",
|
|
||||||
"bitbucket"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Stats": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Stats about your Talon instance",
|
|
||||||
"required": [
|
|
||||||
"n_websites",
|
|
||||||
"n_files",
|
|
||||||
"storage_used"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"n_websites": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint64",
|
|
||||||
"description": "Number of websites"
|
|
||||||
},
|
|
||||||
"n_files": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint64",
|
|
||||||
"description": "Number of unique files"
|
|
||||||
},
|
|
||||||
"storage_used": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint64",
|
|
||||||
"description": "Amount of used storage space (in bytes)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Version": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Website version",
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"created_at",
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32",
|
|
||||||
"description": "Version ID"
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "date-time",
|
|
||||||
"description": "Version creation date"
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Associated version data\n\nThis is an arbitrary string map that can hold build information and other stuff\nand will be displayed in the site info dialog.",
|
|
||||||
"additionalProperties": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"VersionFile": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Website file",
|
|
||||||
"required": [
|
|
||||||
"path",
|
|
||||||
"hash"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"path": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "File path"
|
|
||||||
},
|
|
||||||
"hash": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "File hash"
|
|
||||||
},
|
|
||||||
"mime": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "MIME file type"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"VersionInfo": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Information about a Talon version",
|
|
||||||
"required": [
|
|
||||||
"version",
|
|
||||||
"commit",
|
|
||||||
"commit_date",
|
|
||||||
"rust_version",
|
|
||||||
"build_target",
|
|
||||||
"build_mode"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Talon version"
|
|
||||||
},
|
|
||||||
"commit": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Commit hash"
|
|
||||||
},
|
|
||||||
"commit_date": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "date-time",
|
|
||||||
"description": "Commit date"
|
|
||||||
},
|
|
||||||
"rust_version": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Rust version"
|
|
||||||
},
|
|
||||||
"build_target": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Build target (OS and architecture)"
|
|
||||||
},
|
|
||||||
"build_mode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Rust build mode (`debug` / `release`)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Visibility": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"featured",
|
|
||||||
"searchable",
|
|
||||||
"hidden"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Website": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Website",
|
|
||||||
"required": [
|
|
||||||
"subdomain",
|
|
||||||
"name",
|
|
||||||
"created_at",
|
|
||||||
"visibility"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"subdomain": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Website subdomain"
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Website name"
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "date-time",
|
|
||||||
"description": "Website creation date"
|
|
||||||
},
|
|
||||||
"latest_version": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32",
|
|
||||||
"description": "Latest version ID"
|
|
||||||
},
|
|
||||||
"color": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Color of the page icon\n\nFormat: `#7935df`"
|
|
||||||
},
|
|
||||||
"visibility": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Visibility"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Visibility of the page in the sidebar menu"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source_url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Link to the source of the page"
|
|
||||||
},
|
|
||||||
"source_icon": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SourceIcon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Icon for the source link"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"WebsiteNew": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Create a new website",
|
|
||||||
"required": [
|
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Website name"
|
|
||||||
},
|
|
||||||
"color": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Color of the page icon"
|
|
||||||
},
|
|
||||||
"visibility": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Visibility"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Visibility of the page in the sidebar menu",
|
|
||||||
"default": "hidden"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source_url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Link to the source of the page"
|
|
||||||
},
|
|
||||||
"source_icon": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SourceIcon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Icon for the source link"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"WebsiteUpdate": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "Update a website with the contained values\n\nValues set to `None` remain unchanged.",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Website name"
|
|
||||||
},
|
|
||||||
"color": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Color of the page icon"
|
|
||||||
},
|
|
||||||
"visibility": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Visibility"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Visibility of the page in the sidebar menu"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source_url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Link to the source of the page"
|
|
||||||
},
|
|
||||||
"source_icon": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SourceIcon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Icon for the source link"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"securitySchemes": {
|
|
||||||
"ApiKeyAuthorization": {
|
|
||||||
"type": "apiKey",
|
|
||||||
"name": "X-API-Key",
|
|
||||||
"in": "header"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
|
|
||||||
"spaces": 2,
|
|
||||||
"generator-cli": {
|
|
||||||
"version": "6.4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,7 +11,7 @@ use poem_openapi::{
|
||||||
auth::ApiKey,
|
auth::ApiKey,
|
||||||
param::{Path, Query},
|
param::{Path, Query},
|
||||||
payload::{Binary, Html, Json, Response},
|
payload::{Binary, Html, Json, Response},
|
||||||
LicenseObject, OpenApi, OpenApiService, SecurityScheme,
|
OpenApi, SecurityScheme,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -388,9 +388,3 @@ impl TalonApi {
|
||||||
Ok(Json(talon.info()?))
|
Ok(Json(talon.info()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn api_service() -> OpenApiService<TalonApi, ()> {
|
|
||||||
OpenApiService::new(TalonApi, "Talon", crate::API_VERSION)
|
|
||||||
.description("API for the Talon static site management system")
|
|
||||||
.license(LicenseObject::new("MIT License"))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use crate::{storage::CompressionAlg, util};
|
|
||||||
use poem::{
|
|
||||||
handler,
|
|
||||||
http::{header, Method, StatusCode},
|
|
||||||
web::Path,
|
|
||||||
Request, Response, Result,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(rust_embed::RustEmbed)]
|
|
||||||
#[folder = "ui/menu/dist/"]
|
|
||||||
struct MenuAsset;
|
|
||||||
|
|
||||||
#[handler]
|
|
||||||
pub fn menu_assets(request: &Request, path: Path<String>) -> Result<Response> {
|
|
||||||
assets(request, path, PhantomData::<MenuAsset>)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assets<A: rust_embed::RustEmbed + Sync + Send>(
|
|
||||||
request: &Request,
|
|
||||||
path: Path<String>,
|
|
||||||
_: PhantomData<A>,
|
|
||||||
) -> Result<Response> {
|
|
||||||
if request.method() != Method::GET {
|
|
||||||
return Ok(StatusCode::METHOD_NOT_ALLOWED.into());
|
|
||||||
}
|
|
||||||
let path = path.0;
|
|
||||||
|
|
||||||
match A::get(&path) {
|
|
||||||
Some(content) => {
|
|
||||||
let hash = hex::encode(content.metadata.sha256_hash());
|
|
||||||
|
|
||||||
// if etag is matched, return 304
|
|
||||||
if request
|
|
||||||
.headers()
|
|
||||||
.get(header::IF_NONE_MATCH)
|
|
||||||
.map(|etag| etag.to_str().unwrap_or("000000").eq(&hash))
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
return Ok(StatusCode::NOT_MODIFIED.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let alg = util::parse_accept_encoding(request.headers(), &[CompressionAlg::Brotli]);
|
|
||||||
let (body, body_alg) = if let Some(CompressionAlg::Brotli) = alg {
|
|
||||||
let path_compressed = format!("{path}.br");
|
|
||||||
if let Some(compressed_content) = MenuAsset::get(&path_compressed) {
|
|
||||||
(compressed_content.data, CompressionAlg::Brotli)
|
|
||||||
} else {
|
|
||||||
(content.data, CompressionAlg::None)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(content.data, CompressionAlg::None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// otherwise, return 200 with etag hash
|
|
||||||
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
|
||||||
let mut builder = Response::builder()
|
|
||||||
.header(header::CONTENT_TYPE, mime.as_ref())
|
|
||||||
.header(header::ETAG, hash);
|
|
||||||
if let Some(encoding) = body_alg.encoding() {
|
|
||||||
builder = builder.header(header::CONTENT_ENCODING, encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(builder.body(body.to_vec()))
|
|
||||||
}
|
|
||||||
None => Ok(Response::builder().status(StatusCode::NOT_FOUND).finish()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
use std::{fs::File, io::Error, io::Write};
|
|
||||||
|
|
||||||
/// Generate Talon's OpenAPI documentation
|
|
||||||
fn main() -> Result<(), Error> {
|
|
||||||
let api = talon::api::api_service();
|
|
||||||
let mut file = File::create("openapi.json")?;
|
|
||||||
file.write_all(api.spec().as_bytes())
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#![warn(clippy::todo, clippy::dbg_macro)]
|
#![warn(clippy::todo, clippy::dbg_macro)]
|
||||||
|
|
||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod assets;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
|
|
@ -22,8 +21,6 @@ use time::OffsetDateTime;
|
||||||
|
|
||||||
shadow_rs::shadow!(build);
|
shadow_rs::shadow!(build);
|
||||||
|
|
||||||
pub const API_VERSION: &str = "0.1.0";
|
|
||||||
|
|
||||||
pub static LAST_COMMIT_DATE: Lazy<SystemTime> = Lazy::new(|| {
|
pub static LAST_COMMIT_DATE: Lazy<SystemTime> = Lazy::new(|| {
|
||||||
OffsetDateTime::parse(
|
OffsetDateTime::parse(
|
||||||
build::COMMIT_DATE_3339,
|
build::COMMIT_DATE_3339,
|
||||||
|
|
|
||||||
|
|
@ -131,14 +131,6 @@ pub struct Stats {
|
||||||
pub storage_used: u64,
|
pub storage_used: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Embedded site config
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct TalonConfig<'a> {
|
|
||||||
pub api: &'a str,
|
|
||||||
pub version: &'a str,
|
|
||||||
pub root_domain: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Enum, Serialize, Deserialize,
|
Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Enum, Serialize, Deserialize,
|
||||||
)]
|
)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{ops::Deref, path::Path, sync::Arc};
|
use std::{ops::Deref, path::Path, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assets,
|
api::TalonApi,
|
||||||
config::Config,
|
config::Config,
|
||||||
db::Db,
|
db::Db,
|
||||||
model::{Info, VersionInfo},
|
model::{Info, VersionInfo},
|
||||||
|
|
@ -14,6 +14,7 @@ use poem::{
|
||||||
http::header, listener::TcpListener, middleware, Endpoint, EndpointExt, Route, RouteDomain,
|
http::header, listener::TcpListener, middleware, Endpoint, EndpointExt, Route, RouteDomain,
|
||||||
Server,
|
Server,
|
||||||
};
|
};
|
||||||
|
use poem_openapi::OpenApiService;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -73,8 +74,8 @@ impl Talon {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endpoint(&self) -> impl Endpoint {
|
pub fn endpoint(&self) -> impl Endpoint {
|
||||||
let api_service =
|
let api_service = OpenApiService::new(TalonApi, "Talon", "0.1.0")
|
||||||
crate::api::api_service().server(format!("{}/api", self.i.cfg.server.internal_url));
|
.server(format!("{}/api", self.i.cfg.server.internal_url));
|
||||||
let swagger_ui = api_service.swagger_ui();
|
let swagger_ui = api_service.swagger_ui();
|
||||||
let spec = api_service.spec();
|
let spec = api_service.spec();
|
||||||
|
|
||||||
|
|
@ -83,18 +84,14 @@ impl Talon {
|
||||||
"/",
|
"/",
|
||||||
poem::endpoint::make_sync(|_| "Hello World, I am Talon"),
|
poem::endpoint::make_sync(|_| "Hello World, I am Talon"),
|
||||||
)
|
)
|
||||||
.nest(
|
.nest("/api", api_service)
|
||||||
"/api",
|
|
||||||
api_service
|
|
||||||
.with(middleware::Cors::new())
|
|
||||||
.with(crate::middleware::LastModified),
|
|
||||||
)
|
|
||||||
.nest("/api/swagger", swagger_ui)
|
.nest("/api/swagger", swagger_ui)
|
||||||
.at(
|
.at(
|
||||||
"/api/spec",
|
"/api/spec",
|
||||||
poem::endpoint::make_sync(move |_| spec.clone()),
|
poem::endpoint::make_sync(move |_| spec.clone()),
|
||||||
)
|
)
|
||||||
.at("/assets/menu/*path", assets::menu_assets);
|
.with(middleware::Cors::new())
|
||||||
|
.with(crate::middleware::LastModified);
|
||||||
|
|
||||||
let internal_domain = format!(
|
let internal_domain = format!(
|
||||||
"{}.{}",
|
"{}.{}",
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ use zip::ZipArchive;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
db::{Db, DbError},
|
db::{Db, DbError},
|
||||||
model::{Stats, TalonConfig},
|
model::Stats,
|
||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,7 +32,6 @@ pub struct Storage {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
db: Db,
|
db: Db,
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
to_inject: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
@ -45,7 +44,7 @@ pub enum CompressionAlg {
|
||||||
|
|
||||||
impl CompressionAlg {
|
impl CompressionAlg {
|
||||||
/// Get value of the http encoding header
|
/// Get value of the http encoding header
|
||||||
pub fn encoding(&self) -> Option<&'static str> {
|
fn encoding(&self) -> Option<&'static str> {
|
||||||
match self {
|
match self {
|
||||||
CompressionAlg::None => None,
|
CompressionAlg::None => None,
|
||||||
CompressionAlg::Gzip => Some("gzip"),
|
CompressionAlg::Gzip => Some("gzip"),
|
||||||
|
|
@ -118,28 +117,10 @@ const TMPDIR_PREFIX: &str = "talon";
|
||||||
impl Storage {
|
impl Storage {
|
||||||
/// Create a new file storage using the root folder and the database
|
/// Create a new file storage using the root folder and the database
|
||||||
pub fn new<P: Into<PathBuf>>(path: P, db: Db, cfg: Config) -> Self {
|
pub fn new<P: Into<PathBuf>>(path: P, db: Db, cfg: Config) -> Self {
|
||||||
// Build the string to inject into html pages
|
|
||||||
let talon_cfg = TalonConfig {
|
|
||||||
api: &format!("{}/api", cfg.server.internal_url),
|
|
||||||
version: crate::build::PKG_VERSION,
|
|
||||||
root_domain: &cfg.server.root_domain,
|
|
||||||
};
|
|
||||||
|
|
||||||
let to_inject = format!(
|
|
||||||
r#"<!-- INJECTED BY TALON -->
|
|
||||||
<script id="talon-config" type="application/json">{}</script>
|
|
||||||
<script src="{}/assets/menu/talon.js"></script>
|
|
||||||
<!-- INJECTED BY TALON -->
|
|
||||||
"#,
|
|
||||||
serde_json::to_string(&talon_cfg).unwrap_or_default(),
|
|
||||||
cfg.server.internal_url
|
|
||||||
);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
db,
|
db,
|
||||||
cfg,
|
cfg,
|
||||||
to_inject,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -491,13 +472,15 @@ impl Storage {
|
||||||
// HTML files are not precompressed and need to have UI code injected
|
// HTML files are not precompressed and need to have UI code injected
|
||||||
if is_html {
|
if is_html {
|
||||||
// Inject UI code into HTML
|
// Inject UI code into HTML
|
||||||
|
let to_inject = "<!-- Hello World -->\n";
|
||||||
|
|
||||||
let mut html = String::with_capacity(metadata.len() as usize);
|
let mut html = String::with_capacity(metadata.len() as usize);
|
||||||
tokio::fs::File::from_std(file)
|
tokio::fs::File::from_std(file)
|
||||||
.read_to_string(&mut html)
|
.read_to_string(&mut html)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(ctag_pos) = html.rfind("</html>") {
|
if let Some(ctag_pos) = html.rfind("</html>") {
|
||||||
html.insert_str(ctag_pos, &self.to_inject);
|
html.insert_str(ctag_pos, to_inject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress response if possible
|
// Compress response if possible
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,7 @@ mod storage {
|
||||||
let resp = tokio_test::block_on(tln.storage.file_to_response(gf, &HeaderMap::new(), true))
|
let resp = tokio_test::block_on(tln.storage.file_to_response(gf, &HeaderMap::new(), true))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let body = tokio_test::block_on(resp.into_body().into_string()).unwrap();
|
let body = tokio_test::block_on(resp.into_body().into_string()).unwrap();
|
||||||
assert!(body.contains("<!-- INJECTED BY TALON -->\n"));
|
assert!(body.contains("<!-- Hello World -->\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|
|
||||||
|
|
@ -37,4 +37,4 @@ module.exports = {
|
||||||
],
|
],
|
||||||
rules: {},
|
rules: {},
|
||||||
ignorePatterns: [".rollup/**", "public/**", "dist/**"],
|
ignorePatterns: [".rollup/**", "public/**", "dist/**"],
|
||||||
};
|
}
|
||||||
|
|
|
||||||
52
ui/menu/package-lock.json
generated
52
ui/menu/package-lock.json
generated
|
|
@ -9,8 +9,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||||
"minify-html-stream": "^0.3.1",
|
"minify-html-stream": "^0.3.1"
|
||||||
"talon-client": "file:../talon-client"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.15.5",
|
"@babel/core": "^7.15.5",
|
||||||
|
|
@ -18,7 +17,7 @@
|
||||||
"@babel/preset-typescript": "^7.15.0",
|
"@babel/preset-typescript": "^7.15.0",
|
||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@rollup/plugin-babel": "^5.3.0",
|
||||||
"@rollup/plugin-commonjs": "^20.0.0",
|
"@rollup/plugin-commonjs": "^20.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
"@rollup/plugin-node-resolve": "^13.0.5",
|
||||||
"@rollup/plugin-replace": "^3.0.0",
|
"@rollup/plugin-replace": "^3.0.0",
|
||||||
"@rollup/plugin-typescript": "^8.2.5",
|
"@rollup/plugin-typescript": "^8.2.5",
|
||||||
"@rollup/pluginutils": "^4.1.1",
|
"@rollup/pluginutils": "^4.1.1",
|
||||||
|
|
@ -30,7 +29,6 @@
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"prettier-plugin-svelte": "^1.2.0",
|
"prettier-plugin-svelte": "^1.2.0",
|
||||||
"rollup": "^2.57.0",
|
"rollup": "^2.57.0",
|
||||||
"rollup-plugin-brotli": "^3.1.0",
|
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
"rollup-plugin-copy": "^3.4.0",
|
||||||
"rollup-plugin-html-minifier": "^2.0.0",
|
"rollup-plugin-html-minifier": "^2.0.0",
|
||||||
"rollup-plugin-livereload": "^2.0.5",
|
"rollup-plugin-livereload": "^2.0.5",
|
||||||
|
|
@ -43,8 +41,7 @@
|
||||||
"svelte-keydown": "^0.3.1",
|
"svelte-keydown": "^0.3.1",
|
||||||
"svelte-modals": "^1.0.4",
|
"svelte-modals": "^1.0.4",
|
||||||
"svelte-preprocess": "^4.9.5",
|
"svelte-preprocess": "^4.9.5",
|
||||||
"tslib": "^2.5.0",
|
"typescript": "^4.4.3"
|
||||||
"typescript": "^4.9.5"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
|
|
@ -2761,9 +2758,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001462",
|
"version": "1.0.30001460",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001462.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz",
|
||||||
"integrity": "sha512-PDd20WuOBPiasZ7KbFnmQRyuLE7cFXW2PVd7dmALzbkUXEP46upAuCDm9eY9vho8fgNMGmbAX92QBZHzcnWIqw==",
|
"integrity": "sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -2976,9 +2973,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.325",
|
"version": "1.4.320",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.325.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.320.tgz",
|
||||||
"integrity": "sha512-K1C03NT4I7BuzsRdCU5RWkgZxtswnKDYM6/eMhkEXqKu4e5T+ck610x3FPzu1y7HVFSiQKZqP16gnJzPpji1TQ==",
|
"integrity": "sha512-h70iRscrNluMZPVICXYl5SSB+rBKo22XfuIS1ER0OQxQZpKTnFpuS6coj7wY9M/3trv7OR88rRMOlKmRvDty7Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
|
|
@ -4492,9 +4489,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/resolve.exports": {
|
"node_modules/resolve.exports": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz",
|
||||||
"integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==",
|
"integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
|
|
@ -4540,15 +4537,6 @@
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup-plugin-brotli": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/rollup-plugin-brotli/-/rollup-plugin-brotli-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-vXRPVd9B1x+aaXeBdmLKNNsai9AH3o0Qikf4u0m1icKqgi3qVA4UhOfwGaPYoAHML1GLMUnR//PDhiMHXN/M6g==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=11.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/rollup-plugin-copy": {
|
"node_modules/rollup-plugin-copy": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
|
||||||
|
|
@ -5162,10 +5150,6 @@
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/talon-client": {
|
|
||||||
"version": "0.1.0",
|
|
||||||
"resolved": "file:../talon-client"
|
|
||||||
},
|
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.16.5",
|
"version": "5.16.5",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz",
|
||||||
|
|
@ -5242,9 +5226,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.5.0",
|
"version": "1.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/tsutils": {
|
"node_modules/tsutils": {
|
||||||
|
|
@ -5262,12 +5246,6 @@
|
||||||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tsutils/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/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"start": "sirv public --single",
|
"start": "sirv public --single",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"fix": "eslint . --fix",
|
"fix": "eslint . --fix",
|
||||||
"check": "svelte-check --tsconfig ../../tsconfig.json",
|
"check": "svelte-check --tsconfig tsconfig.json",
|
||||||
"format": "prettier --plugin=./node_modules/prettier-plugin-svelte --write .",
|
"format": "prettier --plugin=./node_modules/prettier-plugin-svelte --write .",
|
||||||
"pc": "npm run fix & npm run check & npm run format",
|
"pc": "npm run fix & npm run check & npm run format",
|
||||||
"ci": "npm run lint & npm run check & prettier --plugin=./node_modules/prettier-plugin-svelte --check ."
|
"ci": "npm run lint & npm run check & prettier --plugin=./node_modules/prettier-plugin-svelte --check ."
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"@babel/preset-typescript": "^7.15.0",
|
"@babel/preset-typescript": "^7.15.0",
|
||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@rollup/plugin-babel": "^5.3.0",
|
||||||
"@rollup/plugin-commonjs": "^20.0.0",
|
"@rollup/plugin-commonjs": "^20.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
"@rollup/plugin-node-resolve": "^13.0.5",
|
||||||
"@rollup/plugin-replace": "^3.0.0",
|
"@rollup/plugin-replace": "^3.0.0",
|
||||||
"@rollup/plugin-typescript": "^8.2.5",
|
"@rollup/plugin-typescript": "^8.2.5",
|
||||||
"@rollup/pluginutils": "^4.1.1",
|
"@rollup/pluginutils": "^4.1.1",
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"prettier-plugin-svelte": "^1.2.0",
|
"prettier-plugin-svelte": "^1.2.0",
|
||||||
"rollup": "^2.57.0",
|
"rollup": "^2.57.0",
|
||||||
"rollup-plugin-brotli": "^3.1.0",
|
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
"rollup-plugin-copy": "^3.4.0",
|
||||||
"rollup-plugin-html-minifier": "^2.0.0",
|
"rollup-plugin-html-minifier": "^2.0.0",
|
||||||
"rollup-plugin-livereload": "^2.0.5",
|
"rollup-plugin-livereload": "^2.0.5",
|
||||||
|
|
@ -45,13 +44,11 @@
|
||||||
"svelte-keydown": "^0.3.1",
|
"svelte-keydown": "^0.3.1",
|
||||||
"svelte-modals": "^1.0.4",
|
"svelte-modals": "^1.0.4",
|
||||||
"svelte-preprocess": "^4.9.5",
|
"svelte-preprocess": "^4.9.5",
|
||||||
"tslib": "^2.5.0",
|
"typescript": "^4.4.3"
|
||||||
"typescript": "^4.9.5"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||||
"minify-html-stream": "^0.3.1",
|
"minify-html-stream": "^0.3.1"
|
||||||
"talon-client": "file:../talon-client"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,11 @@
|
||||||
fill="#000000"
|
fill="#000000"
|
||||||
font-family="sans-serif"
|
font-family="sans-serif"
|
||||||
font-size="40px"
|
font-size="40px"
|
||||||
style="line-height: 1.25; shape-inside: url(#rect3620); white-space: pre"
|
style="
|
||||||
|
line-height: 1.25;
|
||||||
|
shape-inside: url(#rect3620);
|
||||||
|
white-space: pre;
|
||||||
|
"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
/>
|
/>
|
||||||
<g
|
<g
|
||||||
|
|
@ -102,98 +106,191 @@
|
||||||
</div>
|
</div>
|
||||||
<h1>development</h1>
|
<h1>development</h1>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar plum
|
Carrot cake biscuit icing pudding danish topping powder. Croissant sugar
|
||||||
pudding halvah chocolate. Cotton candy tart cake bonbon tart. Shortbread jelly
|
plum pudding halvah chocolate. Cotton candy tart cake bonbon tart.
|
||||||
fruitcake icing pastry. Dragée dessert cupcake cake sesame snaps toffee pie.
|
Shortbread jelly fruitcake icing pastry. Dragée dessert cupcake cake
|
||||||
Sweet roll sweet roll chupa chups jelly-o gummies tootsie roll sweet halvah oat
|
sesame snaps toffee pie. Sweet roll sweet roll chupa chups jelly-o
|
||||||
cake. Carrot cake carrot cake muffin bonbon sesame snaps brownie. Bonbon candy
|
gummies tootsie roll sweet halvah oat cake. Carrot cake carrot cake
|
||||||
macaroon fruitcake candy canes. Cake pudding danish liquorice cupcake jelly-o
|
muffin bonbon sesame snaps brownie. Bonbon candy macaroon fruitcake
|
||||||
ice cream. Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
candy canes. Cake pudding danish liquorice cupcake jelly-o ice cream.
|
||||||
candy canes donut lemon drops apple pie danish bear claw. Caramels cake jelly
|
Liquorice lollipop danish tootsie roll toffee. Gingerbread chocolate
|
||||||
jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop pudding
|
candy canes donut lemon drops apple pie danish bear claw. Caramels cake
|
||||||
marshmallow candy canes tootsie roll danish.
|
jelly jelly sweet chocolate bar gingerbread icing. Cake soufflé lollipop
|
||||||
|
pudding marshmallow candy canes tootsie roll danish.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script id="talon-config" type="application/json">
|
<script id="talon-data" type="application/json">
|
||||||
{
|
{
|
||||||
"api": "http://talon.localhost:3000/api",
|
"root_path": "/",
|
||||||
"version": "0.1.0",
|
"current_page": "2",
|
||||||
"root_domain": "localhost:3000"
|
"current_version": "6",
|
||||||
|
"versions": {
|
||||||
|
"3": {
|
||||||
|
"date": "2021-06-15T11:12:21+00:00",
|
||||||
|
"name": "0.1.0",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "ec55eba5ae45640c3d225c2471920fd3c9a36489"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"date": "2021-06-20T16:48:21+00:00",
|
||||||
|
"name": "0.1.1",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "ec55eba5ae45640c3d225c2471920fd3c9a36489"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"date": "2021-06-22T12:08:21+00:00",
|
||||||
|
"name": "0.1.2",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "ec55eba5ae45640c3d225c2471920fd3c9a36489"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"date": "2021-07-02T16:12:40+00:00",
|
||||||
|
"name": "0.1.3",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "bbc7342580b48433481857bfe95e58784a508275"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pages": {
|
||||||
|
"1": {
|
||||||
|
"name": "ThetaDev",
|
||||||
|
"path": "",
|
||||||
|
"color": "#1f91ee",
|
||||||
|
"visibility": "featured",
|
||||||
|
"source": {
|
||||||
|
"url": "https://github.com/Theta-Dev",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "Talon",
|
||||||
|
"path": "Talon",
|
||||||
|
"color": "#4b228a",
|
||||||
|
"visibility": "featured",
|
||||||
|
"source": {
|
||||||
|
"url": "https://github.com/Theta-Dev/Talon",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"name": "Spotify-Gender-Ex",
|
||||||
|
"path": "Spotify-Gender-Ex",
|
||||||
|
"color": "#1DB954",
|
||||||
|
"image": "https://raw.githubusercontent.com/Theta-Dev/Spotify-Gender-Ex/master/assets/logo_square.svg",
|
||||||
|
"visibility": "featured",
|
||||||
|
"source": {
|
||||||
|
"url": "https://github.com/Theta-Dev/Spotify-Gender-Ex",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "A1",
|
||||||
|
"path": "tests/a1",
|
||||||
|
"color": "#ff0000",
|
||||||
|
"visibility": "searchable"
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"name": "B1",
|
||||||
|
"path": "tests/b1",
|
||||||
|
"color": "#00ff00",
|
||||||
|
"visibility": "searchable"
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"name": "C1",
|
||||||
|
"path": "tests/c1",
|
||||||
|
"color": "#0000ff",
|
||||||
|
"visibility": "searchable"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="./talon.js"></script>
|
<script src="./talon.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import sveltePreprocess from "svelte-preprocess"
|
||||||
import typescript from "@rollup/plugin-typescript"
|
import typescript from "@rollup/plugin-typescript"
|
||||||
import replace from "@rollup/plugin-replace"
|
import replace from "@rollup/plugin-replace"
|
||||||
import babel from "@rollup/plugin-babel"
|
import babel from "@rollup/plugin-babel"
|
||||||
import brotli from "rollup-plugin-brotli"
|
|
||||||
|
|
||||||
import css from ".rollup/css-only"
|
import css from ".rollup/css-only"
|
||||||
import {serve} from ".rollup/serve"
|
import {serve} from ".rollup/serve"
|
||||||
|
|
@ -149,8 +148,6 @@ export default {
|
||||||
],
|
],
|
||||||
babelHelpers: "bundled",
|
babelHelpers: "bundled",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
brotli(),
|
|
||||||
],
|
],
|
||||||
watch: {
|
watch: {
|
||||||
chokidar: true,
|
chokidar: true,
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,16 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import {closeModal, Modals} from "svelte-modals"
|
||||||
import { closeModal, Modals } from "svelte-modals";
|
|
||||||
import type { Website } from "ui/talon-client/src";
|
|
||||||
|
|
||||||
import Menu from "./components/Menu.svelte";
|
import Menu from "./components/Menu.svelte"
|
||||||
import { currentWebsiteStore, fetchWebsites } from "./util/api";
|
import {currentPage, isPresent} from "./util/talonData"
|
||||||
|
|
||||||
let currentWebsite: Website;
|
|
||||||
|
|
||||||
currentWebsiteStore.subscribe((ws) => {
|
|
||||||
console.log("current ws changed", ws);
|
|
||||||
currentWebsite = ws;
|
|
||||||
});
|
|
||||||
|
|
||||||
onMount(fetchWebsites);
|
|
||||||
|
|
||||||
let color: String;
|
|
||||||
$: {
|
|
||||||
if (currentWebsite && currentWebsite.color) {
|
|
||||||
color = currentWebsite.color;
|
|
||||||
} else {
|
|
||||||
color = "#7935df";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
|
// Default theme
|
||||||
|
.wrapper
|
||||||
|
--talon-color: #7935df
|
||||||
|
|
||||||
.backdrop
|
.backdrop
|
||||||
position: fixed
|
position: fixed
|
||||||
top: 0
|
top: 0
|
||||||
|
|
@ -36,13 +20,12 @@
|
||||||
background: rgba(0, 0, 0, 0.6)
|
background: rgba(0, 0, 0, 0.6)
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="wrapper" style={`--talon-color: ${color}`}>
|
<div class="wrapper" style={`--talon-color: ${currentPage.color}`}>
|
||||||
{#if currentWebsite}
|
{#if isPresent}
|
||||||
<Menu />
|
<Menu />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Modals>
|
<Modals>
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
||||||
<div class="backdrop" slot="backdrop" on:click={closeModal} />
|
<div class="backdrop" slot="backdrop" on:click={closeModal} />
|
||||||
</Modals>
|
</Modals>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let imageSrc: string;
|
export let imageSrc: string
|
||||||
export let size = 32;
|
export let size = 32
|
||||||
export let scale = 1;
|
export let scale = 1
|
||||||
export let alt = "??";
|
export let alt = "??"
|
||||||
export let color = "#4b228a";
|
export let color = "#4b228a"
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,63 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fly } from "svelte/transition";
|
import {fly} from "svelte/transition"
|
||||||
import { closeModal } from "svelte-modals";
|
import {closeModal} from "svelte-modals"
|
||||||
import Keydown from "svelte-keydown";
|
import Keydown from "svelte-keydown"
|
||||||
|
|
||||||
import PageIcon from "./PageIcon.svelte";
|
import type {TalonVersion} from "../util/types"
|
||||||
import Icon from "./Icon.svelte";
|
import PageIcon from "./PageIcon.svelte"
|
||||||
import { formatDate, getWebsiteVersionUrl } from "../util/functions";
|
import Icon from "./Icon.svelte"
|
||||||
import InlineIcon from "./InlineIcon.svelte";
|
import {formatDate} from "../util/functions"
|
||||||
import Tag from "./Tag.svelte";
|
import InlineIcon from "./InlineIcon.svelte"
|
||||||
import type { Version, Website } from "talon-client";
|
import Tag from "./Tag.svelte"
|
||||||
import { client, currentWebsiteStore } from "../util/api";
|
import {
|
||||||
import { talonConfig } from "../util/talonData";
|
currentPage,
|
||||||
|
currentVersion,
|
||||||
|
currentVersionId,
|
||||||
|
rootPath,
|
||||||
|
versions,
|
||||||
|
} from "../util/talonData"
|
||||||
|
|
||||||
let currentWebsite: Website;
|
export let isOpen: boolean
|
||||||
currentWebsiteStore.subscribe((ws) => {
|
|
||||||
currentWebsite = ws;
|
|
||||||
});
|
|
||||||
|
|
||||||
export let isOpen: boolean;
|
function getVersionName(versionId: string, version: TalonVersion): string {
|
||||||
$: {
|
return version.name ? version.name : "#" + versionId
|
||||||
if (isOpen && currentWebsite) {
|
|
||||||
client
|
|
||||||
.websiteSubdomainVersionsGet({ subdomain: currentWebsite.subdomain })
|
|
||||||
.then((v) => {
|
|
||||||
versions = v;
|
|
||||||
if (v && v.length > 0) {
|
|
||||||
currentVersion = v[v.length - 1];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let versions: Version[] = [];
|
function getVersionUrl(versionId: string, version: TalonVersion): string {
|
||||||
let currentVersion: Version = null;
|
return (
|
||||||
|
rootPath +
|
||||||
|
(currentPage && version.name
|
||||||
|
? currentPage.path + "@" + version.name
|
||||||
|
: "&v/" + versionId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let versionName: string
|
||||||
|
$: versionName = getVersionName(currentVersionId, currentVersion)
|
||||||
|
|
||||||
|
let versionUrl: string
|
||||||
|
$: versionUrl = getVersionUrl(currentVersionId, currentVersion)
|
||||||
|
|
||||||
|
let uploadDate: string
|
||||||
|
$: uploadDate = formatDate(currentVersion.date)
|
||||||
|
|
||||||
|
let pageTags: [string, string][]
|
||||||
|
$: pageTags = currentVersion.tags
|
||||||
|
? Object.entries(currentVersion.tags).map(([key, val]) => [
|
||||||
|
key.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
|
val,
|
||||||
|
])
|
||||||
|
: []
|
||||||
|
|
||||||
|
let history: [string, string, string][]
|
||||||
|
$: history = Object.entries(versions)
|
||||||
|
.filter((e) => e[0] !== currentVersionId)
|
||||||
|
.map(([key, version]) => [
|
||||||
|
formatDate(version.date),
|
||||||
|
getVersionName(key, version),
|
||||||
|
getVersionUrl(key, version),
|
||||||
|
])
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
|
|
@ -118,55 +143,62 @@
|
||||||
|
|
||||||
<Keydown paused={!isOpen} on:Escape={closeModal} />
|
<Keydown paused={!isOpen} on:Escape={closeModal} />
|
||||||
|
|
||||||
{#if isOpen && currentWebsite}
|
{#if isOpen}
|
||||||
<div class="modal" role="dialog" transition:fly={{y: 50}} on:introstart on:outroend>
|
<div class="modal" role="dialog" transition:fly={{y: 50}} on:introstart on:outroend>
|
||||||
<div>
|
<div>
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
<PageIcon website={currentWebsite} size={60} scale={0.8} />
|
<PageIcon page={currentPage} size={60} scale={0.8} />
|
||||||
<span>{currentWebsite.name}</span>
|
<span>{currentPage ? currentPage.name : 'v' + currentVersionId}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if currentVersion}
|
{#if !currentPage}
|
||||||
|
<p>
|
||||||
|
This is a dangling version, i.e. it does not belong to a page.
|
||||||
|
Assign it to a page or it will be purged within 24 hours.
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<p class="dhead">
|
<p class="dhead">
|
||||||
<InlineIcon iconName="question" />
|
<InlineIcon iconName="question" />
|
||||||
Current version #{currentVersion.id}
|
Current version
|
||||||
</p>
|
</p>
|
||||||
<Tag key="Upload date" value={formatDate(currentVersion.createdAt)} />
|
|
||||||
<!--<Tag key="Uploaded by" value={currentVersion.user} />-->
|
|
||||||
|
|
||||||
{#each Object.entries(currentVersion.data) as [key, value]}
|
<Tag key="Version" value={versionName} href={versionUrl} />
|
||||||
|
<Tag key="Upload date" value={uploadDate} />
|
||||||
|
<Tag key="Uploaded by" value={currentVersion.user} />
|
||||||
|
|
||||||
|
{#each pageTags as [key, value]}
|
||||||
<Tag {key} {value} />
|
<Tag {key} {value} />
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
{#if versions && versions.length}
|
{#if history.length}
|
||||||
<p class="dhead">
|
<p class="dhead">
|
||||||
<InlineIcon iconName="history" />
|
<InlineIcon iconName="history" />
|
||||||
History
|
History
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{#each versions as version}
|
{#each history as [date, name, url]}
|
||||||
<p class="smalltag">
|
<p class="smalltag">
|
||||||
<a href={getWebsiteVersionUrl(currentWebsite.subdomain, version.id)}>
|
<a href={url}> <span>{name}</span> <span>{date}</span> </a>
|
||||||
<span>#{version.id}</span>
|
|
||||||
<span>{formatDate(version.createdAt)}</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
|
||||||
|
|
||||||
<p class="dhead" />
|
<p class="dhead" />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Powered by
|
This site is powered by
|
||||||
<a
|
<a
|
||||||
href="https://code.thetadev.de/ThetaDev/Talon/src/tag/{talonConfig.version}"
|
href="https://github.com/Theta-Dev/Talon/tree/__VERSION__"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
referrerpolicy="no-referrer">Talon __VERSION__</a>, a static site
|
||||||
referrerpolicy="no-referrer">Talon
|
management system created by
|
||||||
{talonConfig.version}</a>
|
<a
|
||||||
|
href="https://thetadev.de"
|
||||||
|
target="_blank"
|
||||||
|
referrerpolicy="no-referrer">ThetaDev</a>
|
||||||
</div>
|
</div>
|
||||||
<!--<p><a href="" target="_blank">View licenses</a></p>-->
|
<p><a href={rootPath + '&credits'} target="_blank">View licenses</a></p>
|
||||||
<button on:click={closeModal}>
|
<button on:click={closeModal}>
|
||||||
<Icon iconName="close" size={40} scale={0.6} transparent={true} />
|
<Icon iconName="close" size={40} scale={0.6} transparent={true} />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,97 +1,87 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { openModal } from "svelte-modals";
|
import {openModal} from "svelte-modals"
|
||||||
|
|
||||||
import Icon from "./Icon.svelte";
|
import Icon from "./Icon.svelte"
|
||||||
import MenuItem from "./MenuItem.svelte";
|
import MenuItem from "./MenuItem.svelte"
|
||||||
import MenuItemPage from "./MenuItemPage.svelte";
|
import MenuItemPage from "./MenuItemPage.svelte"
|
||||||
import InfoModal from "./InfoModal.svelte";
|
import InfoModal from "./InfoModal.svelte"
|
||||||
import FloatingButton from "./FloatingButton.svelte";
|
import FloatingButton from "./FloatingButton.svelte"
|
||||||
|
|
||||||
import type { Focusable } from "../util/types";
|
import type {Focusable, TalonPage} from "../util/types"
|
||||||
import PageIcon from "./PageIcon.svelte";
|
import {TalonVisibility} from "../util/types"
|
||||||
import MenuItemInput from "./MenuItemInput.svelte";
|
import PageIcon from "./PageIcon.svelte"
|
||||||
import { currentWebsiteStore, websitesStore } from "../util/api";
|
import MenuItemInput from "./MenuItemInput.svelte"
|
||||||
import { Visibility, Website } from "talon-client";
|
import {currentPage, currentPageId, pages, rootPath} from "../util/talonData"
|
||||||
import { getWebsiteUrl } from "../util/functions";
|
|
||||||
|
|
||||||
let currentWebsite: Website;
|
|
||||||
let websites: Website[];
|
|
||||||
|
|
||||||
currentWebsiteStore.subscribe((ws) => {
|
|
||||||
currentWebsite = ws;
|
|
||||||
});
|
|
||||||
websitesStore.subscribe((ws) => {
|
|
||||||
websites = ws;
|
|
||||||
});
|
|
||||||
|
|
||||||
function showSidebar(): void {
|
function showSidebar(): void {
|
||||||
sidebarShown = true;
|
sidebarShown = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideSidebar(): void {
|
function hideSidebar(): void {
|
||||||
sidebarShown = false;
|
sidebarShown = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMobile(): boolean {
|
function isMobile(): boolean {
|
||||||
return window.innerWidth < 768;
|
return window.innerWidth < 768
|
||||||
}
|
}
|
||||||
|
|
||||||
function openSearch(): void {
|
function openSearch(): void {
|
||||||
searchOpen = true;
|
searchOpen = true
|
||||||
searchInput.focus();
|
searchInput.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeSearch() {
|
function closeSearch() {
|
||||||
searchOpen = false;
|
searchOpen = false
|
||||||
searchInput.blur();
|
searchInput.blur()
|
||||||
|
|
||||||
if (displayedWebsites.length === 0) searchText = "";
|
if (displayedPages.length === 0) searchText = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSearch() {
|
function clearSearch() {
|
||||||
searchText = "";
|
searchText = ""
|
||||||
closeSearch();
|
closeSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchKeypress(e: KeyboardEvent) {
|
function searchKeypress(e: KeyboardEvent) {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case "Enter":
|
case "Enter":
|
||||||
if (!searchText) {
|
if (!searchText) {
|
||||||
closeSearch();
|
closeSearch()
|
||||||
} else if (displayedWebsites.length) {
|
} else if (displayedPages.length) {
|
||||||
window.location.href = getWebsiteUrl(displayedWebsites[0].subdomain);
|
window.location.href = rootPath + displayedPages[0].path
|
||||||
} else {
|
} else {
|
||||||
closeSearch();
|
closeSearch()
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
case "Escape":
|
case "Escape":
|
||||||
clearSearch();
|
clearSearch()
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openInfo() {
|
function openInfo() {
|
||||||
openModal(InfoModal);
|
openModal(InfoModal)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sidebarShown = !isMobile();
|
let sidebarShown = !isMobile()
|
||||||
let searchInput: Focusable;
|
let searchInput: Focusable
|
||||||
let searchOpen = false;
|
let searchOpen = false
|
||||||
let searchText = "";
|
let searchText = ""
|
||||||
|
|
||||||
let displayedWebsites: Website[];
|
let displayedPages: TalonPage[]
|
||||||
|
$: displayedPages = Object.entries(pages)
|
||||||
$: displayedWebsites = websites.filter((ws) => {
|
.filter(([id, page]) => {
|
||||||
if (ws.subdomain == currentWebsite.subdomain) return false;
|
if (id === currentPageId) return false
|
||||||
|
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
return (
|
return (
|
||||||
ws.visibility !== Visibility.Hidden &&
|
page.visibility !== TalonVisibility.HIDDEN &&
|
||||||
ws.name.toLowerCase().includes(searchText.toLowerCase())
|
page.name.toLowerCase().includes(searchText.toLowerCase())
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
return ws.visibility === Visibility.Featured;
|
return page.visibility === TalonVisibility.FEATURED
|
||||||
});
|
})
|
||||||
|
.map(([, page]) => page)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -138,22 +128,25 @@
|
||||||
bind:text={searchText} />
|
bind:text={searchText} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{#each displayedWebsites as website, i}
|
{#each displayedPages as page, i}
|
||||||
<MenuItemPage {website} active={searchOpen && searchText && i === 0} />
|
<MenuItemPage
|
||||||
|
{page}
|
||||||
|
{rootPath}
|
||||||
|
active={searchOpen && searchText && i === 0} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{#if currentWebsite && currentWebsite.sourceUrl}
|
{#if currentPage && currentPage.source}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text="View source"
|
text="View source"
|
||||||
link={currentWebsite.sourceUrl}
|
link={currentPage.source.url}
|
||||||
newTab={true}
|
newTab={true}
|
||||||
privacy={true}>
|
privacy={true}>
|
||||||
<Icon iconName={currentWebsite.sourceIcon} size={40} scale={0.6} />
|
<Icon iconName={currentPage.source.type} size={40} scale={0.6} />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{/if}
|
{/if}
|
||||||
<MenuItem text="Info" on:click={openInfo}>
|
<MenuItem text="Info" on:click={openInfo}>
|
||||||
<PageIcon website={currentWebsite} />
|
<PageIcon page={currentPage} />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem text="Hide sidebar" on:click={hideSidebar}>
|
<MenuItem text="Hide sidebar" on:click={hideSidebar}>
|
||||||
<Icon iconName="arrowRight" size={40} scale={0.6} />
|
<Icon iconName="arrowRight" size={40} scale={0.6} />
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import PageIcon from "./PageIcon.svelte";
|
import type {TalonPage} from "../util/types"
|
||||||
import MenuItem from "./MenuItem.svelte";
|
import PageIcon from "./PageIcon.svelte"
|
||||||
import type { Website } from "talon-client";
|
import MenuItem from "./MenuItem.svelte"
|
||||||
import { getWebsiteUrl } from "../util/functions";
|
|
||||||
|
|
||||||
export let website: Website;
|
export let page: TalonPage
|
||||||
export let active = false;
|
export let rootPath = "/"
|
||||||
|
export let active = false
|
||||||
|
|
||||||
const MAX_TEXT_LEN = 20;
|
const MAX_TEXT_LEN = 20
|
||||||
|
|
||||||
let text: string;
|
let text: string
|
||||||
$: text =
|
$: text =
|
||||||
website.name.length > MAX_TEXT_LEN
|
page.name.length > MAX_TEXT_LEN
|
||||||
? website.name.substring(0, 20).trim() + "..."
|
? page.name.substr(0, 20).trim() + "..."
|
||||||
: website.name;
|
: page.name
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<MenuItem {active} {text} link={getWebsiteUrl(website.subdomain)}>
|
<MenuItem {active} {text} link={rootPath + page.path}>
|
||||||
<PageIcon {website} />
|
<PageIcon {page} />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ImageIcon from "./ImageIcon.svelte"
|
import ImageIcon from "./ImageIcon.svelte"
|
||||||
import Icon from "./Icon.svelte"
|
import Icon from "./Icon.svelte"
|
||||||
import type { Website } from "ui/apiclient";
|
import type {TalonPage} from "../util/types"
|
||||||
|
|
||||||
export let website: Website
|
export let page: TalonPage
|
||||||
export let size = 40
|
export let size = 40
|
||||||
export let scale = 0.8
|
export let scale = 0.8
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if website}
|
{#if page}
|
||||||
<ImageIcon
|
<ImageIcon
|
||||||
imageSrc=""
|
imageSrc={page.image}
|
||||||
color={website.color}
|
color={page.color}
|
||||||
alt={website.name.substring(0, 2)}
|
alt={page.name.substr(0, 2)}
|
||||||
{size}
|
{size}
|
||||||
{scale} />
|
{scale} />
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const sidebar = document.createElement("talon-sidebar");
|
const sidebar = document.createElement("talon-sidebar")
|
||||||
document.body.append(sidebar);
|
document.body.append(sidebar)
|
||||||
|
|
||||||
export { default as default } from "./App.svelte";
|
export {default as default} from "./App.svelte"
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import {Writable, writable} from "svelte/store"
|
|
||||||
|
|
||||||
import {Configuration, DefaultApi, Website} from "talon-client"
|
|
||||||
import {getSubdomain} from "./functions"
|
|
||||||
import { talonConfig } from "./talonData"
|
|
||||||
|
|
||||||
export const websitesStore: Writable<Website[]> = writable([])
|
|
||||||
export const currentWebsiteStore: Writable<Website> = writable(null)
|
|
||||||
|
|
||||||
export const client = new DefaultApi(new Configuration({basePath: talonConfig.api}));
|
|
||||||
|
|
||||||
export function fetchWebsites(): void {
|
|
||||||
client.websitesGet().then((ws) => {
|
|
||||||
websitesStore.set(ws)
|
|
||||||
const subdomain = getSubdomain()
|
|
||||||
currentWebsiteStore.set(ws.find((w) => w.subdomain == subdomain))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +1,5 @@
|
||||||
import {talonConfig} from "./talonData"
|
function formatDate(dateString: string): string {
|
||||||
|
return new Date(dateString).toLocaleString(navigator.language)
|
||||||
export function formatDate(date: Date): string {
|
|
||||||
return date.toLocaleString(navigator.language)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSubdomain(): string {
|
export {formatDate}
|
||||||
const hn = window.location.hostname
|
|
||||||
const rd_noport = talonConfig.root_domain.split(":", 1)[0]
|
|
||||||
|
|
||||||
if (hn.endsWith("." + rd_noport)) {
|
|
||||||
const subdomain = hn.substring(0, hn.length - rd_noport.length - 1).split("--", 1)[0]
|
|
||||||
if (subdomain === "x") {
|
|
||||||
return "-"
|
|
||||||
} else {
|
|
||||||
return subdomain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "-"
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getWebsiteUrl(subdomain: string): string {
|
|
||||||
const proto = window.location.protocol
|
|
||||||
|
|
||||||
if (subdomain === "-") {
|
|
||||||
return `${proto}//${talonConfig.root_domain}`
|
|
||||||
} else {
|
|
||||||
return `${proto}//${subdomain}.${talonConfig.root_domain}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getWebsiteVersionUrl(subdomain: string, version: number): string {
|
|
||||||
const proto = window.location.protocol
|
|
||||||
const v = `--v${version}`
|
|
||||||
|
|
||||||
if (subdomain === "-") {
|
|
||||||
return `${proto}//x${v}.${talonConfig.root_domain}`
|
|
||||||
} else {
|
|
||||||
return `${proto}//${subdomain}${v}.${talonConfig.root_domain}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,54 @@
|
||||||
import type {TalonConfig} from "./types"
|
import type {TalonData, TalonPage, TalonVersion} from "./types"
|
||||||
|
import {TalonVisibility} from "./types"
|
||||||
|
|
||||||
export const talonConfig: TalonConfig = JSON.parse(
|
const talonData: TalonData = JSON.parse(
|
||||||
document.getElementById("talon-config").textContent
|
document.getElementById("talon-data").textContent
|
||||||
) as TalonConfig
|
) as TalonData
|
||||||
|
|
||||||
// const rootPath = talonData.root_path
|
const isTalonData = (obj: TalonData) =>
|
||||||
|
"root_path" in obj &&
|
||||||
|
"current_page" in obj &&
|
||||||
|
"current_version" in obj &&
|
||||||
|
"versions" in obj &&
|
||||||
|
"pages" in obj
|
||||||
|
|
||||||
// const currentVersion = talonData.versions[talonData.current_version]
|
const isTalonVersion = (obj: TalonVersion) => "date" in obj && "user" in obj
|
||||||
// const currentVersionId = talonData.current_version
|
|
||||||
|
|
||||||
// const getCurrentPage = () => {
|
const rootPath = talonData.root_path
|
||||||
// if (talonData.current_page) {
|
|
||||||
// return talonData.pages[talonData.current_page]
|
|
||||||
// } else {
|
|
||||||
// return {
|
|
||||||
// name: "#" + talonData.current_version,
|
|
||||||
// path: "&v/" + talonData.current_version,
|
|
||||||
// color: "#7935df",
|
|
||||||
// visibility: TalonVisibility.HIDDEN,
|
|
||||||
// image: undefined,
|
|
||||||
// source: undefined,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const currentPage: TalonPage = getCurrentPage()
|
const currentVersion = talonData.versions[talonData.current_version]
|
||||||
// const currentPageId = talonData.current_page
|
const currentVersionId = talonData.current_version
|
||||||
|
|
||||||
// const isPresent = isTalonData(talonData) && isTalonVersion(currentVersion)
|
const getCurrentPage = () => {
|
||||||
|
if (talonData.current_page) {
|
||||||
|
return talonData.pages[talonData.current_page]
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
name: "#" + talonData.current_version,
|
||||||
|
path: "&v/" + talonData.current_version,
|
||||||
|
color: "#7935df",
|
||||||
|
visibility: TalonVisibility.HIDDEN,
|
||||||
|
image: undefined,
|
||||||
|
source: undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// const versions = talonData.versions
|
const currentPage: TalonPage = getCurrentPage()
|
||||||
// const pages = talonData.pages
|
const currentPageId = talonData.current_page
|
||||||
|
|
||||||
|
const isPresent = isTalonData(talonData) && isTalonVersion(currentVersion)
|
||||||
|
|
||||||
|
const versions = talonData.versions
|
||||||
|
const pages = talonData.pages
|
||||||
|
|
||||||
|
export {
|
||||||
|
rootPath,
|
||||||
|
isPresent,
|
||||||
|
currentVersion,
|
||||||
|
currentVersionId,
|
||||||
|
currentPage,
|
||||||
|
currentPageId,
|
||||||
|
versions,
|
||||||
|
pages,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,54 @@
|
||||||
export interface TalonConfig {
|
export interface TalonData {
|
||||||
api: string;
|
root_path: string
|
||||||
version: string;
|
current_page: string | null
|
||||||
root_domain: string;
|
current_version: string
|
||||||
|
versions: {[key: string]: TalonVersion}
|
||||||
|
pages: {[key: string]: TalonPage}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TalonPage {
|
||||||
|
name: string
|
||||||
|
path: string
|
||||||
|
color: string
|
||||||
|
visibility: TalonVisibility
|
||||||
|
image: string | undefined
|
||||||
|
source: TalonLink | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TalonVisibility {
|
||||||
|
FEATURED = "featured",
|
||||||
|
SEARCHABLE = "searchable",
|
||||||
|
HIDDEN = "hidden",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TalonLink {
|
||||||
|
url: string
|
||||||
|
type: TalonLinkType
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TalonLinkType {
|
||||||
|
LINK = "link",
|
||||||
|
GIT = "git",
|
||||||
|
GITHUB = "github",
|
||||||
|
GITLAB = "gitlab",
|
||||||
|
GITEA = "gitea",
|
||||||
|
BITBUCKET = "bitbucket",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TalonVersion {
|
||||||
|
date: string
|
||||||
|
name: string | undefined
|
||||||
|
user: string
|
||||||
|
tags: {[key: string]: string} | undefined
|
||||||
|
}
|
||||||
|
|
||||||
export interface Focusable {
|
export interface Focusable {
|
||||||
focus(): void;
|
focus(): void
|
||||||
blur(): void;
|
blur(): void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SvelteActionRes {
|
export interface SvelteActionRes {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
update?: (parameters: any) => void;
|
update?: (parameters: any) => void
|
||||||
destroy?: () => void;
|
destroy?: () => void
|
||||||
}
|
}
|
||||||
|
|
|
||||||
90
ui/menu/testdata/test.json
vendored
Normal file
90
ui/menu/testdata/test.json
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
{
|
||||||
|
"root_path": "/",
|
||||||
|
"current_page": null,
|
||||||
|
"current_version": "6",
|
||||||
|
"versions": {
|
||||||
|
"3": {
|
||||||
|
"date": "2021-06-15T11:12:21+00:00",
|
||||||
|
"name": "0.1.0",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "ec55eba5ae45640c3d225c2471920fd3c9a36489"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"date": "2021-06-20T16:48:21+00:00",
|
||||||
|
"name": "0.1.1",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "ec55eba5ae45640c3d225c2471920fd3c9a36489"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"date": "2021-06-22T12:08:21+00:00",
|
||||||
|
"name": "0.1.2",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "ec55eba5ae45640c3d225c2471920fd3c9a36489"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"date": "2021-07-02T16:12:40+00:00",
|
||||||
|
"name": "0.1.3",
|
||||||
|
"user": "ThetaDev",
|
||||||
|
"tags": {
|
||||||
|
"commit": "bbc7342580b48433481857bfe95e58784a508275"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pages": {
|
||||||
|
"1": {
|
||||||
|
"name": "ThetaDev",
|
||||||
|
"path": "",
|
||||||
|
"color": "#1f91ee",
|
||||||
|
"visibility": "featured",
|
||||||
|
"source": {
|
||||||
|
"url": "https://github.com/Theta-Dev",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "Talon",
|
||||||
|
"path": "Talon",
|
||||||
|
"color": "#4b228a",
|
||||||
|
"visibility": "featured",
|
||||||
|
"source": {
|
||||||
|
"url": "https://github.com/Theta-Dev/Talon",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"name": "Spotify-Gender-Ex",
|
||||||
|
"path": "Spotify-Gender-Ex",
|
||||||
|
"color": "#1DB954",
|
||||||
|
"image": "https://raw.githubusercontent.com/Theta-Dev/Spotify-Gender-Ex/master/assets/logo_square.svg",
|
||||||
|
"visibility": "featured",
|
||||||
|
"source": {
|
||||||
|
"url": "https://github.com/Theta-Dev/Spotify-Gender-Ex",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "A1",
|
||||||
|
"path": "tests/a1",
|
||||||
|
"color": "#ff0000",
|
||||||
|
"visibility": "searchable"
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"name": "B1",
|
||||||
|
"path": "tests/b1",
|
||||||
|
"color": "#00ff00",
|
||||||
|
"visibility": "searchable"
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"name": "C1",
|
||||||
|
"path": "tests/c1",
|
||||||
|
"color": "#0000ff",
|
||||||
|
"visibility": "searchable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
ui/menu/testdata/testSchema.json
vendored
Normal file
99
ui/menu/testdata/testSchema.json
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Talon menu data",
|
||||||
|
"definitions": {
|
||||||
|
"Version": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["date", "user"]
|
||||||
|
},
|
||||||
|
"Link": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["link", "git", "github", "gitlab", "gitea", "bitbucket"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["url", "type"]
|
||||||
|
},
|
||||||
|
"Page": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 100
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "regex",
|
||||||
|
"pattern": "^#[A-z\\d]{6}$"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri"
|
||||||
|
},
|
||||||
|
"visibility": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["featured", "searchable", "hidden"]
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"$ref": "#/definitions/Link"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name", "path", "color", "visibility"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"root_path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"current_page": {
|
||||||
|
"type": ["string", "null"]
|
||||||
|
},
|
||||||
|
"current_version": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"versions": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/definitions/Version"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pages": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/definitions/Page"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["root_path", "current_page", "current_version", "versions", "pages"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -32,10 +32,5 @@
|
||||||
* Use globals.d.ts instead of compilerOptions.types
|
* Use globals.d.ts instead of compilerOptions.types
|
||||||
* to avoid limiting type declarations.
|
* to avoid limiting type declarations.
|
||||||
*/
|
*/
|
||||||
"include": [
|
"include": ["globals.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||||
"ui/*/globals.d.ts",
|
|
||||||
"ui/*/src/**/*.ts",
|
|
||||||
"ui/*/src/**/*.js",
|
|
||||||
"ui/*/src/**/*.svelte"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
4
ui/talon-client/.gitignore
vendored
4
ui/talon-client/.gitignore
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
wwwroot/*.js
|
|
||||||
node_modules
|
|
||||||
typings
|
|
||||||
dist
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
README.md
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
.gitignore
|
|
||||||
.npmignore
|
|
||||||
.openapi-generator-ignore
|
|
||||||
README.md
|
|
||||||
package.json
|
|
||||||
src/apis/DefaultApi.ts
|
|
||||||
src/apis/index.ts
|
|
||||||
src/index.ts
|
|
||||||
src/models/Info.ts
|
|
||||||
src/models/InfoStats.ts
|
|
||||||
src/models/InfoVersion.ts
|
|
||||||
src/models/SourceIcon.ts
|
|
||||||
src/models/Stats.ts
|
|
||||||
src/models/Version.ts
|
|
||||||
src/models/VersionFile.ts
|
|
||||||
src/models/VersionInfo.ts
|
|
||||||
src/models/Visibility.ts
|
|
||||||
src/models/Website.ts
|
|
||||||
src/models/WebsiteNew.ts
|
|
||||||
src/models/WebsiteUpdate.ts
|
|
||||||
src/models/index.ts
|
|
||||||
src/runtime.ts
|
|
||||||
tsconfig.json
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
6.4.0
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
## talon-client@0.1.0
|
|
||||||
|
|
||||||
This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments:
|
|
||||||
|
|
||||||
Environment
|
|
||||||
* Node.js
|
|
||||||
* Webpack
|
|
||||||
* Browserify
|
|
||||||
|
|
||||||
Language level
|
|
||||||
* ES5 - you must have a Promises/A+ library installed
|
|
||||||
* ES6
|
|
||||||
|
|
||||||
Module system
|
|
||||||
* CommonJS
|
|
||||||
* ES6 module system
|
|
||||||
|
|
||||||
It can be used in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html))
|
|
||||||
|
|
||||||
### Building
|
|
||||||
|
|
||||||
To build and compile the typescript sources to javascript use:
|
|
||||||
```
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Publishing
|
|
||||||
|
|
||||||
First build the package then run ```npm publish```
|
|
||||||
|
|
||||||
### Consuming
|
|
||||||
|
|
||||||
navigate to the folder of your consuming project and run one of the following commands.
|
|
||||||
|
|
||||||
_published:_
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install talon-client@0.1.0 --save
|
|
||||||
```
|
|
||||||
|
|
||||||
_unPublished (not recommended):_
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install PATH_TO_GENERATED_PACKAGE --save
|
|
||||||
28
ui/talon-client/package-lock.json
generated
28
ui/talon-client/package-lock.json
generated
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"name": "talon-client",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "talon-client",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript": {
|
|
||||||
"version": "4.9.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
|
||||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"tsc": "bin/tsc",
|
|
||||||
"tsserver": "bin/tsserver"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"name": "talon-client",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "OpenAPI client for talon-client",
|
|
||||||
"author": "OpenAPI-Generator",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/GIT_USER_ID/GIT_REPO_ID.git"
|
|
||||||
},
|
|
||||||
"main": "./dist/index.js",
|
|
||||||
"typings": "./dist/index.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"prepare": "npm run build"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,559 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 {
|
|
||||||
Info,
|
|
||||||
Version,
|
|
||||||
VersionFile,
|
|
||||||
Visibility,
|
|
||||||
Website,
|
|
||||||
WebsiteNew,
|
|
||||||
WebsiteUpdate,
|
|
||||||
} from '../models';
|
|
||||||
import {
|
|
||||||
InfoFromJSON,
|
|
||||||
InfoToJSON,
|
|
||||||
VersionFromJSON,
|
|
||||||
VersionToJSON,
|
|
||||||
VersionFileFromJSON,
|
|
||||||
VersionFileToJSON,
|
|
||||||
VisibilityFromJSON,
|
|
||||||
VisibilityToJSON,
|
|
||||||
WebsiteFromJSON,
|
|
||||||
WebsiteToJSON,
|
|
||||||
WebsiteNewFromJSON,
|
|
||||||
WebsiteNewToJSON,
|
|
||||||
WebsiteUpdateFromJSON,
|
|
||||||
WebsiteUpdateToJSON,
|
|
||||||
} from '../models';
|
|
||||||
|
|
||||||
export interface FileHashGetRequest {
|
|
||||||
hash: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainDeleteRequest {
|
|
||||||
subdomain: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainGetRequest {
|
|
||||||
subdomain: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainPatchRequest {
|
|
||||||
subdomain: string;
|
|
||||||
websiteUpdate: WebsiteUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainPutRequest {
|
|
||||||
subdomain: string;
|
|
||||||
websiteNew: WebsiteNew;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainUploadPostRequest {
|
|
||||||
subdomain: string;
|
|
||||||
body: Blob;
|
|
||||||
fallback?: string;
|
|
||||||
spa?: boolean;
|
|
||||||
versionData?: { [key: string]: string; };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainVersionVersionDeleteRequest {
|
|
||||||
subdomain: string;
|
|
||||||
version: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainVersionVersionFilesGetRequest {
|
|
||||||
subdomain: string;
|
|
||||||
version: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainVersionVersionGetRequest {
|
|
||||||
subdomain: string;
|
|
||||||
version: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsiteSubdomainVersionsGetRequest {
|
|
||||||
subdomain: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsitesAllGetRequest {
|
|
||||||
visibility?: Visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsitesGetRequest {
|
|
||||||
visibility?: Visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
export class DefaultApi extends runtime.BaseAPI {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a file
|
|
||||||
*/
|
|
||||||
async fileHashGetRaw(requestParameters: FileHashGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Blob>> {
|
|
||||||
if (requestParameters.hash === null || requestParameters.hash === undefined) {
|
|
||||||
throw new runtime.RequiredError('hash','Required parameter requestParameters.hash was null or undefined when calling fileHashGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/file/{hash}`.replace(`{${"hash"}}`, encodeURIComponent(String(requestParameters.hash))),
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.BlobApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a file
|
|
||||||
*/
|
|
||||||
async fileHashGet(requestParameters: FileHashGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Blob> {
|
|
||||||
const response = await this.fileHashGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get information about your server
|
|
||||||
*/
|
|
||||||
async infoGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Info>> {
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/info`,
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => InfoFromJSON(jsonValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get information about your server
|
|
||||||
*/
|
|
||||||
async infoGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Info> {
|
|
||||||
const response = await this.infoGetRaw(initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainDeleteRaw(requestParameters: WebsiteSubdomainDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainDelete.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["X-API-Key"] = this.configuration.apiKey("X-API-Key"); // ApiKeyAuthorization authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))),
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.VoidApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainDelete(requestParameters: WebsiteSubdomainDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
|
|
||||||
await this.websiteSubdomainDeleteRaw(requestParameters, initOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainGetRaw(requestParameters: WebsiteSubdomainGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Website>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))),
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => WebsiteFromJSON(jsonValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainGet(requestParameters: WebsiteSubdomainGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Website> {
|
|
||||||
const response = await this.websiteSubdomainGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainPatchRaw(requestParameters: WebsiteSubdomainPatchRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainPatch.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.websiteUpdate === null || requestParameters.websiteUpdate === undefined) {
|
|
||||||
throw new runtime.RequiredError('websiteUpdate','Required parameter requestParameters.websiteUpdate was null or undefined when calling websiteSubdomainPatch.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
headerParameters['Content-Type'] = 'application/json; charset=utf-8';
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["X-API-Key"] = this.configuration.apiKey("X-API-Key"); // ApiKeyAuthorization authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))),
|
|
||||||
method: 'PATCH',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
body: WebsiteUpdateToJSON(requestParameters.websiteUpdate),
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.VoidApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainPatch(requestParameters: WebsiteSubdomainPatchRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
|
|
||||||
await this.websiteSubdomainPatchRaw(requestParameters, initOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainPutRaw(requestParameters: WebsiteSubdomainPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainPut.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.websiteNew === null || requestParameters.websiteNew === undefined) {
|
|
||||||
throw new runtime.RequiredError('websiteNew','Required parameter requestParameters.websiteNew was null or undefined when calling websiteSubdomainPut.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
headerParameters['Content-Type'] = 'application/json; charset=utf-8';
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["X-API-Key"] = this.configuration.apiKey("X-API-Key"); // ApiKeyAuthorization authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))),
|
|
||||||
method: 'PUT',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
body: WebsiteNewToJSON(requestParameters.websiteNew),
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.VoidApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new website
|
|
||||||
*/
|
|
||||||
async websiteSubdomainPut(requestParameters: WebsiteSubdomainPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
|
|
||||||
await this.websiteSubdomainPutRaw(requestParameters, initOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload a new version
|
|
||||||
*/
|
|
||||||
async websiteSubdomainUploadPostRaw(requestParameters: WebsiteSubdomainUploadPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainUploadPost.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.body === null || requestParameters.body === undefined) {
|
|
||||||
throw new runtime.RequiredError('body','Required parameter requestParameters.body was null or undefined when calling websiteSubdomainUploadPost.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
if (requestParameters.fallback !== undefined) {
|
|
||||||
queryParameters['fallback'] = requestParameters.fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.spa !== undefined) {
|
|
||||||
queryParameters['spa'] = requestParameters.spa;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.versionData !== undefined) {
|
|
||||||
queryParameters['version_data'] = requestParameters.versionData;
|
|
||||||
}
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
headerParameters['Content-Type'] = 'application/octet-stream';
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["X-API-Key"] = this.configuration.apiKey("X-API-Key"); // ApiKeyAuthorization authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}/upload`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))),
|
|
||||||
method: 'POST',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
body: requestParameters.body as any,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.VoidApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload a new version
|
|
||||||
*/
|
|
||||||
async websiteSubdomainUploadPost(requestParameters: WebsiteSubdomainUploadPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
|
|
||||||
await this.websiteSubdomainUploadPostRaw(requestParameters, initOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete version
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionVersionDeleteRaw(requestParameters: WebsiteSubdomainVersionVersionDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainVersionVersionDelete.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.version === null || requestParameters.version === undefined) {
|
|
||||||
throw new runtime.RequiredError('version','Required parameter requestParameters.version was null or undefined when calling websiteSubdomainVersionVersionDelete.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["X-API-Key"] = this.configuration.apiKey("X-API-Key"); // ApiKeyAuthorization authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}/version/{version}`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))).replace(`{${"version"}}`, encodeURIComponent(String(requestParameters.version))),
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.VoidApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete version
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionVersionDelete(requestParameters: WebsiteSubdomainVersionVersionDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
|
|
||||||
await this.websiteSubdomainVersionVersionDeleteRaw(requestParameters, initOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get version files
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionVersionFilesGetRaw(requestParameters: WebsiteSubdomainVersionVersionFilesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<VersionFile>>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainVersionVersionFilesGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.version === null || requestParameters.version === undefined) {
|
|
||||||
throw new runtime.RequiredError('version','Required parameter requestParameters.version was null or undefined when calling websiteSubdomainVersionVersionFilesGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}/version/{version}/files`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))).replace(`{${"version"}}`, encodeURIComponent(String(requestParameters.version))),
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(VersionFileFromJSON));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get version files
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionVersionFilesGet(requestParameters: WebsiteSubdomainVersionVersionFilesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<VersionFile>> {
|
|
||||||
const response = await this.websiteSubdomainVersionVersionFilesGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get version
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionVersionGetRaw(requestParameters: WebsiteSubdomainVersionVersionGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Version>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainVersionVersionGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.version === null || requestParameters.version === undefined) {
|
|
||||||
throw new runtime.RequiredError('version','Required parameter requestParameters.version was null or undefined when calling websiteSubdomainVersionVersionGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}/version/{version}`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))).replace(`{${"version"}}`, encodeURIComponent(String(requestParameters.version))),
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => VersionFromJSON(jsonValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get version
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionVersionGet(requestParameters: WebsiteSubdomainVersionVersionGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Version> {
|
|
||||||
const response = await this.websiteSubdomainVersionVersionGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get website versions
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionsGetRaw(requestParameters: WebsiteSubdomainVersionsGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<Version>>> {
|
|
||||||
if (requestParameters.subdomain === null || requestParameters.subdomain === undefined) {
|
|
||||||
throw new runtime.RequiredError('subdomain','Required parameter requestParameters.subdomain was null or undefined when calling websiteSubdomainVersionsGet.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/website/{subdomain}/versions`.replace(`{${"subdomain"}}`, encodeURIComponent(String(requestParameters.subdomain))),
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(VersionFromJSON));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get website versions
|
|
||||||
*/
|
|
||||||
async websiteSubdomainVersionsGet(requestParameters: WebsiteSubdomainVersionsGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<Version>> {
|
|
||||||
const response = await this.websiteSubdomainVersionsGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all websites from Talon\'s database (including hidden ones, if the current user has access to them). This endpoint requires authentication (use the `/websites` endpoint for unauthenticated users).
|
|
||||||
* Get all websites
|
|
||||||
*/
|
|
||||||
async websitesAllGetRaw(requestParameters: WebsitesAllGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<Website>>> {
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
if (requestParameters.visibility !== undefined) {
|
|
||||||
queryParameters['visibility'] = requestParameters.visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["X-API-Key"] = this.configuration.apiKey("X-API-Key"); // ApiKeyAuthorization authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/websitesAll`,
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(WebsiteFromJSON));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all websites from Talon\'s database (including hidden ones, if the current user has access to them). This endpoint requires authentication (use the `/websites` endpoint for unauthenticated users).
|
|
||||||
* Get all websites
|
|
||||||
*/
|
|
||||||
async websitesAllGet(requestParameters: WebsitesAllGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<Website>> {
|
|
||||||
const response = await this.websitesAllGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all publicly listed websites (visibility != `hidden`)
|
|
||||||
* Get all publicly listed websites
|
|
||||||
*/
|
|
||||||
async websitesGetRaw(requestParameters: WebsitesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<Website>>> {
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
if (requestParameters.visibility !== undefined) {
|
|
||||||
queryParameters['visibility'] = requestParameters.visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/websites`,
|
|
||||||
method: 'GET',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(WebsiteFromJSON));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all publicly listed websites (visibility != `hidden`)
|
|
||||||
* Get all publicly listed websites
|
|
||||||
*/
|
|
||||||
async websitesGet(requestParameters: WebsitesGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<Website>> {
|
|
||||||
const response = await this.websitesGetRaw(requestParameters, initOverrides);
|
|
||||||
return await response.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
export * from './DefaultApi';
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
export * from './runtime';
|
|
||||||
export * from './apis';
|
|
||||||
export * from './models';
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 { InfoStats } from './InfoStats';
|
|
||||||
import {
|
|
||||||
InfoStatsFromJSON,
|
|
||||||
InfoStatsFromJSONTyped,
|
|
||||||
InfoStatsToJSON,
|
|
||||||
} from './InfoStats';
|
|
||||||
import type { InfoVersion } from './InfoVersion';
|
|
||||||
import {
|
|
||||||
InfoVersionFromJSON,
|
|
||||||
InfoVersionFromJSONTyped,
|
|
||||||
InfoVersionToJSON,
|
|
||||||
} from './InfoVersion';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server information
|
|
||||||
* @export
|
|
||||||
* @interface Info
|
|
||||||
*/
|
|
||||||
export interface Info {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {InfoStats}
|
|
||||||
* @memberof Info
|
|
||||||
*/
|
|
||||||
stats: InfoStats;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {InfoVersion}
|
|
||||||
* @memberof Info
|
|
||||||
*/
|
|
||||||
version: InfoVersion;
|
|
||||||
/**
|
|
||||||
* Current uptime of the server in seconds
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Info
|
|
||||||
*/
|
|
||||||
uptime: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the Info interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfInfo(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "stats" in value;
|
|
||||||
isInstance = isInstance && "version" in value;
|
|
||||||
isInstance = isInstance && "uptime" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoFromJSON(json: any): Info {
|
|
||||||
return InfoFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): Info {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'stats': InfoStatsFromJSON(json['stats']),
|
|
||||||
'version': InfoVersionFromJSON(json['version']),
|
|
||||||
'uptime': json['uptime'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoToJSON(value?: Info | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'stats': InfoStatsToJSON(value.stats),
|
|
||||||
'version': InfoVersionToJSON(value.version),
|
|
||||||
'uptime': value.uptime,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 InfoStats
|
|
||||||
*/
|
|
||||||
export interface InfoStats {
|
|
||||||
/**
|
|
||||||
* Number of websites
|
|
||||||
* @type {number}
|
|
||||||
* @memberof InfoStats
|
|
||||||
*/
|
|
||||||
nWebsites: number;
|
|
||||||
/**
|
|
||||||
* Number of unique files
|
|
||||||
* @type {number}
|
|
||||||
* @memberof InfoStats
|
|
||||||
*/
|
|
||||||
nFiles: number;
|
|
||||||
/**
|
|
||||||
* Amount of used storage space (in bytes)
|
|
||||||
* @type {number}
|
|
||||||
* @memberof InfoStats
|
|
||||||
*/
|
|
||||||
storageUsed: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the InfoStats interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfInfoStats(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "nWebsites" in value;
|
|
||||||
isInstance = isInstance && "nFiles" in value;
|
|
||||||
isInstance = isInstance && "storageUsed" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoStatsFromJSON(json: any): InfoStats {
|
|
||||||
return InfoStatsFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoStatsFromJSONTyped(json: any, ignoreDiscriminator: boolean): InfoStats {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'nWebsites': json['n_websites'],
|
|
||||||
'nFiles': json['n_files'],
|
|
||||||
'storageUsed': json['storage_used'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoStatsToJSON(value?: InfoStats | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'n_websites': value.nWebsites,
|
|
||||||
'n_files': value.nFiles,
|
|
||||||
'storage_used': value.storageUsed,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 InfoVersion
|
|
||||||
*/
|
|
||||||
export interface InfoVersion {
|
|
||||||
/**
|
|
||||||
* Talon version
|
|
||||||
* @type {string}
|
|
||||||
* @memberof InfoVersion
|
|
||||||
*/
|
|
||||||
version: string;
|
|
||||||
/**
|
|
||||||
* Commit hash
|
|
||||||
* @type {string}
|
|
||||||
* @memberof InfoVersion
|
|
||||||
*/
|
|
||||||
commit: string;
|
|
||||||
/**
|
|
||||||
* Commit date
|
|
||||||
* @type {Date}
|
|
||||||
* @memberof InfoVersion
|
|
||||||
*/
|
|
||||||
commitDate: Date;
|
|
||||||
/**
|
|
||||||
* Rust version
|
|
||||||
* @type {string}
|
|
||||||
* @memberof InfoVersion
|
|
||||||
*/
|
|
||||||
rustVersion: string;
|
|
||||||
/**
|
|
||||||
* Build target (OS and architecture)
|
|
||||||
* @type {string}
|
|
||||||
* @memberof InfoVersion
|
|
||||||
*/
|
|
||||||
buildTarget: string;
|
|
||||||
/**
|
|
||||||
* Rust build mode (`debug` / `release`)
|
|
||||||
* @type {string}
|
|
||||||
* @memberof InfoVersion
|
|
||||||
*/
|
|
||||||
buildMode: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the InfoVersion interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfInfoVersion(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "version" in value;
|
|
||||||
isInstance = isInstance && "commit" in value;
|
|
||||||
isInstance = isInstance && "commitDate" in value;
|
|
||||||
isInstance = isInstance && "rustVersion" in value;
|
|
||||||
isInstance = isInstance && "buildTarget" in value;
|
|
||||||
isInstance = isInstance && "buildMode" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoVersionFromJSON(json: any): InfoVersion {
|
|
||||||
return InfoVersionFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoVersionFromJSONTyped(json: any, ignoreDiscriminator: boolean): InfoVersion {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'version': json['version'],
|
|
||||||
'commit': json['commit'],
|
|
||||||
'commitDate': (new Date(json['commit_date'])),
|
|
||||||
'rustVersion': json['rust_version'],
|
|
||||||
'buildTarget': json['build_target'],
|
|
||||||
'buildMode': json['build_mode'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function InfoVersionToJSON(value?: InfoVersion | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'version': value.version,
|
|
||||||
'commit': value.commit,
|
|
||||||
'commit_date': (value.commitDate.toISOString()),
|
|
||||||
'rust_version': value.rustVersion,
|
|
||||||
'build_target': value.buildTarget,
|
|
||||||
'build_mode': value.buildMode,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
export const SourceIcon = {
|
|
||||||
Link: 'link',
|
|
||||||
Git: 'git',
|
|
||||||
Github: 'github',
|
|
||||||
Gitlab: 'gitlab',
|
|
||||||
Gitea: 'gitea',
|
|
||||||
Bitbucket: 'bitbucket'
|
|
||||||
} as const;
|
|
||||||
export type SourceIcon = typeof SourceIcon[keyof typeof SourceIcon];
|
|
||||||
|
|
||||||
|
|
||||||
export function SourceIconFromJSON(json: any): SourceIcon {
|
|
||||||
return SourceIconFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SourceIconFromJSONTyped(json: any, ignoreDiscriminator: boolean): SourceIcon {
|
|
||||||
return json as SourceIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SourceIconToJSON(value?: SourceIcon | null): any {
|
|
||||||
return value as any;
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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';
|
|
||||||
/**
|
|
||||||
* Stats about your Talon instance
|
|
||||||
* @export
|
|
||||||
* @interface Stats
|
|
||||||
*/
|
|
||||||
export interface Stats {
|
|
||||||
/**
|
|
||||||
* Number of websites
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Stats
|
|
||||||
*/
|
|
||||||
nWebsites: number;
|
|
||||||
/**
|
|
||||||
* Number of unique files
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Stats
|
|
||||||
*/
|
|
||||||
nFiles: number;
|
|
||||||
/**
|
|
||||||
* Amount of used storage space (in bytes)
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Stats
|
|
||||||
*/
|
|
||||||
storageUsed: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the Stats interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfStats(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "nWebsites" in value;
|
|
||||||
isInstance = isInstance && "nFiles" in value;
|
|
||||||
isInstance = isInstance && "storageUsed" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StatsFromJSON(json: any): Stats {
|
|
||||||
return StatsFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StatsFromJSONTyped(json: any, ignoreDiscriminator: boolean): Stats {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'nWebsites': json['n_websites'],
|
|
||||||
'nFiles': json['n_files'],
|
|
||||||
'storageUsed': json['storage_used'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StatsToJSON(value?: Stats | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'n_websites': value.nWebsites,
|
|
||||||
'n_files': value.nFiles,
|
|
||||||
'storage_used': value.storageUsed,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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';
|
|
||||||
/**
|
|
||||||
* Website version
|
|
||||||
* @export
|
|
||||||
* @interface Version
|
|
||||||
*/
|
|
||||||
export interface Version {
|
|
||||||
/**
|
|
||||||
* Version ID
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Version
|
|
||||||
*/
|
|
||||||
id: number;
|
|
||||||
/**
|
|
||||||
* Version creation date
|
|
||||||
* @type {Date}
|
|
||||||
* @memberof Version
|
|
||||||
*/
|
|
||||||
createdAt: Date;
|
|
||||||
/**
|
|
||||||
* Associated version data
|
|
||||||
*
|
|
||||||
* This is an arbitrary string map that can hold build information and other stuff
|
|
||||||
* and will be displayed in the site info dialog.
|
|
||||||
* @type {{ [key: string]: string; }}
|
|
||||||
* @memberof Version
|
|
||||||
*/
|
|
||||||
data: { [key: string]: string; };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the Version interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfVersion(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "id" in value;
|
|
||||||
isInstance = isInstance && "createdAt" in value;
|
|
||||||
isInstance = isInstance && "data" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionFromJSON(json: any): Version {
|
|
||||||
return VersionFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionFromJSONTyped(json: any, ignoreDiscriminator: boolean): Version {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'id': json['id'],
|
|
||||||
'createdAt': (new Date(json['created_at'])),
|
|
||||||
'data': json['data'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionToJSON(value?: Version | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'id': value.id,
|
|
||||||
'created_at': (value.createdAt.toISOString()),
|
|
||||||
'data': value.data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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';
|
|
||||||
/**
|
|
||||||
* Website file
|
|
||||||
* @export
|
|
||||||
* @interface VersionFile
|
|
||||||
*/
|
|
||||||
export interface VersionFile {
|
|
||||||
/**
|
|
||||||
* File path
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionFile
|
|
||||||
*/
|
|
||||||
path: string;
|
|
||||||
/**
|
|
||||||
* File hash
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionFile
|
|
||||||
*/
|
|
||||||
hash: string;
|
|
||||||
/**
|
|
||||||
* MIME file type
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionFile
|
|
||||||
*/
|
|
||||||
mime?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the VersionFile interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfVersionFile(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "path" in value;
|
|
||||||
isInstance = isInstance && "hash" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionFileFromJSON(json: any): VersionFile {
|
|
||||||
return VersionFileFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionFileFromJSONTyped(json: any, ignoreDiscriminator: boolean): VersionFile {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'path': json['path'],
|
|
||||||
'hash': json['hash'],
|
|
||||||
'mime': !exists(json, 'mime') ? undefined : json['mime'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionFileToJSON(value?: VersionFile | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'path': value.path,
|
|
||||||
'hash': value.hash,
|
|
||||||
'mime': value.mime,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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';
|
|
||||||
/**
|
|
||||||
* Information about a Talon version
|
|
||||||
* @export
|
|
||||||
* @interface VersionInfo
|
|
||||||
*/
|
|
||||||
export interface VersionInfo {
|
|
||||||
/**
|
|
||||||
* Talon version
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionInfo
|
|
||||||
*/
|
|
||||||
version: string;
|
|
||||||
/**
|
|
||||||
* Commit hash
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionInfo
|
|
||||||
*/
|
|
||||||
commit: string;
|
|
||||||
/**
|
|
||||||
* Commit date
|
|
||||||
* @type {Date}
|
|
||||||
* @memberof VersionInfo
|
|
||||||
*/
|
|
||||||
commitDate: Date;
|
|
||||||
/**
|
|
||||||
* Rust version
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionInfo
|
|
||||||
*/
|
|
||||||
rustVersion: string;
|
|
||||||
/**
|
|
||||||
* Build target (OS and architecture)
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionInfo
|
|
||||||
*/
|
|
||||||
buildTarget: string;
|
|
||||||
/**
|
|
||||||
* Rust build mode (`debug` / `release`)
|
|
||||||
* @type {string}
|
|
||||||
* @memberof VersionInfo
|
|
||||||
*/
|
|
||||||
buildMode: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the VersionInfo interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfVersionInfo(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "version" in value;
|
|
||||||
isInstance = isInstance && "commit" in value;
|
|
||||||
isInstance = isInstance && "commitDate" in value;
|
|
||||||
isInstance = isInstance && "rustVersion" in value;
|
|
||||||
isInstance = isInstance && "buildTarget" in value;
|
|
||||||
isInstance = isInstance && "buildMode" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionInfoFromJSON(json: any): VersionInfo {
|
|
||||||
return VersionInfoFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): VersionInfo {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'version': json['version'],
|
|
||||||
'commit': json['commit'],
|
|
||||||
'commitDate': (new Date(json['commit_date'])),
|
|
||||||
'rustVersion': json['rust_version'],
|
|
||||||
'buildTarget': json['build_target'],
|
|
||||||
'buildMode': json['build_mode'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VersionInfoToJSON(value?: VersionInfo | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'version': value.version,
|
|
||||||
'commit': value.commit,
|
|
||||||
'commit_date': (value.commitDate.toISOString()),
|
|
||||||
'rust_version': value.rustVersion,
|
|
||||||
'build_target': value.buildTarget,
|
|
||||||
'build_mode': value.buildMode,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
export const Visibility = {
|
|
||||||
Featured: 'featured',
|
|
||||||
Searchable: 'searchable',
|
|
||||||
Hidden: 'hidden'
|
|
||||||
} as const;
|
|
||||||
export type Visibility = typeof Visibility[keyof typeof Visibility];
|
|
||||||
|
|
||||||
|
|
||||||
export function VisibilityFromJSON(json: any): Visibility {
|
|
||||||
return VisibilityFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VisibilityFromJSONTyped(json: any, ignoreDiscriminator: boolean): Visibility {
|
|
||||||
return json as Visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VisibilityToJSON(value?: Visibility | null): any {
|
|
||||||
return value as any;
|
|
||||||
}
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 { SourceIcon } from './SourceIcon';
|
|
||||||
import {
|
|
||||||
SourceIconFromJSON,
|
|
||||||
SourceIconFromJSONTyped,
|
|
||||||
SourceIconToJSON,
|
|
||||||
} from './SourceIcon';
|
|
||||||
import type { Visibility } from './Visibility';
|
|
||||||
import {
|
|
||||||
VisibilityFromJSON,
|
|
||||||
VisibilityFromJSONTyped,
|
|
||||||
VisibilityToJSON,
|
|
||||||
} from './Visibility';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Website
|
|
||||||
* @export
|
|
||||||
* @interface Website
|
|
||||||
*/
|
|
||||||
export interface Website {
|
|
||||||
/**
|
|
||||||
* Website subdomain
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
subdomain: string;
|
|
||||||
/**
|
|
||||||
* Website name
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
/**
|
|
||||||
* Website creation date
|
|
||||||
* @type {Date}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
createdAt: Date;
|
|
||||||
/**
|
|
||||||
* Latest version ID
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
latestVersion?: number;
|
|
||||||
/**
|
|
||||||
* Color of the page icon
|
|
||||||
*
|
|
||||||
* Format: `#7935df`
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
color?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Visibility}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
visibility: Visibility;
|
|
||||||
/**
|
|
||||||
* Link to the source of the page
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
sourceUrl?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {SourceIcon}
|
|
||||||
* @memberof Website
|
|
||||||
*/
|
|
||||||
sourceIcon?: SourceIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the Website interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfWebsite(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "subdomain" in value;
|
|
||||||
isInstance = isInstance && "name" in value;
|
|
||||||
isInstance = isInstance && "createdAt" in value;
|
|
||||||
isInstance = isInstance && "visibility" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteFromJSON(json: any): Website {
|
|
||||||
return WebsiteFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteFromJSONTyped(json: any, ignoreDiscriminator: boolean): Website {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'subdomain': json['subdomain'],
|
|
||||||
'name': json['name'],
|
|
||||||
'createdAt': (new Date(json['created_at'])),
|
|
||||||
'latestVersion': !exists(json, 'latest_version') ? undefined : json['latest_version'],
|
|
||||||
'color': !exists(json, 'color') ? undefined : json['color'],
|
|
||||||
'visibility': VisibilityFromJSON(json['visibility']),
|
|
||||||
'sourceUrl': !exists(json, 'source_url') ? undefined : json['source_url'],
|
|
||||||
'sourceIcon': !exists(json, 'source_icon') ? undefined : SourceIconFromJSON(json['source_icon']),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteToJSON(value?: Website | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'subdomain': value.subdomain,
|
|
||||||
'name': value.name,
|
|
||||||
'created_at': (value.createdAt.toISOString()),
|
|
||||||
'latest_version': value.latestVersion,
|
|
||||||
'color': value.color,
|
|
||||||
'visibility': VisibilityToJSON(value.visibility),
|
|
||||||
'source_url': value.sourceUrl,
|
|
||||||
'source_icon': SourceIconToJSON(value.sourceIcon),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 { SourceIcon } from './SourceIcon';
|
|
||||||
import {
|
|
||||||
SourceIconFromJSON,
|
|
||||||
SourceIconFromJSONTyped,
|
|
||||||
SourceIconToJSON,
|
|
||||||
} from './SourceIcon';
|
|
||||||
import type { Visibility } from './Visibility';
|
|
||||||
import {
|
|
||||||
VisibilityFromJSON,
|
|
||||||
VisibilityFromJSONTyped,
|
|
||||||
VisibilityToJSON,
|
|
||||||
} from './Visibility';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new website
|
|
||||||
* @export
|
|
||||||
* @interface WebsiteNew
|
|
||||||
*/
|
|
||||||
export interface WebsiteNew {
|
|
||||||
/**
|
|
||||||
* Website name
|
|
||||||
* @type {string}
|
|
||||||
* @memberof WebsiteNew
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
/**
|
|
||||||
* Color of the page icon
|
|
||||||
* @type {string}
|
|
||||||
* @memberof WebsiteNew
|
|
||||||
*/
|
|
||||||
color?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Visibility}
|
|
||||||
* @memberof WebsiteNew
|
|
||||||
*/
|
|
||||||
visibility?: Visibility;
|
|
||||||
/**
|
|
||||||
* Link to the source of the page
|
|
||||||
* @type {string}
|
|
||||||
* @memberof WebsiteNew
|
|
||||||
*/
|
|
||||||
sourceUrl?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {SourceIcon}
|
|
||||||
* @memberof WebsiteNew
|
|
||||||
*/
|
|
||||||
sourceIcon?: SourceIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the WebsiteNew interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfWebsiteNew(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
isInstance = isInstance && "name" in value;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteNewFromJSON(json: any): WebsiteNew {
|
|
||||||
return WebsiteNewFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteNewFromJSONTyped(json: any, ignoreDiscriminator: boolean): WebsiteNew {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'name': json['name'],
|
|
||||||
'color': !exists(json, 'color') ? undefined : json['color'],
|
|
||||||
'visibility': !exists(json, 'visibility') ? undefined : VisibilityFromJSON(json['visibility']),
|
|
||||||
'sourceUrl': !exists(json, 'source_url') ? undefined : json['source_url'],
|
|
||||||
'sourceIcon': !exists(json, 'source_icon') ? undefined : SourceIconFromJSON(json['source_icon']),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteNewToJSON(value?: WebsiteNew | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'name': value.name,
|
|
||||||
'color': value.color,
|
|
||||||
'visibility': VisibilityToJSON(value.visibility),
|
|
||||||
'source_url': value.sourceUrl,
|
|
||||||
'source_icon': SourceIconToJSON(value.sourceIcon),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 { SourceIcon } from './SourceIcon';
|
|
||||||
import {
|
|
||||||
SourceIconFromJSON,
|
|
||||||
SourceIconFromJSONTyped,
|
|
||||||
SourceIconToJSON,
|
|
||||||
} from './SourceIcon';
|
|
||||||
import type { Visibility } from './Visibility';
|
|
||||||
import {
|
|
||||||
VisibilityFromJSON,
|
|
||||||
VisibilityFromJSONTyped,
|
|
||||||
VisibilityToJSON,
|
|
||||||
} from './Visibility';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a website with the contained values
|
|
||||||
*
|
|
||||||
* Values set to `None` remain unchanged.
|
|
||||||
* @export
|
|
||||||
* @interface WebsiteUpdate
|
|
||||||
*/
|
|
||||||
export interface WebsiteUpdate {
|
|
||||||
/**
|
|
||||||
* Website name
|
|
||||||
* @type {string}
|
|
||||||
* @memberof WebsiteUpdate
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
/**
|
|
||||||
* Color of the page icon
|
|
||||||
* @type {string}
|
|
||||||
* @memberof WebsiteUpdate
|
|
||||||
*/
|
|
||||||
color?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Visibility}
|
|
||||||
* @memberof WebsiteUpdate
|
|
||||||
*/
|
|
||||||
visibility?: Visibility;
|
|
||||||
/**
|
|
||||||
* Link to the source of the page
|
|
||||||
* @type {string}
|
|
||||||
* @memberof WebsiteUpdate
|
|
||||||
*/
|
|
||||||
sourceUrl?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {SourceIcon}
|
|
||||||
* @memberof WebsiteUpdate
|
|
||||||
*/
|
|
||||||
sourceIcon?: SourceIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given object implements the WebsiteUpdate interface.
|
|
||||||
*/
|
|
||||||
export function instanceOfWebsiteUpdate(value: object): boolean {
|
|
||||||
let isInstance = true;
|
|
||||||
|
|
||||||
return isInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteUpdateFromJSON(json: any): WebsiteUpdate {
|
|
||||||
return WebsiteUpdateFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteUpdateFromJSONTyped(json: any, ignoreDiscriminator: boolean): WebsiteUpdate {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'name': !exists(json, 'name') ? undefined : json['name'],
|
|
||||||
'color': !exists(json, 'color') ? undefined : json['color'],
|
|
||||||
'visibility': !exists(json, 'visibility') ? undefined : VisibilityFromJSON(json['visibility']),
|
|
||||||
'sourceUrl': !exists(json, 'source_url') ? undefined : json['source_url'],
|
|
||||||
'sourceIcon': !exists(json, 'source_icon') ? undefined : SourceIconFromJSON(json['source_icon']),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebsiteUpdateToJSON(value?: WebsiteUpdate | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'name': value.name,
|
|
||||||
'color': value.color,
|
|
||||||
'visibility': VisibilityToJSON(value.visibility),
|
|
||||||
'source_url': value.sourceUrl,
|
|
||||||
'source_icon': SourceIconToJSON(value.sourceIcon),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
export * from './Info';
|
|
||||||
export * from './InfoStats';
|
|
||||||
export * from './InfoVersion';
|
|
||||||
export * from './SourceIcon';
|
|
||||||
export * from './Stats';
|
|
||||||
export * from './Version';
|
|
||||||
export * from './VersionFile';
|
|
||||||
export * from './VersionInfo';
|
|
||||||
export * from './Visibility';
|
|
||||||
export * from './Website';
|
|
||||||
export * from './WebsiteNew';
|
|
||||||
export * from './WebsiteUpdate';
|
|
||||||
|
|
@ -1,407 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Talon
|
|
||||||
* API for the Talon static site management system
|
|
||||||
*
|
|
||||||
* 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 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"declaration": true,
|
|
||||||
"target": "es5",
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"outDir": "dist",
|
|
||||||
"lib": [
|
|
||||||
"es6",
|
|
||||||
"dom"
|
|
||||||
],
|
|
||||||
"typeRoots": [
|
|
||||||
"node_modules/@types"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"dist",
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue