initial commit
This commit is contained in:
commit
75a0cff258
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
node_modules
|
||||
|
||||
# Output
|
||||
.output
|
||||
.vercel
|
||||
.netlify
|
||||
.wrangler
|
||||
/.svelte-kit
|
||||
/build
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Env
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.test
|
||||
|
||||
# Vite
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# Have empty data folder ready to go
|
||||
/data/*
|
||||
!/data/.gitkeep
|
||||
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@ -0,0 +1,6 @@
|
||||
# Package Managers
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
yarn.lock
|
||||
bun.lock
|
||||
bun.lockb
|
||||
15
.prettierrc
Normal file
15
.prettierrc
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.svelte",
|
||||
"options": {
|
||||
"parser": "svelte"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
38
README.md
Normal file
38
README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# sv
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npx sv create
|
||||
|
||||
# create a new project in my-app
|
||||
npx sv create my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
||||
0
data/.gitkeep
Normal file
0
data/.gitkeep
Normal file
10
drizzle.config.ts
Normal file
10
drizzle.config.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
export default defineConfig({
|
||||
out: "./drizzle",
|
||||
schema: "./src/lib/server/db/schema",
|
||||
dialect: "sqlite",
|
||||
dbCredentials: {
|
||||
url: "./data/db.sqlite",
|
||||
},
|
||||
});
|
||||
3625
package-lock.json
generated
Normal file
3625
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
package.json
Normal file
42
package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "my-app",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"format": "prettier --write .",
|
||||
"lint": "prettier --check ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^4.0.0",
|
||||
"@sveltejs/kit": "^2.16.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
"drizzle-kit": "^0.30.6",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^6.2.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@libsql/client": "^0.15.2",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"drizzle-orm": "^0.41.0",
|
||||
"nanoid": "^5.1.5"
|
||||
},
|
||||
"overrides": {
|
||||
"@sveltejs/kit": {
|
||||
"cookie": "^0.7.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/app.css
Normal file
1
src/app.css
Normal file
@ -0,0 +1 @@
|
||||
@import 'tailwindcss';
|
||||
13
src/app.d.ts
vendored
Normal file
13
src/app.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
12
src/app.html
Normal file
12
src/app.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
25
src/hooks.server.ts
Normal file
25
src/hooks.server.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { db } from "$lib/server/db/db";
|
||||
import { users } from "$lib/server/db/schema/_index";
|
||||
import type { ServerInit } from "@sveltejs/kit";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { nanoid } from "nanoid";
|
||||
import { writeFileSync } from "fs";
|
||||
|
||||
export const init: ServerInit = async () => {
|
||||
const anyUser = await db.query.users.findFirst();
|
||||
|
||||
if (!anyUser) {
|
||||
const pass = nanoid(12);
|
||||
|
||||
await db.insert(users).values({
|
||||
name: "admin",
|
||||
admin: true,
|
||||
password: bcrypt.hashSync(pass),
|
||||
});
|
||||
|
||||
console.log(`default admin password: ${pass}`);
|
||||
console.log("saved to ./default_admin_pass.txt, don't share it and change it asap");
|
||||
|
||||
writeFileSync("./data/default_admin_pass.txt", pass);
|
||||
}
|
||||
};
|
||||
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
@ -0,0 +1 @@
|
||||
// place files you want to import through the `$lib` alias in this folder.
|
||||
4
src/lib/server/db/db.ts
Normal file
4
src/lib/server/db/db.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { drizzle } from "drizzle-orm/libsql";
|
||||
import * as schema from "./schema/_index";
|
||||
|
||||
export const db = drizzle("file:./data/db.sqlite", { schema });
|
||||
7
src/lib/server/db/schema/_index.ts
Normal file
7
src/lib/server/db/schema/_index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from "./users";
|
||||
export * from "./permissions";
|
||||
export * from "./groups";
|
||||
export * from "./groupsPermissions";
|
||||
export * from "./usersGroups";
|
||||
export * from "./usersPermissions";
|
||||
export * from "./devices";
|
||||
10
src/lib/server/db/schema/devices.ts
Normal file
10
src/lib/server/db/schema/devices.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
|
||||
export const devices = sqliteTable("devices", {
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
name: text().notNull().unique(),
|
||||
mac: text().notNull().unique(),
|
||||
ip: text().notNull(),
|
||||
port: int().notNull(),
|
||||
packets: int().notNull().default(3),
|
||||
});
|
||||
14
src/lib/server/db/schema/groups.ts
Normal file
14
src/lib/server/db/schema/groups.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
import { groupsPermissions } from "./groupsPermissions";
|
||||
import { usersGroups } from "./usersGroups";
|
||||
|
||||
export const groups = sqliteTable("groups", {
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
name: text().notNull().unique(),
|
||||
});
|
||||
|
||||
export const groupsRelations = relations(groups, ({ many }) => ({
|
||||
groupsPermissions: many(groupsPermissions),
|
||||
usersGroups: many(usersGroups),
|
||||
}));
|
||||
22
src/lib/server/db/schema/groupsPermissions.ts
Normal file
22
src/lib/server/db/schema/groupsPermissions.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { int, primaryKey, sqliteTable } from "drizzle-orm/sqlite-core";
|
||||
import { groups } from "./groups";
|
||||
import { permissions } from "./permissions";
|
||||
import { relations } from "drizzle-orm";
|
||||
|
||||
export const groupsPermissions = sqliteTable("groups_permissions", {
|
||||
groupId: int().notNull().references(() => groups.id),
|
||||
permissionId: int().notNull().references(() => permissions.id),
|
||||
}, (t) => [
|
||||
primaryKey({ columns: [t.groupId, t.permissionId] }),
|
||||
]);
|
||||
|
||||
export const groupsPermissionsRelations = relations(groupsPermissions, ({ one }) => ({
|
||||
group: one(groups, {
|
||||
fields: [groupsPermissions.groupId],
|
||||
references: [groups.id],
|
||||
}),
|
||||
permission: one(permissions, {
|
||||
fields: [groupsPermissions.permissionId],
|
||||
references: [permissions.id],
|
||||
}),
|
||||
}));
|
||||
16
src/lib/server/db/schema/permissions.ts
Normal file
16
src/lib/server/db/schema/permissions.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { int, sqliteTable } from "drizzle-orm/sqlite-core";
|
||||
import { devices } from "./devices";
|
||||
|
||||
export const permissions = sqliteTable("permissions", {
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
deviceId: int().notNull(),
|
||||
flags: int().notNull(),
|
||||
});
|
||||
|
||||
export const permissionsRelations = relations(permissions, ({ one }) => ({
|
||||
device: one(devices, {
|
||||
fields: [permissions.deviceId],
|
||||
references: [devices.id],
|
||||
}),
|
||||
}));
|
||||
16
src/lib/server/db/schema/users.ts
Normal file
16
src/lib/server/db/schema/users.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
import { usersPermissions } from "./usersPermissions";
|
||||
import { usersGroups } from "./usersGroups";
|
||||
|
||||
export const users = sqliteTable("users", {
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
name: text().notNull().unique(),
|
||||
admin: int({ mode: "boolean" }).notNull().default(false),
|
||||
password: text().notNull(),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
usersPermissions: many(usersPermissions),
|
||||
usersGroups: many(usersGroups),
|
||||
}));
|
||||
22
src/lib/server/db/schema/usersGroups.ts
Normal file
22
src/lib/server/db/schema/usersGroups.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { int, primaryKey, sqliteTable } from "drizzle-orm/sqlite-core";
|
||||
import { users } from "./users";
|
||||
import { groups } from "./groups";
|
||||
|
||||
export const usersGroups = sqliteTable("users_groups", {
|
||||
userId: int().notNull().references(() => users.id),
|
||||
groupId: int().notNull().references(() => groups.id),
|
||||
}, (t) => [
|
||||
primaryKey({ columns: [t.userId, t.groupId] }),
|
||||
]);
|
||||
|
||||
export const usersGroupsRelations = relations(usersGroups, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [usersGroups.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
group: one(groups, {
|
||||
fields: [usersGroups.groupId],
|
||||
references: [groups.id],
|
||||
}),
|
||||
}));
|
||||
22
src/lib/server/db/schema/usersPermissions.ts
Normal file
22
src/lib/server/db/schema/usersPermissions.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { int, primaryKey, sqliteTable } from "drizzle-orm/sqlite-core";
|
||||
import { users } from "./users";
|
||||
import { permissions } from "./permissions";
|
||||
|
||||
export const usersPermissions = sqliteTable("users_permissions", {
|
||||
userId: int().notNull().references(() => users.id),
|
||||
permissionId: int().notNull().references(() => permissions.id),
|
||||
}, (t) => [
|
||||
primaryKey({ columns: [t.userId, t.permissionId] }),
|
||||
]);
|
||||
|
||||
export const usersPermissionsRelations = relations(usersPermissions, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [usersPermissions.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
permission: one(permissions, {
|
||||
fields: [usersPermissions.permissionId],
|
||||
references: [permissions.id],
|
||||
}),
|
||||
}));
|
||||
75
src/lib/server/sessions.ts
Normal file
75
src/lib/server/sessions.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { nanoid } from "nanoid";
|
||||
import type { groups, permissions, users } from "./db/schema/_index";
|
||||
import { db } from "./db/db";
|
||||
|
||||
type SessionData = {
|
||||
userId: number,
|
||||
userAgent: string,
|
||||
};
|
||||
|
||||
const sessions: Map<string, SessionData> = new Map();
|
||||
|
||||
export function createSession(data: SessionData) {
|
||||
const token = nanoid();
|
||||
sessions.set(token, data);
|
||||
setTimeout(() => sessions.delete(token), 1000 * 60 * 60 * 24);
|
||||
return token;
|
||||
};
|
||||
|
||||
export type FullUser = typeof users.$inferSelect & {
|
||||
permissions: typeof permissions.$inferSelect[],
|
||||
groups: typeof groups.$inferSelect & { permissions: typeof permissions.$inferSelect[] }[]
|
||||
};
|
||||
|
||||
export async function getUserFromSession(sessionId?: string): Promise<typeof users.$inferSelect | undefined> {
|
||||
if (!sessionId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const data = sessions.get(sessionId);
|
||||
|
||||
if (!data) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// what in the nested fuck is this shit
|
||||
// I thought ORMs made it easier but they just make queries more ridiculous
|
||||
const user = await db.query.users.findFirst({
|
||||
where: (users, { eq }) => eq(users.id, data.userId),
|
||||
with: {
|
||||
usersGroups: {
|
||||
with: {
|
||||
group: {
|
||||
with: {
|
||||
groupsPermissions: {
|
||||
with: {
|
||||
permission: {
|
||||
with: {
|
||||
device: true
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
usersPermissions: {
|
||||
with: {
|
||||
permission: {
|
||||
with: {
|
||||
device: true
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
export function deleteSession(sessionId?: string) {
|
||||
if (!sessionId) return;
|
||||
sessions.delete(sessionId);
|
||||
}
|
||||
7
src/routes/+layout.svelte
Normal file
7
src/routes/+layout.svelte
Normal file
@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
import '../app.css';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
{@render children()}
|
||||
6
src/routes/+page.server.ts
Normal file
6
src/routes/+page.server.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
redirect(302, '/dashboard');
|
||||
};
|
||||
15
src/routes/dashboard/+layout.server.ts
Normal file
15
src/routes/dashboard/+layout.server.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { getUserFromSession } from "$lib/server/sessions";
|
||||
import { redirect } from "@sveltejs/kit";
|
||||
import type { LayoutServerLoad } from "./$types";
|
||||
|
||||
export const load: LayoutServerLoad = async ({ cookies }) => {
|
||||
const user = await getUserFromSession(cookies.get("session"));
|
||||
|
||||
if (!user) {
|
||||
redirect(302, "/login");
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
}
|
||||
};
|
||||
15
src/routes/dashboard/+layout.svelte
Normal file
15
src/routes/dashboard/+layout.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
let { children, data } = $props();
|
||||
</script>
|
||||
|
||||
<p>logged in as {data.user.name}</p>
|
||||
<a href="/dashboard">home</a>
|
||||
{#if data.user.admin}
|
||||
<a href="/dashboard/users">users</a>
|
||||
<a href="/dashboard/groups">groups</a>
|
||||
{/if}
|
||||
<a href="/logout">logout</a>
|
||||
|
||||
<br><br>
|
||||
|
||||
{@render children()}
|
||||
15
src/routes/dashboard/+page.server.ts
Normal file
15
src/routes/dashboard/+page.server.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { db } from "$lib/server/db/db";
|
||||
import type { FullUser } from "$lib/server/sessions";
|
||||
import type { ServerLoad } from "@sveltejs/kit";
|
||||
|
||||
export const load: ServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent() as { user: FullUser };
|
||||
|
||||
if (user.admin) {
|
||||
console.log(user);
|
||||
|
||||
return {
|
||||
devices: await db.query.devices.findMany(),
|
||||
}
|
||||
}
|
||||
};
|
||||
5
src/routes/dashboard/+page.svelte
Normal file
5
src/routes/dashboard/+page.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<script lang="ts">
|
||||
let { data } = $props();
|
||||
</script>
|
||||
|
||||
aaaa
|
||||
46
src/routes/login/+page.server.ts
Normal file
46
src/routes/login/+page.server.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { createSession, getUserFromSession } from '$lib/server/sessions';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { Actions } from './$types';
|
||||
import { db } from '$lib/server/db/db';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
export const actions = {
|
||||
default: async ({ cookies, request }) => {
|
||||
if (await getUserFromSession(cookies.get('session'))) {
|
||||
redirect(302, "/dashboard");
|
||||
}
|
||||
|
||||
const data = await request.formData();
|
||||
const username = data.get("username")?.toString();
|
||||
const password = data.get("password")?.toString();
|
||||
|
||||
if (!username || !password) {
|
||||
return {
|
||||
error: "MISSING_CREDENTIALS"
|
||||
}
|
||||
}
|
||||
|
||||
const user = await db.query.users.findFirst({
|
||||
where: (users, { eq }) => eq(users.name, username),
|
||||
});
|
||||
|
||||
if (!user || !bcrypt.compareSync(password, user.password)) {
|
||||
return {
|
||||
error: "INVALID_CREDENTIALS"
|
||||
}
|
||||
}
|
||||
|
||||
cookies.set("session", createSession({
|
||||
userAgent: request.headers.get("user-agent") ?? "UNKNOWN",
|
||||
userId: user.id
|
||||
}), {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: true,
|
||||
maxAge: 60 * 60 * 24,
|
||||
});
|
||||
|
||||
redirect(302, "/dashboard");
|
||||
}
|
||||
} satisfies Actions;
|
||||
21
src/routes/login/+page.svelte
Normal file
21
src/routes/login/+page.svelte
Normal file
@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type { PageProps } from './$types';
|
||||
|
||||
let { form }: PageProps = $props();
|
||||
</script>
|
||||
|
||||
<form method="POST">
|
||||
<label>
|
||||
Username
|
||||
<input name="username" type="text">
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
<input name="password" type="password">
|
||||
</label>
|
||||
<button>Log in</button>
|
||||
</form>
|
||||
|
||||
{#if form?.error}
|
||||
<p>Could not login: {form.error}</p>
|
||||
{/if}
|
||||
8
src/routes/logout/+page.server.ts
Normal file
8
src/routes/logout/+page.server.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { deleteSession } from "$lib/server/sessions";
|
||||
import { redirect, type ServerLoad } from "@sveltejs/kit";
|
||||
|
||||
export const load: ServerLoad = async ({ cookies }) => {
|
||||
deleteSession(cookies.get("session"));
|
||||
cookies.delete("session", { path: "/" });
|
||||
redirect(302, "/login");
|
||||
};
|
||||
18
svelte.config.js
Normal file
18
svelte.config.js
Normal file
@ -0,0 +1,18 @@
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://svelte.dev/docs/kit/integrations
|
||||
// for more information about preprocessors
|
||||
preprocess: vitePreprocess(),
|
||||
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler"
|
||||
}
|
||||
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
||||
7
vite.config.ts
Normal file
7
vite.config.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [tailwindcss(), sveltekit()]
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user