aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Program.cs208
-rw-r--r--Properties/launchSettings.json31
-rw-r--r--README.md5
-rw-r--r--aitp.sql90
-rw-r--r--appsettings.Development.json8
-rw-r--r--appsettings.json9
-rw-r--r--frontend/.gitignore22
-rw-r--r--frontend/README.md48
-rw-r--r--frontend/dist/assets/index.1ad9e6ac.css1
-rw-r--r--frontend/dist/assets/index.daae4851.js11
-rw-r--r--frontend/dist/assets/vendor.84699d7b.js1
-rw-r--r--frontend/dist/favicon.icobin0 -> 1150 bytes
-rw-r--r--frontend/dist/index.html19
-rw-r--r--frontend/index.html16
-rw-r--r--frontend/package.json22
-rw-r--r--frontend/pnpm-lock.yaml839
-rw-r--r--frontend/public/favicon.icobin0 -> 1150 bytes
-rw-r--r--frontend/src/AddBook.svelte103
-rw-r--r--frontend/src/App.svelte32
-rw-r--r--frontend/src/Books.svelte165
-rw-r--r--frontend/src/DBInput.svelte60
-rw-r--r--frontend/src/Login.svelte74
-rw-r--r--frontend/src/Search.svelte92
-rw-r--r--frontend/src/assets/svelte.pngbin0 -> 5185 bytes
-rw-r--r--frontend/src/main.ts7
-rw-r--r--frontend/src/utils.ts22
-rw-r--r--frontend/src/vite-env.d.ts2
-rw-r--r--frontend/svelte.config.js7
-rw-r--r--frontend/tsconfig.json20
-rw-r--r--frontend/tsconfig.node.json8
-rw-r--r--frontend/vite.config.ts7
-rwxr-xr-xstart1
-rw-r--r--бібліотека.csproj16
34 files changed, 1949 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a4cf37d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+bin/
+obj/
+*.log
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..13923c9
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,208 @@
+using MySqlConnector;
+using System.Security.Cryptography;
+using System.Text;
+
+var SK_DB = "db-cred";
+var SK_LOGGED = "logged-in";
+
+var builder = WebApplication.CreateBuilder(new WebApplicationOptions
+{
+ Args = args,
+ WebRootPath = "frontend/dist"
+});
+
+builder.Services.AddDistributedMemoryCache();
+
+builder.Services.AddSession(options =>
+{
+ options.Cookie.HttpOnly = true;
+ options.Cookie.IsEssential = true;
+});
+
+var app = builder.Build();
+
+var connection = new MySqlConnection();
+app.UseStaticFiles();
+app.UseRouting();
+app.UseSession();
+
+app.MapPost("/login", (LoginForm lgf, HttpResponse response, HttpContext context) =>
+{
+ var pass = hashPassword(lgf.password!);
+ connection = new MySqlConnection(context.Session.GetString(SK_DB));
+ connection.Open();
+ var command = new MySqlCommand(null, connection);
+
+ if (lgf.mode == "login")
+ {
+ command.CommandText = "SELECT * FROM user WHERE login = @login AND password = @password;";
+
+ command.Parameters.AddWithValue("@login", lgf.login);
+ command.Parameters.AddWithValue("@password", pass);
+
+ var reader = command.ExecuteReader();
+ while (reader.Read())
+ {
+ context.Session.SetString(SK_LOGGED, "true");
+ connection.Close();
+ return "ok";
+ }
+ }
+ else
+ {
+ Console.WriteLine("registering");
+
+ command.CommandText = "INSERT INTO user (email, login, password) VALUES (@email, @login, @password)";
+
+ command.Parameters.AddWithValue("@login", lgf.login);
+ command.Parameters.AddWithValue("@password", pass);
+ command.Parameters.AddWithValue("@email", lgf.email);
+
+ command.ExecuteNonQuery();
+ connection.Close();
+ return "ok";
+ }
+ connection.Close();
+ return "error";
+});
+app.MapPost("/check-db", async (DbForm dbf, HttpResponse response, HttpContext context) =>
+{
+ try
+ {
+ var connstr = $"server={dbf.server};port={dbf.port};user={dbf.user};password={dbf.password};database={dbf.database}";
+ var conn = new MySqlConnection(connstr);
+ Console.WriteLine(connstr);
+ await conn.OpenAsync();
+ connection = conn;
+ await conn.CloseAsync();
+ context.Session.SetString(SK_DB, connstr);
+ return "ok";
+ }
+ catch (Exception _)
+ {
+ return "error";
+ }
+});
+app.MapMethods("/check-db", new[] { "OPTIONS" }, (HttpResponse response) =>
+{
+ response.Headers.AccessControlAllowOrigin = "*";
+ response.Headers.AccessControlAllowHeaders = "*";
+ return "ok";
+});
+app.MapGet("/", (HttpContext context) =>
+{
+ context.Response.SendFileAsync("./frontend/dist/index.html");
+});
+app.MapPost("/book", (Book book, HttpContext context) =>
+{
+ if (!checkRequest(context)) return "error";
+ connection.Open();
+ var command = new MySqlCommand(null, connection);
+ if (book.id == null)
+ {
+ command.CommandText = "INSERT INTO book (author, title, year, publisher, isbn, format, pages, description) VALUES (@author, @title, @year, @publisher, @isbn, @format, @pages, @description)";
+ }
+ else
+ {
+ command.CommandText = "UPDATE book SET author = @author, title = @title, year = @year, publisher = @publisher, isbn = @isbn, format = @format, pages = @pages, description = @description WHERE id = @id";
+ command.Parameters.AddWithValue("@id", book.id);
+ }
+ command.Parameters.AddWithValue("@author", book.author);
+ command.Parameters.AddWithValue("@title", book.title);
+ command.Parameters.AddWithValue("@year", MySqlDbType.Int32).Value = book.year;
+ command.Parameters.AddWithValue("@publisher", book.publisher);
+ command.Parameters.AddWithValue("@isbn", book.isbn);
+ command.Parameters.AddWithValue("@format", book.format);
+ command.Parameters.AddWithValue("@pages", book.pages);
+ command.Parameters.AddWithValue("@description", book.description);
+ command.ExecuteNonQuery();
+ connection.Close();
+ return "ok";
+});
+app.MapGet("/books", (HttpContext context) =>
+{
+ if (!checkRequest(context)) return Results.Ok("error");
+
+ connection.Open();
+ var command = new MySqlCommand("SELECT * FROM book;", connection);
+ var reader = command.ExecuteReader();
+
+ List<Dictionary<string, string>> books = new List<Dictionary<string, string>>();
+
+ while (reader.Read())
+ {
+ Dictionary<string, string> book = new Dictionary<string, string>();
+
+ book.Add("id", reader.GetValue(0).ToString() ?? "");
+ book.Add("author", reader.GetValue(1).ToString() ?? "");
+ book.Add("title", reader.GetValue(2).ToString() ?? "");
+ book.Add("year", reader.GetValue(3).ToString() ?? "");
+ book.Add("publisher", reader.GetValue(4).ToString() ?? "");
+ book.Add("isbn", reader.GetValue(5).ToString() ?? "");
+ book.Add("format", reader.GetValue(6).ToString() ?? "");
+ book.Add("pages", reader.GetValue(7).ToString() ?? "");
+ book.Add("description", reader.GetValue(8).ToString() ?? "");
+
+ books.Add(book);
+ }
+
+ connection.Close();
+ return Results.Json(books);
+});
+
+// Remove book
+app.MapDelete("/book", (HttpContext context) =>
+{
+ if (!checkRequest(context)) return Results.Unauthorized();
+
+ connection.Open();
+ var command = new MySqlCommand(null, connection);
+
+ command.CommandText = "DELETE FROM book WHERE id = @id;";
+ command.Parameters.AddWithValue("@id", MySqlDbType.Int32).Value = Int32.Parse(context.Request.Query["bid"]);
+ command.ExecuteNonQuery();
+
+ connection.Close();
+ return Results.Ok("ok");
+});
+
+app.Run("http://localhost:8000");
+
+String hashPassword(string pass)
+{
+ var sha256 = SHA256.Create();
+ return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(pass!)));
+}
+
+Boolean checkRequest(HttpContext context)
+{
+ return context.Session.GetString(SK_LOGGED) == "true";
+}
+
+class DbForm
+{
+ public string? server { get; set; }
+ public int port { get; set; }
+ public string? database { get; set; }
+ public string? user { get; set; }
+ public string? password { get; set; }
+}
+class LoginForm
+{
+ public string? email { get; set; }
+ public string? login { get; set; }
+ public string? password { get; set; }
+ public string? mode { get; set; }
+}
+class Book
+{
+ public int? id { get; set; }
+ public string? author { get; set; }
+ public string? title { get; set; }
+ public int? year { get; set; }
+ public string? publisher { get; set; }
+ public string? isbn { get; set; }
+ public string? format { get; set; }
+ public int? pages { get; set; }
+ public string? description { get; set; }
+}
diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json
new file mode 100644
index 0000000..6c77bcd
--- /dev/null
+++ b/Properties/launchSettings.json
@@ -0,0 +1,31 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:31117",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "бібліотека": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5068",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fe1c823
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+### To start a project run command
+```
+ dotnet run
+```
+### in project directory
diff --git a/aitp.sql b/aitp.sql
new file mode 100644
index 0000000..6d7e2f6
--- /dev/null
+++ b/aitp.sql
@@ -0,0 +1,90 @@
+-- MariaDB dump 10.19 Distrib 10.7.3-MariaDB, for Linux (x86_64)
+--
+-- Host: localhost Database: aitp
+-- ------------------------------------------------------
+-- Server version 10.7.3-MariaDB
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `book`
+--
+
+DROP TABLE IF EXISTS `book`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `book` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `author` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `title` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `year` int(11) DEFAULT NULL,
+ `publisher` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `isbn` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `format` varchar(3) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `pages` int(11) DEFAULT NULL,
+ `description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `book`
+--
+
+LOCK TABLES `book` WRITE;
+/*!40000 ALTER TABLE `book` DISABLE KEYS */;
+INSERT INTO `book` VALUES
+(14,'Maks','o maksowaniu',2020,'MaksOwO','1234567894','A5',123,'Super ksiazka o byciu maksem'),
+(15,'Filip','O filipowaniu',2000,'Filipowo','98765416','A6',321,'Super ksiazka o byciu Filipem'),
+(16,'Maciek','O maciekowaniu',1920,'Maciekowo','321678456','A7',543,'(Edit) Super ksiazka o Maciekowniu'),
+(17,'Gal Anonim','Kronika',1000,'-','-','A2',23,'Lore dorem ');
+/*!40000 ALTER TABLE `book` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `user`
+--
+
+DROP TABLE IF EXISTS `user`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `user` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `email` varchar(254) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `login` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `password` varchar(95) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `user`
+--
+
+LOCK TABLES `user` WRITE;
+/*!40000 ALTER TABLE `user` DISABLE KEYS */;
+INSERT INTO `user` VALUES
+(6,'maks@jopek.eu','maks2','65-E8-4B-E3-35-32-FB-78-4C-48-12-96-75-F9-EF-F3-A6-82-B2-71-68-C0-EA-74-4B-2C-F5-8E-E0-23-37-C5'),
+(11,'maks@maks','maks','65-E8-4B-E3-35-32-FB-78-4C-48-12-96-75-F9-EF-F3-A6-82-B2-71-68-C0-EA-74-4B-2C-F5-8E-E0-23-37-C5');
+/*!40000 ALTER TABLE `user` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2022-03-10 15:31:58
diff --git a/appsettings.Development.json b/appsettings.Development.json
new file mode 100644
index 0000000..ff66ba6
--- /dev/null
+++ b/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/appsettings.json b/appsettings.json
new file mode 100644
index 0000000..4d56694
--- /dev/null
+++ b/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..234f2f1
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,22 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000..a9d516a
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,48 @@
+# Svelte + TS + Vite
+
+This template should help get you started developing with Svelte and TypeScript in Vite.
+
+## Recommended IDE Setup
+
+[VSCode](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
+
+## Need an official Svelte framework?
+
+Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
+
+## Technical considerations
+
+**Why use this over SvelteKit?**
+
+- It brings its own routing solution which might not be preferable for some users.
+- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
+ `vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.
+
+This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
+
+Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
+
+**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
+
+Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
+
+**Why include `.vscode/extensions.json`?**
+
+Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
+
+**Why enable `allowJs` in the TS template?**
+
+While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
+
+**Why is HMR not preserving my local component state?**
+
+HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
+
+If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
+
+```ts
+// store.ts
+// An extremely simple external store
+import { writable } from 'svelte/store'
+export default writable(0)
+```
diff --git a/frontend/dist/assets/index.1ad9e6ac.css b/frontend/dist/assets/index.1ad9e6ac.css
new file mode 100644
index 0000000..cc522de
--- /dev/null
+++ b/frontend/dist/assets/index.1ad9e6ac.css
@@ -0,0 +1 @@
+main.svelte-ifemoi{text-align:center;padding:1em;margin:0 auto;font-size:2em}input.svelte-ifemoi,button.svelte-ifemoi{font-size:1em;margin-left:10px}p.svelte-ifemoi{color:red}main.svelte-1ourgq3{text-align:center;padding:1em;margin:0 auto;font-size:2em}input.svelte-1ourgq3,button.svelte-1ourgq3{font-size:1em;margin-left:10px}input[type=checkbox].svelte-1ourgq3{width:25px;height:25px}p.svelte-1ourgq3{color:red}main.svelte-7dm5ql{position:fixed;left:0;right:0;margin:auto auto 30px;height:fit-content;width:fit-content;font-size:1.9em;color:#fff;background-color:#000000bf;padding:50px}input.svelte-7dm5ql{font-size:1em;margin-bottom:30px}main.svelte-do7epp{text-align:center}table.svelte-do7epp{margin:0 auto;border-collapse:collapse;width:90%;font-size:1.5em}thead.svelte-do7epp{font-weight:700}td.svelte-do7epp,th.svelte-do7epp{border:1px solid black}.main-btn.svelte-do7epp{margin-top:30px;margin-bottom:30px;margin-left:15px;font-size:1.9em;text-decoration:underline}.action-btn.svelte-do7epp{margin-top:10px;margin-bottom:10px;font-size:1.2em;text-decoration:underline}main.svelte-5hvcw5{text-align:center;font-size:1.9em}button.svelte-5hvcw5{margin-top:30px;margin-bottom:30px;margin-left:15px;text-decoration:underline;font-size:1em}input.svelte-5hvcw5{font-size:1em}:root{font-family:Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell}
diff --git a/frontend/dist/assets/index.daae4851.js b/frontend/dist/assets/index.daae4851.js
new file mode 100644
index 0000000..b5c9117
--- /dev/null
+++ b/frontend/dist/assets/index.daae4851.js
@@ -0,0 +1,11 @@
+import{S as he,i as _e,s as me,e as r,a as c,b as o,c as De,d as te,f as t,l as A,n as pe,g as le,r as ge,h as y,t as Z,j as $,k as Ee,m as re,o as ke,p as ve,q as be,u as oe,v as ue,w as we,x as Ie,y as Ae,z as Me,A as ae,B as ce,C as Oe}from"./vendor.84699d7b.js";const He=function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))s(a);new MutationObserver(a=>{for(const f of a)if(f.type==="childList")for(const u of f.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&s(u)}).observe(document,{childList:!0,subtree:!0});function l(a){const f={};return a.integrity&&(f.integrity=a.integrity),a.referrerpolicy&&(f.referrerPolicy=a.referrerpolicy),a.crossorigin==="use-credentials"?f.credentials="include":a.crossorigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function s(a){if(a.ep)return;a.ep=!0;const f=l(a);fetch(a.href,f)}};He();const ye="http://localhost:8000";async function Ce(n,e,l=!1){const s=await fetch(ye+n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});return l?await s.text():s.json()}async function je(n,e=!1){const l=await fetch(ye+n);return e?await l.text():l.json()}async function Fe(n,e=!1){const l=await fetch(ye+n,{method:"DELETE"});return e?await l.text():l.json()}function Ne(n){let e,l,s,a,f,u,p,i,b,d,g,_,B,k,C,D,M,E,I,h,v,q,w,m,S,L,N,R,z,P,O,j,x,F,Y,ee;return{c(){e=r("main"),l=r("label"),l.textContent="Server:",s=c(),a=r("input"),f=r("br"),u=r("br"),p=c(),i=r("label"),i.textContent="Port:",b=c(),d=r("input"),g=r("br"),_=r("br"),B=c(),k=r("label"),k.textContent="Database:",C=c(),D=r("input"),M=r("br"),E=r("br"),I=c(),h=r("label"),h.textContent="User:",v=c(),q=r("input"),w=r("br"),m=r("br"),S=c(),L=r("label"),L.textContent="Password:",N=c(),R=r("input"),z=r("br"),P=r("br"),O=c(),j=r("button"),j.textContent="Connect",x=c(),F=r("p"),o(l,"for","server"),o(a,"type","text"),o(a,"id","server"),a.value="127.0.0.1",o(a,"class","svelte-ifemoi"),o(i,"for","port"),o(d,"type","number"),o(d,"min","1"),o(d,"max","65535"),o(d,"id","port"),d.value="3306",o(d,"class","svelte-ifemoi"),o(k,"for","database"),o(D,"type","text"),o(D,"id","database"),D.value="aitp",o(D,"class","svelte-ifemoi"),o(h,"for","user"),o(q,"type","text"),o(q,"id","user"),q.value="admin",o(q,"class","svelte-ifemoi"),o(L,"for","password"),o(R,"type","password"),o(R,"id","password"),R.value="qwerty",o(R,"class","svelte-ifemoi"),o(j,"type","button"),o(j,"class","svelte-ifemoi"),o(F,"contenteditable","true"),o(F,"class","svelte-ifemoi"),n[0]===void 0&&De(()=>n[3].call(F)),o(e,"class","svelte-ifemoi")},m(K,W){te(K,e,W),t(e,l),t(e,s),t(e,a),t(e,f),t(e,u),t(e,p),t(e,i),t(e,b),t(e,d),t(e,g),t(e,_),t(e,B),t(e,k),t(e,C),t(e,D),t(e,M),t(e,E),t(e,I),t(e,h),t(e,v),t(e,q),t(e,w),t(e,m),t(e,S),t(e,L),t(e,N),t(e,R),t(e,z),t(e,P),t(e,O),t(e,j),t(e,x),t(e,F),n[0]!==void 0&&(F.innerHTML=n[0]),Y||(ee=[A(j,"click",n[1]),A(F,"input",n[3])],Y=!0)},p(K,[W]){W&1&&K[0]!==F.innerHTML&&(F.innerHTML=K[0])},i:pe,o:pe,d(K){K&&le(e),Y=!1,ge(ee)}}}function Re(n,e,l){let{whereami:s}=e,a;async function f(){const p=["server","port","database","user","password"],i={};for(const d of p)i[d]=document.getElementById(d).value;i.port=parseInt(i.port),await Ce("/check-db",i,!0)==="ok"?l(2,s="login"):l(0,a="Error, your database credentials are wrong")}function u(){a=this.innerHTML,l(0,a)}return n.$$set=p=>{"whereami"in p&&l(2,s=p.whereami)},[a,f,s,u]}class Ue extends he{constructor(e){super();_e(this,e,Re,Ne,me,{whereami:2})}}function Le(n){let e,l,s,a,f,u,p;return{c(){e=r("label"),e.textContent="Email:",l=c(),s=r("input"),a=r("br"),f=r("br"),o(e,"for","email"),o(s,"type","email"),o(s,"id","email"),o(s,"maxlength","254"),o(s,"class","svelte-1ourgq3")},m(i,b){te(i,e,b),te(i,l,b),te(i,s,b),y(s,n[2]),te(i,a,b),te(i,f,b),u||(p=A(s,"input",n[7]),u=!0)},p(i,b){b&4&&s.value!==i[2]&&y(s,i[2])},d(i){i&&le(e),i&&le(l),i&&le(s),i&&le(a),i&&le(f),u=!1,p()}}}function Ye(n){let e,l,s,a,f,u,p,i,b,d,g,_,B,k,C,D=n[1]==="login"?"Login":"Register",M,E,I,h,v,q,w,m,S,L,N,R,z,P=n[1]==="register"&&Le(n);return{c(){e=r("main"),P&&P.c(),l=c(),s=r("label"),s.textContent="Login:",a=c(),f=r("input"),u=r("br"),p=r("br"),i=c(),b=r("label"),b.textContent="Password:",d=c(),g=r("input"),_=r("br"),B=r("br"),k=c(),C=r("button"),M=Z(D),E=c(),I=r("br"),h=r("br"),v=c(),q=r("label"),q.textContent="Register:",w=c(),m=r("input"),S=c(),L=r("p"),N=Z(n[0]),o(s,"for","login"),o(f,"type","text"),o(f,"id","login"),o(f,"maxlength","256"),o(f,"class","svelte-1ourgq3"),o(b,"for","password"),o(g,"type","password"),o(g,"id","password"),o(g,"class","svelte-1ourgq3"),o(C,"type","button"),o(C,"class","svelte-1ourgq3"),o(q,"for","mode"),o(m,"type","checkbox"),o(m,"id","mode"),o(m,"class","svelte-1ourgq3"),o(L,"class","svelte-1ourgq3"),o(e,"class","svelte-1ourgq3")},m(O,j){te(O,e,j),P&&P.m(e,null),t(e,l),t(e,s),t(e,a),t(e,f),y(f,n[3]),t(e,u),t(e,p),t(e,i),t(e,b),t(e,d),t(e,g),y(g,n[4]),t(e,_),t(e,B),t(e,k),t(e,C),t(C,M),t(C,E),t(e,I),t(e,h),t(e,v),t(e,q),t(e,w),t(e,m),t(e,S),t(e,L),t(L,N),R||(z=[A(f,"input",n[8]),A(g,"input",n[9]),A(C,"click",n[5]),A(m,"click",n[10])],R=!0)},p(O,[j]){O[1]==="register"?P?P.p(O,j):(P=Le(O),P.c(),P.m(e,l)):P&&(P.d(1),P=null),j&8&&f.value!==O[3]&&y(f,O[3]),j&16&&g.value!==O[4]&&y(g,O[4]),j&2&&D!==(D=O[1]==="login"?"Login":"Register")&&$(M,D),j&1&&$(N,O[0])},i:pe,o:pe,d(O){O&&le(e),P&&P.d(),R=!1,ge(z)}}}function ze(n,e,l){let{whereami:s}=e,a="",f="login",u="asd@asd",p="maks",i="qwerty";async function b(){const k=await Ce("/login",{email:u,login:p,password:i,mode:f},!0);console.log(k),k==="ok"?l(6,s="books"):l(0,a="Wrong login or password")}function d(){u=this.value,l(2,u)}function g(){p=this.value,l(3,p)}function _(){i=this.value,l(4,i)}const B=()=>l(1,f=f==="login"?"register":"login");return n.$$set=k=>{"whereami"in k&&l(6,s=k.whereami)},[a,f,u,p,i,b,s,d,g,_,B]}class Ge extends he{constructor(e){super();_e(this,e,ze,Ye,me,{whereami:6})}}function Je(n){let e,l,s,a,f,u,p,i,b,d,g,_,B,k,C,D,M,E,I,h,v,q,w,m,S,L,N,R,z,P,O,j,x,F,Y,ee,K,W,G,J,se,X,ie,Q,V,fe,de;return{c(){e=r("main"),l=r("label"),l.textContent="Id:",s=c(),a=r("input"),f=r("br"),u=c(),p=r("label"),p.textContent="Author:",i=c(),b=r("input"),d=r("br"),g=c(),_=r("label"),_.textContent="Title:",B=c(),k=r("input"),C=r("br"),D=c(),M=r("label"),M.textContent="Year:",E=c(),I=r("input"),h=r("br"),v=c(),q=r("label"),q.textContent="Publisher:",w=c(),m=r("input"),S=r("br"),L=c(),N=r("label"),N.textContent="Isbn:",R=c(),z=r("input"),P=r("br"),O=c(),j=r("label"),j.textContent="Format:",x=c(),F=r("input"),Y=r("br"),ee=c(),K=r("label"),K.textContent="Pages:",W=c(),G=r("input"),J=r("br"),se=c(),X=r("label"),X.textContent="Description:",ie=c(),Q=r("input"),V=r("br"),o(l,"for","id"),o(a,"type","number"),o(a,"id","id"),o(a,"class","svelte-7dm5ql"),o(p,"for","author"),o(b,"type","text"),o(b,"id","author"),o(b,"class","svelte-7dm5ql"),o(_,"for","title"),o(k,"type","text"),o(k,"id","title"),o(k,"class","svelte-7dm5ql"),o(M,"for","year"),o(I,"type","number"),o(I,"id","year"),o(I,"class","svelte-7dm5ql"),o(q,"for","publisher"),o(m,"type","number"),o(m,"id","publisher"),o(m,"class","svelte-7dm5ql"),o(N,"for","isbn"),o(z,"id","isbn"),o(z,"class","svelte-7dm5ql"),o(j,"for","format"),o(F,"id","format"),o(F,"class","svelte-7dm5ql"),o(K,"for","pages"),o(G,"id","pages"),o(G,"class","svelte-7dm5ql"),o(X,"for","description"),o(Q,"id","description"),Ee(Q,"margin-bottom","0"),o(Q,"class","svelte-7dm5ql"),o(e,"class","svelte-7dm5ql")},m(T,H){te(T,e,H),t(e,l),t(e,s),t(e,a),y(a,n[0]),t(e,f),t(e,u),t(e,p),t(e,i),t(e,b),y(b,n[1]),t(e,d),t(e,g),t(e,_),t(e,B),t(e,k),y(k,n[2]),t(e,C),t(e,D),t(e,M),t(e,E),t(e,I),y(I,n[3]),t(e,h),t(e,v),t(e,q),t(e,w),t(e,m),y(m,n[8]),t(e,S),t(e,L),t(e,N),t(e,R),t(e,z),y(z,n[4]),t(e,P),t(e,O),t(e,j),t(e,x),t(e,F),y(F,n[5]),t(e,Y),t(e,ee),t(e,K),t(e,W),t(e,G),y(G,n[6]),t(e,J),t(e,se),t(e,X),t(e,ie),t(e,Q),y(Q,n[7]),t(e,V),fe||(de=[A(a,"input",n[11]),A(b,"input",n[12]),A(k,"input",n[13]),A(I,"input",n[14]),A(m,"input",n[15]),A(z,"input",n[16]),A(F,"input",n[17]),A(G,"input",n[18]),A(Q,"input",n[19])],fe=!0)},p(T,[H]){H&1&&re(a.value)!==T[0]&&y(a,T[0]),H&2&&b.value!==T[1]&&y(b,T[1]),H&4&&k.value!==T[2]&&y(k,T[2]),H&8&&re(I.value)!==T[3]&&y(I,T[3]),H&256&&re(m.value)!==T[8]&&y(m,T[8]),H&16&&z.value!==T[4]&&y(z,T[4]),H&32&&F.value!==T[5]&&y(F,T[5]),H&64&&G.value!==T[6]&&y(G,T[6]),H&128&&Q.value!==T[7]&&y(Q,T[7])},i:pe,o:pe,d(T){T&&le(e),fe=!1,ge(de)}}}function Ke(n,e,l){let{filters:s}=e,a,f,u,p,i,b,d,g,_;function B(){l(0,a=null),l(1,f=null),l(2,u=null),l(3,p=null),l(4,i=null),l(5,b=null),l(6,d=null),l(7,g=null),l(8,_=null)}function k(){a=re(this.value),l(0,a)}function C(){f=this.value,l(1,f)}function D(){u=this.value,l(2,u)}function M(){p=re(this.value),l(3,p)}function E(){_=re(this.value),l(8,_)}function I(){i=this.value,l(4,i)}function h(){b=this.value,l(5,b)}function v(){d=this.value,l(6,d)}function q(){g=this.value,l(7,g)}return n.$$set=w=>{"filters"in w&&l(9,s=w.filters)},n.$$.update=()=>{n.$$.dirty&1023&&(a?l(9,s.id=a,s):delete s.id,f?l(9,s.author=f,s):delete s.author,u?l(9,s.title=u,s):delete s.title,p?l(9,s.year=p,s):delete s.year,_?l(9,s.publisher=_,s):delete s.publisher,i?l(9,s.isbn=i,s):delete s.isbn,b?l(9,s.format=b,s):delete s.format,d?l(9,s.pages=d,s):delete s.pages,g?l(9,s.description=g,s):delete s.description,l(9,s.key=Math.random(),s))},[a,f,u,p,i,b,d,g,_,s,B,k,C,D,M,E,I,h,v,q]}class We extends he{constructor(e){super();_e(this,e,Ke,Je,me,{filters:9,clear:10})}get clear(){return this.$$.ctx[10]}}function Se(n,e,l){const s=n.slice();return s[17]=e[l],s}function Pe(n){let e,l,s;function a(u){n[13](u)}let f={};return n[0]!==void 0&&(f.filters=n[0]),e=new We({props:f}),ae.push(()=>ce(e,"filters",a)),n[14](e),{c(){ke(e.$$.fragment)},m(u,p){ve(e,u,p),s=!0},p(u,p){const i={};!l&&p&1&&(l=!0,i.filters=u[0],be(()=>l=!1)),e.$set(i)},i(u){s||(oe(e.$$.fragment,u),s=!0)},o(u){ue(e.$$.fragment,u),s=!1},d(u){n[14](null),we(e,u)}}}function Te(n){let e,l,s=n[17].id+"",a,f,u,p=n[17].author+"",i,b,d,g=n[17].title+"",_,B,k,C=n[17].year+"",D,M,E,I=n[17].publisher+"",h,v,q,w=n[17].isbn+"",m,S,L,N=n[17].format+"",R,z,P,O=n[17].pages+"",j,x,F,Y=n[17].description+"",ee,K,W,G,J,se,X,ie,Q,V;function fe(){return n[15](n[17])}function de(){return n[16](n[17])}return{c(){e=r("tr"),l=r("td"),a=Z(s),f=c(),u=r("td"),i=Z(p),b=c(),d=r("td"),_=Z(g),B=c(),k=r("td"),D=Z(C),M=c(),E=r("td"),h=Z(I),v=c(),q=r("td"),m=Z(w),S=c(),L=r("td"),R=Z(N),z=c(),P=r("td"),j=Z(O),x=c(),F=r("td"),ee=Z(Y),K=c(),W=r("td"),G=r("button"),G.textContent="Edit",J=c(),se=r("td"),X=r("button"),X.textContent="Remove",ie=c(),o(l,"class","svelte-do7epp"),o(u,"class","svelte-do7epp"),o(d,"class","svelte-do7epp"),o(k,"class","svelte-do7epp"),o(E,"class","svelte-do7epp"),o(q,"class","svelte-do7epp"),o(L,"class","svelte-do7epp"),o(P,"class","svelte-do7epp"),o(F,"class","svelte-do7epp"),o(G,"type","button"),o(G,"class","action-btn svelte-do7epp"),o(W,"class","svelte-do7epp"),o(X,"type","button"),o(X,"class","action-btn svelte-do7epp"),o(se,"class","svelte-do7epp")},m(T,H){te(T,e,H),t(e,l),t(l,a),t(e,f),t(e,u),t(u,i),t(e,b),t(e,d),t(d,_),t(e,B),t(e,k),t(k,D),t(e,M),t(e,E),t(E,h),t(e,v),t(e,q),t(q,m),t(e,S),t(e,L),t(L,R),t(e,z),t(e,P),t(P,j),t(e,x),t(e,F),t(F,ee),t(e,K),t(e,W),t(W,G),t(e,J),t(e,se),t(se,X),t(e,ie),Q||(V=[A(G,"click",fe),A(X,"click",de)],Q=!0)},p(T,H){n=T,H&4&&s!==(s=n[17].id+"")&&$(a,s),H&4&&p!==(p=n[17].author+"")&&$(i,p),H&4&&g!==(g=n[17].title+"")&&$(_,g),H&4&&C!==(C=n[17].year+"")&&$(D,C),H&4&&I!==(I=n[17].publisher+"")&&$(h,I),H&4&&w!==(w=n[17].isbn+"")&&$(m,w),H&4&&N!==(N=n[17].format+"")&&$(R,N),H&4&&O!==(O=n[17].pages+"")&&$(j,O),H&4&&Y!==(Y=n[17].description+"")&&$(ee,Y)},d(T){T&&le(e),Q=!1,ge(V)}}}function Qe(n){let e,l,s,a,f=n[3]?"Hide":"Show",u,p,i,b,d,g,_,B,k,C,D,M,E,I,h,v=n[3]&&Pe(n),q=n[2],w=[];for(let m=0;m<q.length;m+=1)w[m]=Te(Se(n,q,m));return{c(){e=r("main"),l=r("button"),l.textContent="Add",s=c(),a=r("button"),u=Z(f),p=Z(" search dialog"),i=c(),b=r("button"),b.textContent="Clear filters",d=c(),g=r("button"),g.textContent="Reload data",_=c(),v&&v.c(),B=c(),k=r("table"),C=r("thead"),C.innerHTML=`<tr><th class="svelte-do7epp">Id</th>
+ <th class="svelte-do7epp">Author</th>
+ <th class="svelte-do7epp">Title</th>
+ <th class="svelte-do7epp">Year of<br/>publication</th>
+ <th class="svelte-do7epp">Publisher</th>
+ <th class="svelte-do7epp">Isbn</th>
+ <th class="svelte-do7epp">Format</th>
+ <th class="svelte-do7epp">Pages</th>
+ <th class="svelte-do7epp">Description</th>
+ <th class="svelte-do7epp"></th>
+ <th class="svelte-do7epp"></th></tr>`,D=c(),M=r("tbody");for(let m=0;m<w.length;m+=1)w[m].c();o(l,"type","button"),o(l,"class","main-btn svelte-do7epp"),o(a,"type","button"),o(a,"class","main-btn svelte-do7epp"),o(b,"type","button"),o(b,"class","main-btn svelte-do7epp"),o(g,"type","button"),o(g,"class","main-btn svelte-do7epp"),o(C,"class","svelte-do7epp"),o(k,"class","svelte-do7epp"),o(e,"class","svelte-do7epp")},m(m,S){te(m,e,S),t(e,l),t(e,s),t(e,a),t(a,u),t(a,p),t(e,i),t(e,b),t(e,d),t(e,g),t(e,_),v&&v.m(e,null),t(e,B),t(e,k),t(k,C),t(k,D),t(k,M);for(let L=0;L<w.length;L+=1)w[L].m(M,null);E=!0,I||(h=[A(l,"click",n[5]),A(a,"click",n[6]),A(b,"click",n[9]),A(g,"click",n[4])],I=!0)},p(m,[S]){if((!E||S&8)&&f!==(f=m[3]?"Hide":"Show")&&$(u,f),m[3]?v?(v.p(m,S),S&8&&oe(v,1)):(v=Pe(m),v.c(),oe(v,1),v.m(e,B)):v&&(Ie(),ue(v,1,1,()=>{v=null}),Ae()),S&388){q=m[2];let L;for(L=0;L<q.length;L+=1){const N=Se(m,q,L);w[L]?w[L].p(N,S):(w[L]=Te(N),w[L].c(),w[L].m(M,null))}for(;L<w.length;L+=1)w[L].d(1);w.length=q.length}},i(m){E||(oe(v),E=!0)},o(m){ue(v),E=!1},d(m){m&&le(e),v&&v.d(),Me(w,m),I=!1,ge(h)}}}function Ve(n,e,l){let{whereami:s}=e,{ebook:a}=e,f,u={key:2},p=[],i=[];async function b(){l(12,i=await je("/books")),l(2,p=i)}b();let d=!1;function g(){l(10,s="add-book")}function _(){l(3,d=!d)}function B(h){l(10,s="edit-book"),l(11,a=h)}async function k(h){await Fe("/book?bid="+h,!0),l(12,i=i.filter(v=>v.id!==h))}function C(){f.clear(),l(0,u={key:Math.random()})}function D(h){u=h,l(0,u)}function M(h){ae[h?"unshift":"push"](()=>{f=h,l(1,f)})}const E=h=>B(h),I=h=>k(h.id);return n.$$set=h=>{"whereami"in h&&l(10,s=h.whereami),"ebook"in h&&l(11,a=h.ebook)},n.$$.update=()=>{if(n.$$.dirty&4097){async function h(){Object.keys(u).length===1?l(2,p=i):l(2,p=i.filter(v=>{for(const q in u){const w=u[q];if(!(!w||q==="key")&&v[q].toString().toLowerCase().includes(w.toString().toLowerCase()))return!0}return!1}))}h()}},[u,f,p,d,b,g,_,B,k,C,s,a,i,D,M,E,I]}class Xe extends he{constructor(e){super();_e(this,e,Ve,Qe,me,{whereami:10,ebook:11})}}function Ze(n){let e,l,s=n[1][0].toUpperCase()+n[1].substring(1)+"",a,f,u,p,i,b,d,g,_,B,k,C,D,M,E,I,h,v,q,w,m,S,L,N,R,z,P,O,j,x,F,Y,ee,K,W,G,J,se,X,ie,Q,V,fe,de,T,H,qe;return{c(){e=r("main"),l=r("button"),a=Z(s),f=c(),u=r("br"),p=c(),i=r("label"),i.textContent="Author:",b=c(),d=r("input"),g=r("br"),_=c(),B=r("label"),B.textContent="Title:",k=c(),C=r("input"),D=r("br"),M=c(),E=r("label"),E.textContent="Year:",I=c(),h=r("input"),v=r("br"),q=c(),w=r("label"),w.textContent="Publisher:",m=c(),S=r("input"),L=r("br"),N=c(),R=r("label"),R.textContent="Isbn:",z=c(),P=r("input"),O=r("br"),j=c(),x=r("label"),x.textContent="Format:",F=c(),Y=r("input"),ee=r("br"),K=c(),W=r("label"),W.textContent="Pages:",G=c(),J=r("input"),se=r("br"),X=c(),ie=r("label"),ie.textContent="Description:",Q=c(),V=r("input"),fe=r("br"),de=c(),T=r("button"),T.textContent="Go back",o(l,"type","button"),o(l,"class","svelte-5hvcw5"),o(i,"for","author"),o(d,"id","author"),o(d,"maxlength","100"),o(d,"class","svelte-5hvcw5"),o(B,"for","title"),o(C,"id","title"),o(C,"maxlength","100"),o(C,"class","svelte-5hvcw5"),o(E,"for","year"),o(h,"id","year"),o(h,"type","number"),o(h,"min","0000"),o(h,"step","1"),o(h,"max","2000000"),o(h,"class","svelte-5hvcw5"),o(w,"for","publisher"),o(S,"id","publisher"),o(S,"maxlength","100"),o(S,"class","svelte-5hvcw5"),o(R,"for","isbn"),o(P,"id","isbn"),o(P,"maxlength","13"),o(P,"class","svelte-5hvcw5"),o(x,"for","format"),o(Y,"id","format"),o(Y,"maxlength","3"),o(Y,"class","svelte-5hvcw5"),o(W,"for","pages"),o(J,"id","pages"),o(J,"type","number"),o(J,"min","0"),o(J,"step","1"),o(J,"max","2000000"),o(J,"class","svelte-5hvcw5"),o(ie,"for","description"),o(V,"id","description"),o(V,"maxlength","255"),o(V,"class","svelte-5hvcw5"),o(T,"type","button"),o(T,"class","svelte-5hvcw5"),o(e,"class","svelte-5hvcw5")},m(U,ne){te(U,e,ne),t(e,l),t(l,a),t(l,f),t(e,u),t(e,p),t(e,i),t(e,b),t(e,d),y(d,n[2]),t(e,g),t(e,_),t(e,B),t(e,k),t(e,C),y(C,n[3]),t(e,D),t(e,M),t(e,E),t(e,I),t(e,h),y(h,n[8]),t(e,v),t(e,q),t(e,w),t(e,m),t(e,S),y(S,n[9]),t(e,L),t(e,N),t(e,R),t(e,z),t(e,P),y(P,n[4]),t(e,O),t(e,j),t(e,x),t(e,F),t(e,Y),y(Y,n[5]),t(e,ee),t(e,K),t(e,W),t(e,G),t(e,J),y(J,n[6]),t(e,se),t(e,X),t(e,ie),t(e,Q),t(e,V),y(V,n[7]),t(e,fe),t(e,de),t(e,T),H||(qe=[A(l,"click",n[10]),A(d,"input",n[12]),A(C,"input",n[13]),A(h,"input",n[14]),A(S,"input",n[15]),A(P,"input",n[16]),A(Y,"input",n[17]),A(J,"input",n[18]),A(V,"input",n[19]),A(T,"click",n[20])],H=!0)},p(U,[ne]){ne&2&&s!==(s=U[1][0].toUpperCase()+U[1].substring(1)+"")&&$(a,s),ne&4&&d.value!==U[2]&&y(d,U[2]),ne&8&&C.value!==U[3]&&y(C,U[3]),ne&256&&re(h.value)!==U[8]&&y(h,U[8]),ne&512&&S.value!==U[9]&&y(S,U[9]),ne&16&&P.value!==U[4]&&y(P,U[4]),ne&32&&Y.value!==U[5]&&y(Y,U[5]),ne&64&&re(J.value)!==U[6]&&y(J,U[6]),ne&128&&V.value!==U[7]&&y(V,U[7])},i:pe,o:pe,d(U){U&&le(e),H=!1,ge(qe)}}}function xe(n,e,l){let{whereami:s}=e,{mode:a}=e,{ebook:f}=e,u=f?f.author:"",p=f?f.title:"",i=f?f.isbn:"",b=f?f.format:"",d=f?f.pages:"",g=f?f.description:"",_=f?f.year:null,B=f?f.id:null,k=f?f.publisher:"";async function C(){await Ce("/book",{author:u,title:p,year:_,publisher:k,id:B,isbn:i,format:b,pages:d,description:g},!0),l(2,u=""),l(3,p=""),l(8,_=null),l(9,k=""),B=null,l(4,i=""),l(5,b=""),l(6,d=""),l(7,g=""),a==="edit"&&l(0,s="books")}function D(){u=this.value,l(2,u)}function M(){p=this.value,l(3,p)}function E(){_=re(this.value),l(8,_)}function I(){k=this.value,l(9,k)}function h(){i=this.value,l(4,i)}function v(){b=this.value,l(5,b)}function q(){d=re(this.value),l(6,d)}function w(){g=this.value,l(7,g)}const m=()=>l(0,s="books");return n.$$set=S=>{"whereami"in S&&l(0,s=S.whereami),"mode"in S&&l(1,a=S.mode),"ebook"in S&&l(11,f=S.ebook)},[s,a,u,p,i,b,d,g,_,k,C,f,D,M,E,I,h,v,q,w,m]}class Be extends he{constructor(e){super();_e(this,e,xe,Ze,me,{whereami:0,mode:1,ebook:11})}}function $e(n){let e,l,s,a;function f(i){n[7](i)}function u(i){n[8](i)}let p={mode:"edit"};return n[0]!==void 0&&(p.whereami=n[0]),n[1]!==void 0&&(p.ebook=n[1]),e=new Be({props:p}),ae.push(()=>ce(e,"whereami",f)),ae.push(()=>ce(e,"ebook",u)),{c(){ke(e.$$.fragment)},m(i,b){ve(e,i,b),a=!0},p(i,b){const d={};!l&&b&1&&(l=!0,d.whereami=i[0],be(()=>l=!1)),!s&&b&2&&(s=!0,d.ebook=i[1],be(()=>s=!1)),e.$set(d)},i(i){a||(oe(e.$$.fragment,i),a=!0)},o(i){ue(e.$$.fragment,i),a=!1},d(i){we(e,i)}}}function et(n){let e,l,s;function a(u){n[6](u)}let f={mode:"add",ebook:null};return n[0]!==void 0&&(f.whereami=n[0]),e=new Be({props:f}),ae.push(()=>ce(e,"whereami",a)),{c(){ke(e.$$.fragment)},m(u,p){ve(e,u,p),s=!0},p(u,p){const i={};!l&&p&1&&(l=!0,i.whereami=u[0],be(()=>l=!1)),e.$set(i)},i(u){s||(oe(e.$$.fragment,u),s=!0)},o(u){ue(e.$$.fragment,u),s=!1},d(u){we(e,u)}}}function tt(n){let e,l,s,a;function f(i){n[4](i)}function u(i){n[5](i)}let p={};return n[0]!==void 0&&(p.whereami=n[0]),n[1]!==void 0&&(p.ebook=n[1]),e=new Xe({props:p}),ae.push(()=>ce(e,"whereami",f)),ae.push(()=>ce(e,"ebook",u)),{c(){ke(e.$$.fragment)},m(i,b){ve(e,i,b),a=!0},p(i,b){const d={};!l&&b&1&&(l=!0,d.whereami=i[0],be(()=>l=!1)),!s&&b&2&&(s=!0,d.ebook=i[1],be(()=>s=!1)),e.$set(d)},i(i){a||(oe(e.$$.fragment,i),a=!0)},o(i){ue(e.$$.fragment,i),a=!1},d(i){we(e,i)}}}function lt(n){let e,l,s;function a(u){n[3](u)}let f={};return n[0]!==void 0&&(f.whereami=n[0]),e=new Ge({props:f}),ae.push(()=>ce(e,"whereami",a)),{c(){ke(e.$$.fragment)},m(u,p){ve(e,u,p),s=!0},p(u,p){const i={};!l&&p&1&&(l=!0,i.whereami=u[0],be(()=>l=!1)),e.$set(i)},i(u){s||(oe(e.$$.fragment,u),s=!0)},o(u){ue(e.$$.fragment,u),s=!1},d(u){we(e,u)}}}function nt(n){let e,l,s;function a(u){n[2](u)}let f={};return n[0]!==void 0&&(f.whereami=n[0]),e=new Ue({props:f}),ae.push(()=>ce(e,"whereami",a)),{c(){ke(e.$$.fragment)},m(u,p){ve(e,u,p),s=!0},p(u,p){const i={};!l&&p&1&&(l=!0,i.whereami=u[0],be(()=>l=!1)),e.$set(i)},i(u){s||(oe(e.$$.fragment,u),s=!0)},o(u){ue(e.$$.fragment,u),s=!1},d(u){we(e,u)}}}function ot(n){let e,l,s,a;const f=[nt,lt,tt,et,$e],u=[];function p(i,b){return i[0]==="check-db"?0:i[0]==="login"?1:i[0]==="books"?2:i[0]==="add-book"?3:i[0]==="edit-book"?4:-1}return~(e=p(n))&&(l=u[e]=f[e](n)),{c(){l&&l.c(),s=Oe()},m(i,b){~e&&u[e].m(i,b),te(i,s,b),a=!0},p(i,[b]){let d=e;e=p(i),e===d?~e&&u[e].p(i,b):(l&&(Ie(),ue(u[d],1,1,()=>{u[d]=null}),Ae()),~e?(l=u[e],l?l.p(i,b):(l=u[e]=f[e](i),l.c()),oe(l,1),l.m(s.parentNode,s)):l=null)},i(i){a||(oe(l),a=!0)},o(i){ue(l),a=!1},d(i){~e&&u[e].d(i),i&&le(s)}}}function st(n,e,l){let s="check-db",a={};function f(_){s=_,l(0,s)}function u(_){s=_,l(0,s)}function p(_){s=_,l(0,s)}function i(_){a=_,l(1,a)}function b(_){s=_,l(0,s)}function d(_){s=_,l(0,s)}function g(_){a=_,l(1,a)}return n.$$.update=()=>{n.$$.dirty&1&&console.log(s)},[s,a,f,u,p,i,b,d,g]}class it extends he{constructor(e){super();_e(this,e,st,ot,me,{})}}new it({target:document.getElementById("app")});
diff --git a/frontend/dist/assets/vendor.84699d7b.js b/frontend/dist/assets/vendor.84699d7b.js
new file mode 100644
index 0000000..f6c0c92
--- /dev/null
+++ b/frontend/dist/assets/vendor.84699d7b.js
@@ -0,0 +1 @@
+function S(){}function N(t){return t()}function A(){return Object.create(null)}function d(t){t.forEach(N)}function B(t){return typeof t=="function"}function J(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function L(t){return Object.keys(t).length===0}function K(t,e){t.appendChild(e)}function Q(t,e,n){t.insertBefore(e,n||null)}function T(t){t.parentNode.removeChild(t)}function R(t,e){for(let n=0;n<t.length;n+=1)t[n]&&t[n].d(e)}function U(t){return document.createElement(t)}function O(t){return document.createTextNode(t)}function V(){return O(" ")}function W(){return O("")}function X(t,e,n,r){return t.addEventListener(e,n,r),()=>t.removeEventListener(e,n,r)}function Y(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Z(t){return t===""?null:+t}function q(t){return Array.from(t.childNodes)}function tt(t,e){e=""+e,t.wholeText!==e&&(t.data=e)}function et(t,e){t.value=e==null?"":e}function nt(t,e,n,r){n===null?t.style.removeProperty(e):t.style.setProperty(e,n,r?"important":"")}let w;function l(t){w=t}const a=[],C=[],h=[],y=[],z=Promise.resolve();let x=!1;function M(){x||(x=!0,z.then(P))}function b(t){h.push(t)}function rt(t){y.push(t)}const $=new Set;let _=0;function P(){const t=w;do{for(;_<a.length;){const e=a[_];_++,l(e),D(e.$$)}for(l(null),a.length=0,_=0;C.length;)C.pop()();for(let e=0;e<h.length;e+=1){const n=h[e];$.has(n)||($.add(n),n())}h.length=0}while(a.length);for(;y.length;)y.pop()();x=!1,$.clear(),l(t)}function D(t){if(t.fragment!==null){t.update(),d(t.before_update);const e=t.dirty;t.dirty=[-1],t.fragment&&t.fragment.p(t.ctx,e),t.after_update.forEach(b)}}const p=new Set;let c;function st(){c={r:0,c:[],p:c}}function ot(){c.r||d(c.c),c=c.p}function F(t,e){t&&t.i&&(p.delete(t),t.i(e))}function ut(t,e,n,r){if(t&&t.o){if(p.has(t))return;p.add(t),c.c.push(()=>{p.delete(t),r&&(n&&t.d(1),r())}),t.o(e)}}function ft(t,e,n){const r=t.$$.props[e];r!==void 0&&(t.$$.bound[r]=n,n(t.$$.ctx[r]))}function ct(t){t&&t.c()}function G(t,e,n,r){const{fragment:o,on_mount:m,on_destroy:i,after_update:g}=t.$$;o&&o.m(e,n),r||b(()=>{const f=m.map(N).filter(B);i?i.push(...f):d(f),t.$$.on_mount=[]}),g.forEach(b)}function H(t,e){const n=t.$$;n.fragment!==null&&(d(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function I(t,e){t.$$.dirty[0]===-1&&(a.push(t),M(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<<e%31}function it(t,e,n,r,o,m,i,g=[-1]){const f=w;l(t);const s=t.$$={fragment:null,ctx:null,props:m,update:S,not_equal:o,bound:A(),on_mount:[],on_destroy:[],on_disconnect:[],before_update:[],after_update:[],context:new Map(e.context||(f?f.$$.context:[])),callbacks:A(),dirty:g,skip_bound:!1,root:e.target||f.$$.root};i&&i(s.root);let v=!1;if(s.ctx=n?n(t,e.props||{},(u,E,...k)=>{const j=k.length?k[0]:E;return s.ctx&&o(s.ctx[u],s.ctx[u]=j)&&(!s.skip_bound&&s.bound[u]&&s.bound[u](j),v&&I(t,u)),E}):[],s.update(),v=!0,d(s.before_update),s.fragment=r?r(s.ctx):!1,e.target){if(e.hydrate){const u=q(e.target);s.fragment&&s.fragment.l(u),u.forEach(T)}else s.fragment&&s.fragment.c();e.intro&&F(t.$$.fragment),G(t,e.target,e.anchor,e.customElement),P()}l(f)}class at{$destroy(){H(this,1),this.$destroy=S}$on(e,n){const r=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return r.push(n),()=>{const o=r.indexOf(n);o!==-1&&r.splice(o,1)}}$set(e){this.$$set&&!L(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}export{C as A,ft as B,W as C,at as S,V as a,Y as b,b as c,Q as d,U as e,K as f,T as g,et as h,it as i,tt as j,nt as k,X as l,Z as m,S as n,ct as o,G as p,rt as q,d as r,J as s,O as t,F as u,ut as v,H as w,st as x,ot as y,R as z};
diff --git a/frontend/dist/favicon.ico b/frontend/dist/favicon.ico
new file mode 100644
index 0000000..d75d248
--- /dev/null
+++ b/frontend/dist/favicon.ico
Binary files differ
diff --git a/frontend/dist/index.html b/frontend/dist/index.html
new file mode 100644
index 0000000..2a88f93
--- /dev/null
+++ b/frontend/dist/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8" />
+ <link rel="icon" href="/favicon.ico" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>бібліотека</title>
+ <script type="module" crossorigin src="/assets/index.daae4851.js"></script>
+ <link rel="modulepreload" href="/assets/vendor.84699d7b.js">
+ <link rel="stylesheet" href="/assets/index.1ad9e6ac.css">
+</head>
+
+<body>
+ <div id="app"></div>
+
+</body>
+
+</html>
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..4e618dc
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8" />
+ <link rel="icon" href="/favicon.ico" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>бібліотека</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="module" src="/src/main.ts"></script>
+</body>
+
+</html>
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..f360acb
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "-",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-check --tsconfig ./tsconfig.json"
+ },
+ "devDependencies": {
+ "@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
+ "@tsconfig/svelte": "^2.0.1",
+ "svelte": "^3.44.0",
+ "svelte-check": "^2.2.7",
+ "svelte-preprocess": "^4.9.8",
+ "tslib": "^2.3.1",
+ "typescript": "^4.5.4",
+ "vite": "^2.8.0"
+ }
+} \ No newline at end of file
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
new file mode 100644
index 0000000..592805b
--- /dev/null
+++ b/frontend/pnpm-lock.yaml
@@ -0,0 +1,839 @@
+lockfileVersion: 5.3
+
+specifiers:
+ '@sveltejs/vite-plugin-svelte': ^1.0.0-next.30
+ '@tsconfig/svelte': ^2.0.1
+ svelte: ^3.44.0
+ svelte-check: ^2.2.7
+ svelte-preprocess: ^4.9.8
+ tslib: ^2.3.1
+ typescript: ^4.5.4
+ vite: ^2.8.0
+
+devDependencies:
+ '@sveltejs/vite-plugin-svelte': 1.0.0-next.37_svelte@3.46.4+vite@2.8.4
+ '@tsconfig/svelte': 2.0.1
+ svelte: 3.46.4
+ svelte-check: 2.4.5_svelte@3.46.4
+ svelte-preprocess: 4.10.4_svelte@3.46.4+typescript@4.5.5
+ tslib: 2.3.1
+ typescript: 4.5.5
+ vite: 2.8.4
+
+packages:
+
+ /@nodelib/fs.scandir/2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat/2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk/1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.13.0
+ dev: true
+
+ /@rollup/pluginutils/4.1.2:
+ resolution: {integrity: sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==}
+ engines: {node: '>= 8.0.0'}
+ dependencies:
+ estree-walker: 2.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /@sveltejs/vite-plugin-svelte/1.0.0-next.37_svelte@3.46.4+vite@2.8.4:
+ resolution: {integrity: sha512-EdSXw2rXeOahNrQfMJVZxa/NxZxW1a0TiBI3s+pVxnxU14hEQtnkLtdbTFhnceu22gJpNPFSIJRcIwRBBDQIeA==}
+ engines: {node: ^14.13.1 || >= 16}
+ peerDependencies:
+ diff-match-patch: ^1.0.5
+ svelte: ^3.44.0
+ vite: ^2.7.0
+ peerDependenciesMeta:
+ diff-match-patch:
+ optional: true
+ dependencies:
+ '@rollup/pluginutils': 4.1.2
+ debug: 4.3.3
+ kleur: 4.1.4
+ magic-string: 0.25.7
+ svelte: 3.46.4
+ svelte-hmr: 0.14.9_svelte@3.46.4
+ vite: 2.8.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@tsconfig/svelte/2.0.1:
+ resolution: {integrity: sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==}
+ dev: true
+
+ /@types/node/17.0.21:
+ resolution: {integrity: sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==}
+ dev: true
+
+ /@types/pug/2.0.6:
+ resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==}
+ dev: true
+
+ /@types/sass/1.43.1:
+ resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==}
+ dependencies:
+ '@types/node': 17.0.21
+ dev: true
+
+ /anymatch/3.1.2:
+ resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /balanced-match/1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /binary-extensions/2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /brace-expansion/1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /braces/3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /buffer-crc32/0.2.13:
+ resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=}
+ dev: true
+
+ /callsites/3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /chokidar/3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.2
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /concat-map/0.0.1:
+ resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
+ dev: true
+
+ /debug/4.3.3:
+ resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /detect-indent/6.1.0:
+ resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /es6-promise/3.3.1:
+ resolution: {integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=}
+ dev: true
+
+ /esbuild-android-arm64/0.14.23:
+ resolution: {integrity: sha512-k9sXem++mINrZty1v4FVt6nC5BQCFG4K2geCIUUqHNlTdFnuvcqsY7prcKZLFhqVC1rbcJAr9VSUGFL/vD4vsw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-darwin-64/0.14.23:
+ resolution: {integrity: sha512-lB0XRbtOYYL1tLcYw8BoBaYsFYiR48RPrA0KfA/7RFTr4MV7Bwy/J4+7nLsVnv9FGuQummM3uJ93J3ptaTqFug==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-darwin-arm64/0.14.23:
+ resolution: {integrity: sha512-yat73Z/uJ5tRcfRiI4CCTv0FSnwErm3BJQeZAh+1tIP0TUNh6o+mXg338Zl5EKChD+YGp6PN+Dbhs7qa34RxSw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-freebsd-64/0.14.23:
+ resolution: {integrity: sha512-/1xiTjoLuQ+LlbfjJdKkX45qK/M7ARrbLmyf7x3JhyQGMjcxRYVR6Dw81uH3qlMHwT4cfLW4aEVBhP1aNV7VsA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-freebsd-arm64/0.14.23:
+ resolution: {integrity: sha512-uyPqBU/Zcp6yEAZS4LKj5jEE0q2s4HmlMBIPzbW6cTunZ8cyvjG6YWpIZXb1KK3KTJDe62ltCrk3VzmWHp+iLg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-32/0.14.23:
+ resolution: {integrity: sha512-37R/WMkQyUfNhbH7aJrr1uCjDVdnPeTHGeDhZPUNhfoHV0lQuZNCKuNnDvlH/u/nwIYZNdVvz1Igv5rY/zfrzQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-64/0.14.23:
+ resolution: {integrity: sha512-H0gztDP60qqr8zoFhAO64waoN5yBXkmYCElFklpd6LPoobtNGNnDe99xOQm28+fuD75YJ7GKHzp/MLCLhw2+vQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-arm/0.14.23:
+ resolution: {integrity: sha512-x64CEUxi8+EzOAIpCUeuni0bZfzPw/65r8tC5cy5zOq9dY7ysOi5EVQHnzaxS+1NmV+/RVRpmrzGw1QgY2Xpmw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-arm64/0.14.23:
+ resolution: {integrity: sha512-c4MLOIByNHR55n3KoYf9hYDfBRghMjOiHLaoYLhkQkIabb452RWi+HsNgB41sUpSlOAqfpqKPFNg7VrxL3UX9g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-mips64le/0.14.23:
+ resolution: {integrity: sha512-kHKyKRIAedYhKug2EJpyJxOUj3VYuamOVA1pY7EimoFPzaF3NeY7e4cFBAISC/Av0/tiV0xlFCt9q0HJ68IBIw==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-ppc64le/0.14.23:
+ resolution: {integrity: sha512-7ilAiJEPuJJnJp/LiDO0oJm5ygbBPzhchJJh9HsHZzeqO+3PUzItXi+8PuicY08r0AaaOe25LA7sGJ0MzbfBag==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-riscv64/0.14.23:
+ resolution: {integrity: sha512-fbL3ggK2wY0D8I5raPIMPhpCvODFE+Bhb5QGtNP3r5aUsRR6TQV+ZBXIaw84iyvKC8vlXiA4fWLGhghAd/h/Zg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-s390x/0.14.23:
+ resolution: {integrity: sha512-GHMDCyfy7+FaNSO8RJ8KCFsnax8fLUsOrj9q5Gi2JmZMY0Zhp75keb5abTFCq2/Oy6KVcT0Dcbyo/bFb4rIFJA==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-netbsd-64/0.14.23:
+ resolution: {integrity: sha512-ovk2EX+3rrO1M2lowJfgMb/JPN1VwVYrx0QPUyudxkxLYrWeBxDKQvc6ffO+kB4QlDyTfdtAURrVzu3JeNdA2g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-openbsd-64/0.14.23:
+ resolution: {integrity: sha512-uYYNqbVR+i7k8ojP/oIROAHO9lATLN7H2QeXKt2H310Fc8FJj4y3Wce6hx0VgnJ4k1JDrgbbiXM8rbEgQyg8KA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-sunos-64/0.14.23:
+ resolution: {integrity: sha512-hAzeBeET0+SbScknPzS2LBY6FVDpgE+CsHSpe6CEoR51PApdn2IB0SyJX7vGelXzlyrnorM4CAsRyb9Qev4h9g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-windows-32/0.14.23:
+ resolution: {integrity: sha512-Kttmi3JnohdaREbk6o9e25kieJR379TsEWF0l39PQVHXq3FR6sFKtVPgY8wk055o6IB+rllrzLnbqOw/UV60EA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-windows-64/0.14.23:
+ resolution: {integrity: sha512-JtIT0t8ymkpl6YlmOl6zoSWL5cnCgyLaBdf/SiU/Eg3C13r0NbHZWNT/RDEMKK91Y6t79kTs3vyRcNZbfu5a8g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-windows-arm64/0.14.23:
+ resolution: {integrity: sha512-cTFaQqT2+ik9e4hePvYtRZQ3pqOvKDVNarzql0VFIzhc0tru/ZgdLoXd6epLiKT+SzoSce6V9YJ+nn6RCn6SHw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild/0.14.23:
+ resolution: {integrity: sha512-XjnIcZ9KB6lfonCa+jRguXyRYcldmkyZ99ieDksqW/C8bnyEX299yA4QH2XcgijCgaddEZePPTgvx/2imsq7Ig==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ esbuild-android-arm64: 0.14.23
+ esbuild-darwin-64: 0.14.23
+ esbuild-darwin-arm64: 0.14.23
+ esbuild-freebsd-64: 0.14.23
+ esbuild-freebsd-arm64: 0.14.23
+ esbuild-linux-32: 0.14.23
+ esbuild-linux-64: 0.14.23
+ esbuild-linux-arm: 0.14.23
+ esbuild-linux-arm64: 0.14.23
+ esbuild-linux-mips64le: 0.14.23
+ esbuild-linux-ppc64le: 0.14.23
+ esbuild-linux-riscv64: 0.14.23
+ esbuild-linux-s390x: 0.14.23
+ esbuild-netbsd-64: 0.14.23
+ esbuild-openbsd-64: 0.14.23
+ esbuild-sunos-64: 0.14.23
+ esbuild-windows-32: 0.14.23
+ esbuild-windows-64: 0.14.23
+ esbuild-windows-arm64: 0.14.23
+ dev: true
+
+ /estree-walker/2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: true
+
+ /fast-glob/3.2.11:
+ resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.4
+ dev: true
+
+ /fastq/1.13.0:
+ resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /fill-range/7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /fs.realpath/1.0.0:
+ resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=}
+ dev: true
+
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind/1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+ dev: true
+
+ /glob-parent/5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob/7.2.0:
+ resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /graceful-fs/4.2.9:
+ resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==}
+ dev: true
+
+ /has/1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+ dev: true
+
+ /import-fresh/3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /inflight/1.0.6:
+ resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits/2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /is-binary-path/2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-core-module/2.8.1:
+ resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /is-extglob/2.1.1:
+ resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-glob/4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-number/7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /kleur/4.1.4:
+ resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /magic-string/0.25.7:
+ resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==}
+ dependencies:
+ sourcemap-codec: 1.4.8
+ dev: true
+
+ /merge2/1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch/4.0.4:
+ resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /min-indent/1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /minimatch/3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimist/1.2.5:
+ resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==}
+ dev: true
+
+ /mkdirp/0.5.5:
+ resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.5
+ dev: true
+
+ /mri/1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /ms/2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /nanoid/3.3.1:
+ resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /normalize-path/3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /once/1.4.0:
+ resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /parent-module/1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /path-is-absolute/1.0.1:
+ resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-parse/1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /picocolors/1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /picomatch/2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /postcss/8.4.7:
+ resolution: {integrity: sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.1
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /queue-microtask/1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /readdirp/3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /resolve-from/4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve/1.22.0:
+ resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.8.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify/1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rimraf/2.7.1:
+ resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.0
+ dev: true
+
+ /rollup/2.68.0:
+ resolution: {integrity: sha512-XrMKOYK7oQcTio4wyTz466mucnd8LzkiZLozZ4Rz0zQD+HeX4nUK4B8GrTX/2EvN2/vBF/i2WnaXboPxo0JylA==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /run-parallel/1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /sade/1.8.1:
+ resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
+ engines: {node: '>=6'}
+ dependencies:
+ mri: 1.2.0
+ dev: true
+
+ /sander/0.5.1:
+ resolution: {integrity: sha1-dB4kXiMfB8r7b98PEzrfohalAq0=}
+ dependencies:
+ es6-promise: 3.3.1
+ graceful-fs: 4.2.9
+ mkdirp: 0.5.5
+ rimraf: 2.7.1
+ dev: true
+
+ /sorcery/0.10.0:
+ resolution: {integrity: sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=}
+ hasBin: true
+ dependencies:
+ buffer-crc32: 0.2.13
+ minimist: 1.2.5
+ sander: 0.5.1
+ sourcemap-codec: 1.4.8
+ dev: true
+
+ /source-map-js/1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map/0.7.3:
+ resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /sourcemap-codec/1.4.8:
+ resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ dev: true
+
+ /strip-indent/3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ min-indent: 1.0.1
+ dev: true
+
+ /supports-preserve-symlinks-flag/1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /svelte-check/2.4.5_svelte@3.46.4:
+ resolution: {integrity: sha512-nRft8BbG2wcxyCdHDZ7X43xLcvDzua3xLwq6wzHGcAF3ka3Jyhv2rvgq0+SF9NwHLMefp9C2XkM6etzsxK/cMQ==}
+ hasBin: true
+ peerDependencies:
+ svelte: ^3.24.0
+ dependencies:
+ chokidar: 3.5.3
+ fast-glob: 3.2.11
+ import-fresh: 3.3.0
+ minimist: 1.2.5
+ picocolors: 1.0.0
+ sade: 1.8.1
+ source-map: 0.7.3
+ svelte: 3.46.4
+ svelte-preprocess: 4.10.4_svelte@3.46.4+typescript@4.5.5
+ typescript: 4.5.5
+ transitivePeerDependencies:
+ - '@babel/core'
+ - coffeescript
+ - less
+ - node-sass
+ - postcss
+ - postcss-load-config
+ - pug
+ - sass
+ - stylus
+ - sugarss
+ dev: true
+
+ /svelte-hmr/0.14.9_svelte@3.46.4:
+ resolution: {integrity: sha512-bKE9+4qb4sAnA+TKHiYurUl970rjA0XmlP9TEP7K/ncyWz3m81kA4HOgmlZK/7irGK7gzZlaPDI3cmf8fp/+tg==}
+ peerDependencies:
+ svelte: '>=3.19.0'
+ dependencies:
+ svelte: 3.46.4
+ dev: true
+
+ /svelte-preprocess/4.10.4_svelte@3.46.4+typescript@4.5.5:
+ resolution: {integrity: sha512-fuwol0N4UoHsNQolLFbMqWivqcJ9N0vfWO9IuPAiX/5okfoGXURyJ6nECbuEIv0nU3M8Xe2I1ONNje2buk7l6A==}
+ engines: {node: '>= 9.11.2'}
+ requiresBuild: true
+ peerDependencies:
+ '@babel/core': ^7.10.2
+ coffeescript: ^2.5.1
+ less: ^3.11.3 || ^4.0.0
+ node-sass: '*'
+ postcss: ^7 || ^8
+ postcss-load-config: ^2.1.0 || ^3.0.0
+ pug: ^3.0.0
+ sass: ^1.26.8
+ stylus: ^0.55.0
+ sugarss: ^2.0.0
+ svelte: ^3.23.0
+ typescript: ^3.9.5 || ^4.0.0
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ coffeescript:
+ optional: true
+ less:
+ optional: true
+ node-sass:
+ optional: true
+ postcss:
+ optional: true
+ postcss-load-config:
+ optional: true
+ pug:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ typescript:
+ optional: true
+ dependencies:
+ '@types/pug': 2.0.6
+ '@types/sass': 1.43.1
+ detect-indent: 6.1.0
+ magic-string: 0.25.7
+ sorcery: 0.10.0
+ strip-indent: 3.0.0
+ svelte: 3.46.4
+ typescript: 4.5.5
+ dev: true
+
+ /svelte/3.46.4:
+ resolution: {integrity: sha512-qKJzw6DpA33CIa+C/rGp4AUdSfii0DOTCzj/2YpSKKayw5WGSS624Et9L1nU1k2OVRS9vaENQXp2CVZNU+xvIg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /to-regex-range/5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /tslib/2.3.1:
+ resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
+ dev: true
+
+ /typescript/4.5.5:
+ resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
+ /vite/2.8.4:
+ resolution: {integrity: sha512-GwtOkkaT2LDI82uWZKcrpRQxP5tymLnC7hVHHqNkhFNknYr0hJUlDLfhVRgngJvAy3RwypkDCWtTKn1BjO96Dw==}
+ engines: {node: '>=12.2.0'}
+ hasBin: true
+ peerDependencies:
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ peerDependenciesMeta:
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ dependencies:
+ esbuild: 0.14.23
+ postcss: 8.4.7
+ resolve: 1.22.0
+ rollup: 2.68.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /wrappy/1.0.2:
+ resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
+ dev: true
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
new file mode 100644
index 0000000..d75d248
--- /dev/null
+++ b/frontend/public/favicon.ico
Binary files differ
diff --git a/frontend/src/AddBook.svelte b/frontend/src/AddBook.svelte
new file mode 100644
index 0000000..9352808
--- /dev/null
+++ b/frontend/src/AddBook.svelte
@@ -0,0 +1,103 @@
+<script lang="ts">
+ import { postToServer } from "./utils";
+
+ export let whereami: string;
+ export let mode: string;
+ export let ebook: any;
+
+ let author: string = ebook ? ebook.author : "",
+ title: string = ebook ? ebook.title : "",
+ isbn: string = ebook ? ebook.isbn : "",
+ format: string = ebook ? ebook.format : "",
+ pages: string = ebook ? ebook.pages : "",
+ description: string = ebook ? ebook.description : "",
+ year: number = ebook ? ebook.year : null,
+ id: number = ebook ? ebook.id : null,
+ publisher: string = ebook ? ebook.publisher : "";
+
+ async function add() {
+ await postToServer(
+ "/book",
+ {
+ author,
+ title,
+ year,
+ publisher,
+ id,
+ isbn,
+ format,
+ pages,
+ description,
+ },
+ true
+ );
+ author = "";
+ title = "";
+ year = null;
+ publisher = "";
+ id = null;
+ isbn = "";
+ format = "";
+ pages = "";
+ description = "";
+ if (mode === "edit") whereami = "books";
+ }
+</script>
+
+<main>
+ <button type="button" on:click={add}>
+ {mode[0].toUpperCase() + mode.substring(1)}
+ </button><br />
+ <label for="author">Author:</label>
+ <input bind:value={author} id="author" maxlength="100" /><br />
+ <label for="title">Title:</label>
+ <input bind:value={title} id="title" maxlength="100" /><br />
+ <label for="year">Year:</label>
+ <input
+ bind:value={year}
+ id="year"
+ type="number"
+ min="0000"
+ step="1"
+ max="2000000"
+ /><br />
+ <label for="publisher">Publisher:</label>
+ <input bind:value={publisher} id="publisher" maxlength="100" /><br />
+ <label for="isbn">Isbn:</label>
+ <input bind:value={isbn} id="isbn" maxlength="13" /><br />
+ <label for="format">Format:</label>
+ <input bind:value={format} id="format" maxlength="3" /><br />
+ <label for="pages">Pages:</label>
+ <input
+ bind:value={pages}
+ id="pages"
+ type="number"
+ min="0"
+ step="1"
+ max="2000000"
+ /><br />
+ <label for="description">Description:</label>
+ <input bind:value={description} id="description" maxlength="255" /><br />
+ <button type="button" on:click={() => (whereami = "books")}>Go back</button>
+</main>
+
+<style>
+ :root {
+ font-family: "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell;
+ }
+
+ main {
+ text-align: center;
+ font-size: 1.9em;
+ }
+ button {
+ margin-top: 30px;
+ margin-bottom: 30px;
+ margin-left: 15px;
+ text-decoration: underline;
+ font-size: 1em;
+ }
+ input {
+ font-size: 1em;
+ }
+</style>
diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte
new file mode 100644
index 0000000..ee4d894
--- /dev/null
+++ b/frontend/src/App.svelte
@@ -0,0 +1,32 @@
+<script lang="ts">
+ import DbInput from "./DBInput.svelte";
+ import Login from "./Login.svelte";
+ import Books from "./Books.svelte";
+ import AddBook from "./AddBook.svelte";
+ let whereami = "check-db";
+ // whereami = "books";
+ let ebook = {};
+ // whereami = "books";
+
+ $: {
+ console.log(whereami);
+ }
+</script>
+
+{#if whereami === "check-db"}
+ <DbInput bind:whereami />
+{:else if whereami === "login"}
+ <Login bind:whereami />
+{:else if whereami === "books"}
+ <Books bind:whereami bind:ebook />
+{:else if whereami === "add-book"}
+ <AddBook bind:whereami mode="add" ebook={null} />
+{:else if whereami === "edit-book"}
+ <AddBook bind:whereami mode="edit" bind:ebook />
+{/if}
+
+<style>
+ :root {
+ font-family: "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell;
+ }
+</style>
diff --git a/frontend/src/Books.svelte b/frontend/src/Books.svelte
new file mode 100644
index 0000000..db1c10b
--- /dev/null
+++ b/frontend/src/Books.svelte
@@ -0,0 +1,165 @@
+<script lang="ts">
+ import { fetchFromServer, deleteOnServer } from "./utils";
+ import Search from "./Search.svelte";
+
+ export let whereami: string;
+ export let ebook: object;
+
+ // let thead: HTMLTableSectionElement, tbody: HTMLTableSectionElement;
+ let searchCom: Search;
+ let filters: any = { key: 2 };
+ let books: Array<any> = [];
+ let _books: Array<any> = [];
+ async function loadData() {
+ _books = await fetchFromServer("/books");
+ books = _books;
+ }
+ loadData();
+
+ let showSearch = false;
+
+ $: {
+ async function getBooks() {
+ if (Object.keys(filters).length === 1) {
+ books = _books;
+ } else {
+ books = _books.filter((b: any) => {
+ for (const fk in filters) {
+ const fv = filters[fk];
+ if (!fv || fk === "key") continue;
+ if (
+ b[fk]
+ .toString()
+ .toLowerCase()
+ .includes(fv.toString().toLowerCase())
+ )
+ return true;
+ }
+ return false;
+ });
+ }
+ }
+ getBooks();
+ }
+
+ function add() {
+ whereami = "add-book";
+ }
+ function search() {
+ showSearch = !showSearch;
+ }
+ function edit(book: object) {
+ whereami = "edit-book";
+ ebook = book;
+ }
+ async function remove(id: number) {
+ await deleteOnServer("/book?bid=" + id, true);
+ _books = _books.filter((b) => b.id !== id);
+ }
+ function clearFilters() {
+ searchCom.clear();
+ filters = { key: Math.random() };
+ }
+</script>
+
+<main>
+ <button type="button" class="main-btn" on:click={add}>Add</button>
+ <button type="button" class="main-btn" on:click={search}>
+ {showSearch ? "Hide" : "Show"} search dialog
+ </button>
+ <button type="button" class="main-btn" on:click={clearFilters}>
+ Clear filters
+ </button>
+ <button type="button" class="main-btn" on:click={loadData}>
+ Reload data
+ </button>
+ {#if showSearch}
+ <Search bind:filters bind:this={searchCom} />
+ {/if}
+ <table>
+ <thead>
+ <tr>
+ <th>Id</th>
+ <th>Author</th>
+ <th>Title</th>
+ <th>Year of<br />publication</th>
+ <th>Publisher</th>
+ <th>Isbn</th>
+ <th>Format</th>
+ <th>Pages</th>
+ <th>Description</th>
+ <th />
+ <th />
+ </tr>
+ </thead>
+ <tbody>
+ {#each books as book}
+ <tr>
+ <td>{book.id}</td>
+ <td>{book.author}</td>
+ <td>{book.title}</td>
+ <td>{book.year}</td>
+ <td>{book.publisher}</td>
+ <td>{book.isbn}</td>
+ <td>{book.format}</td>
+ <td>{book.pages}</td>
+ <td>{book.description}</td>
+ <td>
+ <button
+ type="button"
+ class="action-btn"
+ on:click={() => edit(book)}
+ >
+ Edit
+ </button>
+ </td>
+ <td>
+ <button
+ type="button"
+ class="action-btn"
+ on:click={() => remove(book.id)}
+ >
+ Remove
+ </button>
+ </td>
+ </tr>
+ {/each}
+ </tbody>
+ </table>
+</main>
+
+<style>
+ :root {
+ font-family: "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell;
+ }
+
+ main {
+ text-align: center;
+ }
+ table {
+ margin: 0 auto;
+ border-collapse: collapse;
+ width: 90%;
+ font-size: 1.5em;
+ }
+ thead {
+ font-weight: bold;
+ }
+ td,
+ th {
+ border: 1px solid black;
+ }
+ .main-btn {
+ margin-top: 30px;
+ margin-bottom: 30px;
+ margin-left: 15px;
+ font-size: 1.9em;
+ text-decoration: underline;
+ }
+ .action-btn {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ font-size: 1.2em;
+ text-decoration: underline;
+ }
+</style>
diff --git a/frontend/src/DBInput.svelte b/frontend/src/DBInput.svelte
new file mode 100644
index 0000000..f520014
--- /dev/null
+++ b/frontend/src/DBInput.svelte
@@ -0,0 +1,60 @@
+<script lang="ts">
+ import { postToServer } from "./utils";
+
+ export let whereami: string;
+
+ let pt: string;
+
+ async function sendData() {
+ const ids = ["server", "port", "database", "user", "password"];
+ const body: any = {};
+ for (const id of ids) {
+ body[id] = (document.getElementById(id) as HTMLInputElement).value;
+ }
+ body["port"] = parseInt(body["port"]);
+
+ const res = await postToServer("/check-db", body, true);
+ if (res === "ok") {
+ whereami = "login";
+ } else {
+ pt = "Error, your database credentials are wrong";
+ }
+ }
+</script>
+
+<main>
+ <label for="server">Server:</label>
+ <input type="text" id="server" value="127.0.0.1" /><br /><br />
+ <label for="port">Port:</label>
+ <input type="number" min="1" max="65535" id="port" value="3306" /><br /><br />
+ <label for="database">Database:</label>
+ <input type="text" id="database" value="aitp" /><br /><br />
+ <label for="user">User:</label>
+ <input type="text" id="user" value="admin" /><br /><br />
+ <label for="password">Password:</label>
+ <input type="password" id="password" value="qwerty" /><br /><br />
+ <button type="button" on:click={sendData}>Connect</button>
+ <p contenteditable="true" bind:innerHTML={pt} />
+</main>
+
+<style>
+ :root {
+ font-family: "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell;
+ }
+
+ main {
+ text-align: center;
+ padding: 1em;
+ margin: 0 auto;
+ font-size: 2em;
+ }
+ input,
+ button {
+ font-size: 1em;
+ margin-left: 10px;
+ }
+
+ p {
+ color: red;
+ }
+</style>
diff --git a/frontend/src/Login.svelte b/frontend/src/Login.svelte
new file mode 100644
index 0000000..674ca47
--- /dev/null
+++ b/frontend/src/Login.svelte
@@ -0,0 +1,74 @@
+<script lang="ts">
+ export let whereami: string;
+ import { postToServer } from "./utils";
+
+ let pt = "";
+ let mode = "login",
+ // email = "maks@maks.pl",
+ email = "asd@asd",
+ login = "maks",
+ password = "qwerty";
+
+ async function register() {
+ const res = await postToServer(
+ "/login",
+ { email, login, password, mode },
+ true
+ );
+ console.log(res);
+ if (res === "ok") {
+ whereami = "books";
+ } else {
+ pt = "Wrong login or password";
+ }
+ }
+</script>
+
+<main>
+ {#if mode === "register"}
+ <label for="email">Email:</label>
+ <input bind:value={email} type="email" id="email" maxlength="254" /><br
+ /><br />
+ {/if}
+ <label for="login">Login:</label>
+ <input bind:value={login} type="text" id="login" maxlength="256" /><br /><br
+ />
+ <label for="password">Password:</label>
+ <input bind:value={password} type="password" id="password" /><br /><br />
+ <button type="button" on:click={register}>
+ {mode === "login" ? "Login" : "Register"}
+ </button><br /><br />
+ <label for="mode">Register:</label>
+ <input
+ type="checkbox"
+ id="mode"
+ on:click={() => (mode = mode === "login" ? "register" : "login")}
+ />
+ <p>{pt}</p>
+</main>
+
+<style>
+ :root {
+ font-family: "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell;
+ }
+
+ main {
+ text-align: center;
+ padding: 1em;
+ margin: 0 auto;
+ font-size: 2em;
+ }
+ input,
+ button {
+ font-size: 1em;
+ margin-left: 10px;
+ }
+ input[type="checkbox"] {
+ width: 25px;
+ height: 25px;
+ }
+
+ p {
+ color: red;
+ }
+</style>
diff --git a/frontend/src/Search.svelte b/frontend/src/Search.svelte
new file mode 100644
index 0000000..2f192eb
--- /dev/null
+++ b/frontend/src/Search.svelte
@@ -0,0 +1,92 @@
+<script lang="ts">
+ export let filters: any;
+ let id: number,
+ author: string,
+ title: string,
+ year: number,
+ isbn: string,
+ format: string,
+ pages: string,
+ description: string,
+ publisher: string;
+ export function clear() {
+ id = null;
+ author = null;
+ title = null;
+ year = null;
+ isbn = null;
+ format = null;
+ pages = null;
+ description = null;
+ publisher = null;
+ }
+ $: {
+ if (id) filters["id"] = id;
+ else delete filters["id"];
+ if (author) filters["author"] = author;
+ else delete filters["author"];
+ if (title) filters["title"] = title;
+ else delete filters["title"];
+ if (year) filters["year"] = year;
+ else delete filters["year"];
+ if (publisher) filters["publisher"] = publisher;
+ else delete filters["publisher"];
+ if (isbn) filters["isbn"] = isbn;
+ else delete filters["isbn"];
+ if (format) filters["format"] = format;
+ else delete filters["format"];
+ if (pages) filters["pages"] = pages;
+ else delete filters["pages"];
+ if (description) filters["description"] = description;
+ else delete filters["description"];
+ filters["key"] = Math.random();
+ }
+</script>
+
+<main>
+ <label for="id">Id:</label>
+ <input type="number" id="id" bind:value={id} /><br />
+ <label for="author">Author:</label>
+ <input type="text" id="author" bind:value={author} /><br />
+ <label for="title">Title:</label>
+ <input type="text" id="title" bind:value={title} /><br />
+ <label for="year">Year:</label>
+ <input type="number" id="year" bind:value={year} /><br />
+ <label for="publisher">Publisher:</label>
+ <input type="number" id="publisher" bind:value={publisher} /><br />
+ <label for="isbn">Isbn:</label>
+ <!-- @tsignore -->
+ <input bind:value={isbn} id="isbn" /><br />
+ <label for="format">Format:</label>
+ <input bind:value={format} id="format" /><br />
+ <label for="pages">Pages:</label>
+ <input bind:value={pages} id="pages" /><br />
+ <label for="description">Description:</label>
+ <input
+ bind:value={description}
+ id="description"
+ style="margin-bottom: 0;"
+ /><br />
+ <!-- <button on:click={search}>Filter</button> -->
+</main>
+
+<style>
+ main {
+ position: fixed;
+ left: 0;
+ right: 0;
+ margin: auto;
+ height: fit-content;
+ width: fit-content;
+ /* border: 1px solid black; */
+ font-size: 1.9em;
+ margin-bottom: 30px;
+ color: white;
+ background-color: rgba(0, 0, 0, 0.75);
+ padding: 50px;
+ }
+ input {
+ font-size: 1em;
+ margin-bottom: 30px;
+ }
+</style>
diff --git a/frontend/src/assets/svelte.png b/frontend/src/assets/svelte.png
new file mode 100644
index 0000000..e673c91
--- /dev/null
+++ b/frontend/src/assets/svelte.png
Binary files differ
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
new file mode 100644
index 0000000..d8200ac
--- /dev/null
+++ b/frontend/src/main.ts
@@ -0,0 +1,7 @@
+import App from './App.svelte'
+
+const app = new App({
+ target: document.getElementById('app')
+})
+
+export default app
diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts
new file mode 100644
index 0000000..0bf115a
--- /dev/null
+++ b/frontend/src/utils.ts
@@ -0,0 +1,22 @@
+export const url = "http://localhost:8000";
+export async function postToServer(path: string, body: object, asText = false) {
+ const res = await fetch(url + path, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(body),
+ });
+ if (asText) return await res.text()
+ return res.json();
+}
+export async function fetchFromServer(path: string, asText = false) {
+ const res = await fetch(url + path);
+ if (asText) return await res.text()
+ return res.json();
+}
+export async function deleteOnServer(path: string, asText = false) {
+ const res = await fetch(url + path, { method: "DELETE" });
+ if (asText) return await res.text()
+ return res.json();
+}
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
new file mode 100644
index 0000000..4078e74
--- /dev/null
+++ b/frontend/src/vite-env.d.ts
@@ -0,0 +1,2 @@
+/// <reference types="svelte" />
+/// <reference types="vite/client" />
diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js
new file mode 100644
index 0000000..3630bb3
--- /dev/null
+++ b/frontend/svelte.config.js
@@ -0,0 +1,7 @@
+import sveltePreprocess from 'svelte-preprocess'
+
+export default {
+ // Consult https://github.com/sveltejs/svelte-preprocess
+ // for more information about preprocessors
+ preprocess: sveltePreprocess()
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..4d6c04c
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "extends": "@tsconfig/svelte/tsconfig.json",
+ "compilerOptions": {
+ "target": "esnext",
+ "useDefineForClassFields": true,
+ "module": "esnext",
+ "resolveJsonModule": true,
+ "baseUrl": ".",
+ /**
+ * Typecheck JS in `.svelte` and `.js` files by default.
+ * Disable checkJs if you'd like to use dynamic types in JS.
+ * Note that setting allowJs false does not prevent the use
+ * of JS in `.svelte` files.
+ */
+ "allowJs": true,
+ "checkJs": true
+ },
+ "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json
new file mode 100644
index 0000000..e993792
--- /dev/null
+++ b/frontend/tsconfig.node.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "module": "esnext",
+ "moduleResolution": "node"
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 0000000..401b4d4
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import { svelte } from '@sveltejs/vite-plugin-svelte'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [svelte()]
+})
diff --git a/start b/start
new file mode 100755
index 0000000..1005fcc
--- /dev/null
+++ b/start
@@ -0,0 +1 @@
+dotnet run
diff --git a/бібліотека.csproj b/бібліотека.csproj
new file mode 100644
index 0000000..1f94eab
--- /dev/null
+++ b/бібліотека.csproj
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <Nullable>enable</Nullable>
+ <ImplicitUsings>enable</ImplicitUsings>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.2" />
+ <PackageReference Include="MySqlConnector" Version="2.1.7" />
+ <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
+ <Watch Include="**\*.cs" />
+ </ItemGroup>
+
+</Project>