Merge pull request #39 from seanmorley15/development

Development
This commit is contained in:
Sean Morley
2024-04-18 19:48:41 -04:00
committed by GitHub
22 changed files with 892 additions and 117 deletions

View File

@@ -10,5 +10,7 @@ _**⚠️ AdventureLog is in early development and is not recommended for produc
2. Edit the `docker-compose.yml` file and change the database password 2. Edit the `docker-compose.yml` file and change the database password
3. Run `docker compose up -d` to build the image and start the container 3. Run `docker compose up -d` to build the image and start the container
4. Wait for the app to start up and migrate then visit the port and enjoy! 4. Wait for the app to start up and migrate then visit the port and enjoy!
5. After navigating to the app, fill out the form to create the admin user.
**Note**: The `ORIGIN` variable is required for CSRF protection. It can be omitted if using a reverse proxy or other HTTPS service. **Note**: The `ORIGIN` variable is required for CSRF protection. It can be omitted if using a reverse proxy or other HTTPS service.

15
compose-dev.yml Normal file
View File

@@ -0,0 +1,15 @@
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=
# ORIGIN is only necessary when not using a reverse proxy or hosting that includes https
- ORIGIN=http://localhost:3000
- SKIP_DB_WAIT=true
# Only necessary for externaly hosted databases such as NeonDB
volumes:
- ./sql:/sql
# docker compose -f ./compose-dev.yml up --build

View File

@@ -7,6 +7,8 @@ services:
- DATABASE_URL=postgres://adventurelog:PO24VjITwGgk@db:5432/adventurelog - DATABASE_URL=postgres://adventurelog:PO24VjITwGgk@db:5432/adventurelog
# ORIGIN is only necessary when not using a reverse proxy or hosting that includes https # ORIGIN is only necessary when not using a reverse proxy or hosting that includes https
- ORIGIN=http://localhost:3000 - ORIGIN=http://localhost:3000
- SKIP_DB_WAIT=false
# Only necessary for externaly hosted databases such as NeonDB
depends_on: depends_on:
- db - db
volumes: volumes:

View File

@@ -0,0 +1,3 @@
ALTER TABLE "user" ADD COLUMN "signup_date" timestamp with time zone NOT NULL;--> statement-breakpoint
ALTER TABLE "user" ADD COLUMN "last_login" timestamp with time zone;--> statement-breakpoint
ALTER TABLE "user" ADD COLUMN "role" text NOT NULL;

View File

@@ -0,0 +1,409 @@
{
"id": "72cc9a9a-a12e-4ca2-b644-b704673af4d7",
"prevId": "91692e84-91ec-4411-ad9d-7b8b14f67dda",
"version": "5",
"dialect": "pg",
"tables": {
"featuredAdventures": {
"name": "featuredAdventures",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"location": {
"name": "location",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"featuredAdventures_name_unique": {
"name": "featuredAdventures_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
}
},
"session": {
"name": "session",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_user_id_user_id_fk": {
"name": "session_user_id_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"sharedAdventures": {
"name": "sharedAdventures",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"data": {
"name": "data",
"type": "json",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"date": {
"name": "date",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"user": {
"name": "user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"first_name": {
"name": "first_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"last_name": {
"name": "last_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false
},
"hashed_password": {
"name": "hashed_password",
"type": "varchar",
"primaryKey": false,
"notNull": true
},
"signup_date": {
"name": "signup_date",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"last_login": {
"name": "last_login",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"userVisitedAdventures": {
"name": "userVisitedAdventures",
"schema": "",
"columns": {
"adventure_id": {
"name": "adventure_id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"adventure_name": {
"name": "adventure_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"location": {
"name": "location",
"type": "text",
"primaryKey": false,
"notNull": false
},
"visited_date": {
"name": "visited_date",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"userVisitedAdventures_user_id_user_id_fk": {
"name": "userVisitedAdventures_user_id_user_id_fk",
"tableFrom": "userVisitedAdventures",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"userVisitedWorldTravel": {
"name": "userVisitedWorldTravel",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"country_code": {
"name": "country_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"region_id": {
"name": "region_id",
"type": "varchar",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"userVisitedWorldTravel_country_code_worldTravelCountries_country_code_fk": {
"name": "userVisitedWorldTravel_country_code_worldTravelCountries_country_code_fk",
"tableFrom": "userVisitedWorldTravel",
"tableTo": "worldTravelCountries",
"columnsFrom": [
"country_code"
],
"columnsTo": [
"country_code"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userVisitedWorldTravel_user_id_user_id_fk": {
"name": "userVisitedWorldTravel_user_id_user_id_fk",
"tableFrom": "userVisitedWorldTravel",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userVisitedWorldTravel_region_id_worldTravelCountryRegions_id_fk": {
"name": "userVisitedWorldTravel_region_id_worldTravelCountryRegions_id_fk",
"tableFrom": "userVisitedWorldTravel",
"tableTo": "worldTravelCountryRegions",
"columnsFrom": [
"region_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"worldTravelCountries": {
"name": "worldTravelCountries",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"country_code": {
"name": "country_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"continent": {
"name": "continent",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"worldTravelCountries_country_code_unique": {
"name": "worldTravelCountries_country_code_unique",
"nullsNotDistinct": false,
"columns": [
"country_code"
]
}
}
},
"worldTravelCountryRegions": {
"name": "worldTravelCountryRegions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "varchar",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"country_code": {
"name": "country_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"info": {
"name": "info",
"type": "json",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"worldTravelCountryRegions_country_code_worldTravelCountries_country_code_fk": {
"name": "worldTravelCountryRegions_country_code_worldTravelCountries_country_code_fk",
"tableFrom": "worldTravelCountryRegions",
"tableTo": "worldTravelCountries",
"columnsFrom": [
"country_code"
],
"columnsTo": [
"country_code"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -22,6 +22,13 @@
"when": 1713125110816, "when": 1713125110816,
"tag": "0002_far_mephistopheles", "tag": "0002_far_mephistopheles",
"breakpoints": true "breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1713402092365,
"tag": "0003_easy_iron_monger",
"breakpoints": true
} }
] ]
} }

167
package-lock.json generated
View File

@@ -1,14 +1,16 @@
{ {
"name": "adventurelog", "name": "adventurelog",
"version": "0.0.1", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "adventurelog", "name": "adventurelog",
"version": "0.0.1", "version": "0.1.0",
"dependencies": { "dependencies": {
"@lucia-auth/adapter-drizzle": "^1.0.7", "@lucia-auth/adapter-drizzle": "^1.0.7",
"@vercel/analytics": "^1.2.2",
"@vercel/speed-insights": "^1.0.10",
"drizzle-orm": "^0.30.6", "drizzle-orm": "^0.30.6",
"oslo": "^1.2.0", "oslo": "^1.2.0",
"postgres": "^3.4.4" "postgres": "^3.4.4"
@@ -52,7 +54,7 @@
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24" "@jridgewell/trace-mapping": "^0.3.24"
@@ -886,7 +888,7 @@
"version": "0.3.5", "version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@jridgewell/set-array": "^1.2.1", "@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/sourcemap-codec": "^1.4.10",
@@ -900,7 +902,7 @@
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
} }
@@ -909,7 +911,7 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
} }
@@ -918,13 +920,13 @@
"version": "1.4.15", "version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true "devOptional": true
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25", "version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14" "@jridgewell/sourcemap-codec": "^1.4.14"
@@ -1529,7 +1531,7 @@
"version": "1.0.0-next.25", "version": "1.0.0-next.25",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz",
"integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==",
"dev": true "devOptional": true
}, },
"node_modules/@rollup/plugin-commonjs": { "node_modules/@rollup/plugin-commonjs": {
"version": "25.0.7", "version": "25.0.7",
@@ -2329,7 +2331,7 @@
"version": "2.5.5", "version": "2.5.5",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.5.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.5.tgz",
"integrity": "sha512-ULe3PB00q4+wYRL+IS5FDPsCEVnhEITofm7b9Yz8malcH3r1SAnW/JJ6T13hIMeu8QNRIuVQWo+P4+2VklbnLQ==", "integrity": "sha512-ULe3PB00q4+wYRL+IS5FDPsCEVnhEITofm7b9Yz8malcH3r1SAnW/JJ6T13hIMeu8QNRIuVQWo+P4+2VklbnLQ==",
"dev": true, "devOptional": true,
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@types/cookie": "^0.6.0", "@types/cookie": "^0.6.0",
@@ -2361,7 +2363,7 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.0.2.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.0.2.tgz",
"integrity": "sha512-MpmF/cju2HqUls50WyTHQBZUV3ovV/Uk8k66AN2gwHogNAG8wnW8xtZDhzNBsFJJuvmq1qnzA5kE7YfMJNFv2Q==", "integrity": "sha512-MpmF/cju2HqUls50WyTHQBZUV3ovV/Uk8k66AN2gwHogNAG8wnW8xtZDhzNBsFJJuvmq1qnzA5kE7YfMJNFv2Q==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^2.0.0", "@sveltejs/vite-plugin-svelte-inspector": "^2.0.0",
"debug": "^4.3.4", "debug": "^4.3.4",
@@ -2383,7 +2385,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.0.0.tgz",
"integrity": "sha512-gjr9ZFg1BSlIpfZ4PRewigrvYmHWbDrq2uvvPB1AmTWKuM+dI1JXQSUu2pIrYLb/QncyiIGkFDFKTwJ0XqQZZg==", "integrity": "sha512-gjr9ZFg1BSlIpfZ4PRewigrvYmHWbDrq2uvvPB1AmTWKuM+dI1JXQSUu2pIrYLb/QncyiIGkFDFKTwJ0XqQZZg==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
@@ -2437,13 +2439,13 @@
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
"dev": true "devOptional": true
}, },
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true "devOptional": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.12.3", "version": "20.12.3",
@@ -2534,6 +2536,26 @@
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
"dev": true "dev": true
}, },
"node_modules/@vercel/analytics": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.2.2.tgz",
"integrity": "sha512-X0rctVWkQV1e5Y300ehVNqpOfSOufo7ieA5PIdna8yX/U7Vjz0GFsGf4qvAhxV02uQ2CVt7GYcrFfddXXK2Y4A==",
"dependencies": {
"server-only": "^0.0.1"
},
"peerDependencies": {
"next": ">= 13",
"react": "^18 || ^19"
},
"peerDependenciesMeta": {
"next": {
"optional": true
},
"react": {
"optional": true
}
}
},
"node_modules/@vercel/nft": { "node_modules/@vercel/nft": {
"version": "0.26.4", "version": "0.26.4",
"resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz", "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz",
@@ -2588,6 +2610,40 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/@vercel/speed-insights": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@vercel/speed-insights/-/speed-insights-1.0.10.tgz",
"integrity": "sha512-4uzdKB0RW6Ff2FkzshzjZ+RlJfLPxgm/00i0XXgxfMPhwnnsk92YgtqsxT9OcPLdJUyVU1DqFlSWWjIQMPkh0g==",
"hasInstallScript": true,
"peerDependencies": {
"@sveltejs/kit": "^1 || ^2",
"next": ">= 13",
"react": "^18 || ^19",
"svelte": "^4",
"vue": "^3",
"vue-router": "^4"
},
"peerDependenciesMeta": {
"@sveltejs/kit": {
"optional": true
},
"next": {
"optional": true
},
"react": {
"optional": true
},
"svelte": {
"optional": true
},
"vue": {
"optional": true
},
"vue-router": {
"optional": true
}
}
},
"node_modules/abbrev": { "node_modules/abbrev": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -2598,7 +2654,7 @@
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true, "devOptional": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -2699,7 +2755,7 @@
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"dequal": "^2.0.3" "dequal": "^2.0.3"
} }
@@ -2751,7 +2807,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz",
"integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"dequal": "^2.0.3" "dequal": "^2.0.3"
} }
@@ -2979,7 +3035,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz",
"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15", "@jridgewell/sourcemap-codec": "^1.4.15",
"@types/estree": "^1.0.1", "@types/estree": "^1.0.1",
@@ -3046,7 +3102,7 @@
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@@ -3094,7 +3150,7 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"mdn-data": "2.0.30", "mdn-data": "2.0.30",
"source-map-js": "^1.0.1" "source-map-js": "^1.0.1"
@@ -3160,7 +3216,7 @@
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
}, },
@@ -3177,7 +3233,7 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -3192,7 +3248,7 @@
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -3219,7 +3275,7 @@
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.2.tgz", "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.2.tgz",
"integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==", "integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==",
"dev": true "devOptional": true
}, },
"node_modules/didyoumean": { "node_modules/didyoumean": {
"version": "1.2.2", "version": "1.2.2",
@@ -3965,7 +4021,7 @@
"version": "0.20.2", "version": "0.20.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
"dev": true, "devOptional": true,
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"esbuild": "bin/esbuild" "esbuild": "bin/esbuild"
@@ -4024,7 +4080,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==", "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
"dev": true "devOptional": true
}, },
"node_modules/esniff": { "node_modules/esniff": {
"version": "2.0.1", "version": "2.0.1",
@@ -4045,7 +4101,7 @@
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/estree": "^1.0.0" "@types/estree": "^1.0.0"
} }
@@ -4321,13 +4377,13 @@
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
"dev": true "devOptional": true
}, },
"node_modules/globrex": { "node_modules/globrex": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true "devOptional": true
}, },
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.11", "version": "4.2.11",
@@ -4402,7 +4458,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
"integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==",
"dev": true, "devOptional": true,
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
@@ -4518,7 +4574,7 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/estree": "*" "@types/estree": "*"
} }
@@ -4589,7 +4645,7 @@
"version": "4.1.5", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -4613,7 +4669,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"dev": true "devOptional": true
}, },
"node_modules/lodash.castarray": { "node_modules/lodash.castarray": {
"version": "4.4.0", "version": "4.4.0",
@@ -5150,7 +5206,7 @@
"version": "0.30.8", "version": "0.30.8",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
"integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15" "@jridgewell/sourcemap-codec": "^1.4.15"
}, },
@@ -5186,7 +5242,7 @@
"version": "2.0.30", "version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"dev": true "devOptional": true
}, },
"node_modules/memfs": { "node_modules/memfs": {
"version": "3.5.3", "version": "3.5.3",
@@ -5327,7 +5383,7 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=4" "node": ">=4"
} }
@@ -5336,7 +5392,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
"integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=10" "node": ">=10"
} }
@@ -5345,7 +5401,7 @@
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "devOptional": true
}, },
"node_modules/mz": { "node_modules/mz": {
"version": "2.7.0", "version": "2.7.0",
@@ -5362,7 +5418,7 @@
"version": "3.3.7", "version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true, "devOptional": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -5562,7 +5618,7 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/estree": "^1.0.0", "@types/estree": "^1.0.0",
"estree-walker": "^3.0.0", "estree-walker": "^3.0.0",
@@ -5671,7 +5727,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true "devOptional": true
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.1",
@@ -5707,7 +5763,7 @@
"version": "8.4.38", "version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"dev": true, "devOptional": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -6025,7 +6081,7 @@
"version": "4.13.2", "version": "4.13.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.2.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.2.tgz",
"integrity": "sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==", "integrity": "sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/estree": "1.0.5" "@types/estree": "1.0.5"
}, },
@@ -6082,7 +6138,7 @@
"version": "1.8.1", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
"integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"mri": "^1.1.0" "mri": "^1.1.0"
}, },
@@ -6149,6 +6205,11 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/server-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz",
"integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="
},
"node_modules/set-blocking": { "node_modules/set-blocking": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
@@ -6159,7 +6220,7 @@
"version": "2.6.0", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
"integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==",
"dev": true "devOptional": true
}, },
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
@@ -6198,7 +6259,7 @@
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@polka/url": "^1.0.0-next.24", "@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0", "mrmime": "^2.0.0",
@@ -6242,7 +6303,7 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -6479,7 +6540,7 @@
"version": "4.2.12", "version": "4.2.12",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz", "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz",
"integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==", "integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.1", "@ampproject/remapping": "^2.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15", "@jridgewell/sourcemap-codec": "^1.4.15",
@@ -6526,7 +6587,7 @@
"version": "0.15.3", "version": "0.15.3",
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz",
"integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==", "integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": "^12.20 || ^14.13.1 || >= 16" "node": "^12.20 || ^14.13.1 || >= 16"
}, },
@@ -6719,7 +6780,7 @@
"version": "0.2.9", "version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"globalyzer": "0.1.0", "globalyzer": "0.1.0",
"globrex": "^0.1.2" "globrex": "^0.1.2"
@@ -6741,7 +6802,7 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
"dev": true, "devOptional": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -6829,7 +6890,7 @@
"version": "5.2.7", "version": "5.2.7",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.7.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.7.tgz",
"integrity": "sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==", "integrity": "sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"esbuild": "^0.20.1", "esbuild": "^0.20.1",
"postcss": "^8.4.38", "postcss": "^8.4.38",
@@ -6884,7 +6945,7 @@
"version": "0.2.5", "version": "0.2.5",
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz",
"integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==",
"dev": true, "devOptional": true,
"peerDependencies": { "peerDependencies": {
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0" "vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
}, },

View File

@@ -39,6 +39,8 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@lucia-auth/adapter-drizzle": "^1.0.7", "@lucia-auth/adapter-drizzle": "^1.0.7",
"@vercel/analytics": "^1.2.2",
"@vercel/speed-insights": "^1.0.10",
"drizzle-orm": "^0.30.6", "drizzle-orm": "^0.30.6",
"oslo": "^1.2.0", "oslo": "^1.2.0",
"postgres": "^3.4.4" "postgres": "^3.4.4"

1
src/app.d.ts vendored
View File

@@ -3,6 +3,7 @@ declare global {
interface Locals { interface Locals {
user: import("lucia").User | null; user: import("lucia").User | null;
session: import("lucia").Session | null; session: import("lucia").Session | null;
isServerSetup: boolean | null;
} }
} }
} }

View File

@@ -1,6 +1,9 @@
import { lucia } from "$lib/server/auth"; import { lucia } from "$lib/server/auth";
import type { Handle } from "@sveltejs/kit"; import { redirect, type Handle } from "@sveltejs/kit";
import { sequence } from '@sveltejs/kit/hooks'; import { sequence } from '@sveltejs/kit/hooks';
import { db } from "$lib/db/db.server";
import { userTable } from "$lib/db/schema";
import { eq } from "drizzle-orm";
export const authHook: Handle = async ({ event, resolve }) => { export const authHook: Handle = async ({ event, resolve }) => {
const sessionId = event.cookies.get(lucia.sessionCookieName); const sessionId = event.cookies.get(lucia.sessionCookieName);
@@ -53,4 +56,27 @@ export const themeHook: Handle = async ({ event, resolve }) => {
return await resolve(event); return await resolve(event);
} }
export const handle = sequence(authHook, themeHook); export const setupAdminUser: Handle = async ({ event, resolve }) => {
// Check if an admin user exists
/* let result = await db
.select()
.from(userVisitedAdventures)
.where(eq(userVisitedAdventures.userId, event.locals.user.id))
.execute();*/
let adminUser = await db
.select()
.from(userTable)
.where(eq(userTable.role, 'admin'))
.execute();
// If an admin user exists, return the resolved event
if (adminUser != null && adminUser.length > 0) {
event.locals.isServerSetup = true;
return await resolve(event);
}
console.log("No admin user found");
event.locals.isServerSetup = false;
return await resolve(event);
};
export const handle = sequence(setupAdminUser, authHook, themeHook);

View File

@@ -36,7 +36,12 @@
<p class="text-lg ml-4 font-bold">Hi, {user.first_name} {user.last_name}</p> <p class="text-lg ml-4 font-bold">Hi, {user.first_name} {user.last_name}</p>
<li><a>Profile</a></li> <li><a>Profile</a></li>
<li><button on:click={navToLog}>My Log</button></li> <li><button on:click={navToLog}>My Log</button></li>
<li><button on:click={navToSettings}>Settings</button></li> <li><button on:click={navToSettings}>User Settings</button></li>
{#if user.role == "admin"}
<li>
<button on:click={() => goto("/settings/admin")}>Admin Settings</button>
</li>
{/if}
<form method="post"> <form method="post">
<li><button formaction="/?/logout">Logout</button></li> <li><button formaction="/?/logout">Logout</button></li>
</form> </form>

View File

@@ -28,6 +28,15 @@ export const userTable = pgTable("user", {
last_name: text("last_name").notNull(), last_name: text("last_name").notNull(),
icon: text("icon"), icon: text("icon"),
hashed_password: varchar("hashed_password").notNull(), hashed_password: varchar("hashed_password").notNull(),
signup_date: timestamp("signup_date", {
withTimezone: true,
mode: "date",
}).notNull(),
last_login: timestamp("last_login", {
withTimezone: true,
mode: "date",
}),
role: text("role").notNull(),
}); });
// export type SelectUser = typeof userTable.$inferSelect; // export type SelectUser = typeof userTable.$inferSelect;

View File

@@ -20,6 +20,9 @@ export const lucia = new Lucia(adapter, {
first_name: attributes.first_name, first_name: attributes.first_name,
last_name: attributes.last_name, last_name: attributes.last_name,
icon: attributes.icon, icon: attributes.icon,
signup_date: attributes.signup_date,
last_login: attributes.last_login,
role: attributes.role,
}; };
}, },
}); });
@@ -38,4 +41,7 @@ export interface DatabaseUser {
last_name: string; last_name: string;
icon: string; icon: string;
hashed_password: string; hashed_password: string;
signup_date: Date;
last_login: Date;
role: string;
} }

View File

@@ -1,12 +1,21 @@
import type { LayoutServerLoad, PageServerLoad } from "./$types"; import type { LayoutServerLoad, PageServerLoad } from "./$types";
import { inject } from "@vercel/analytics";
import { injectSpeedInsights } from "@vercel/speed-insights/sveltekit";
if (process.env.USING_VERCEL === "true") {
inject();
injectSpeedInsights();
}
export const load: LayoutServerLoad = async (event) => { export const load: LayoutServerLoad = async (event) => {
if (event.locals.user) { if (event.locals.user) {
return { return {
user: event.locals.user, user: event.locals.user,
isServerSetup: event.locals.isServerSetup,
}; };
} }
return { return {
user: null, user: null,
isServerSetup: event.locals.isServerSetup,
}; };
}; };

View File

@@ -4,6 +4,21 @@
import Navbar from "$lib/components/Navbar.svelte"; import Navbar from "$lib/components/Navbar.svelte";
import type { SubmitFunction } from "@sveltejs/kit"; import type { SubmitFunction } from "@sveltejs/kit";
import "../app.css"; import "../app.css";
import { goto } from "$app/navigation";
import { onMount } from "svelte";
import { page } from "$app/stores";
let isServerSetup = data.isServerSetup;
onMount(() => {
console.log("isServerSetup", isServerSetup);
if (!isServerSetup && $page.url.pathname !== "/setup") {
goto("/setup");
}
if (isServerSetup && $page.url.pathname == "/setup") {
goto("/");
}
});
</script> </script>
<!-- passes the user object to the navbar component --> <!-- passes the user object to the navbar component -->

View File

@@ -47,7 +47,7 @@ export const actions: Actions = {
}); });
} }
const existingUser = await db const existingUser:any = await db
.select() .select()
.from(userTable) .from(userTable)
.where(eq(userTable.username, username)) .where(eq(userTable.username, username))
@@ -70,6 +70,14 @@ export const actions: Actions = {
}); });
} }
await db
.update(userTable)
.set({
last_login: new Date(),
})
.where(eq(userTable.id, existingUser.id))
.execute();
const session = await lucia.createSession(existingUser.id, {}); const session = await lucia.createSession(existingUser.id, {});
const sessionCookie = lucia.createSessionCookie(session.id); const sessionCookie = lucia.createSessionCookie(session.id);
event.cookies.set(sessionCookie.name, sessionCookie.value, { event.cookies.set(sessionCookie.name, sessionCookie.value, {

View File

@@ -4,6 +4,7 @@ import { db } from "$lib/db/db.server";
import { userTable } from "$lib/db/schema"; import { userTable } from "$lib/db/schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { Argon2id } from "oslo/password"; import { Argon2id } from "oslo/password";
import type { DatabaseUser } from "$lib/server/auth";
export const load: PageServerLoad = async (event) => { export const load: PageServerLoad = async (event) => {
if (event.locals.user) if (event.locals.user)
@@ -42,6 +43,22 @@ export const actions: Actions = {
}; };
} }
const usernameTaken = await db
.select()
.from(userTable)
.where(eq(userTable.username, username))
.limit(1)
.then((results) => results[0] as unknown as DatabaseUser | undefined);
if (usernameTaken) {
return {
status: 400,
body: {
message: "Username taken!"
}
};
}
if (password) { if (password) {
let hashedPassword = await new Argon2id().hash(password); let hashedPassword = await new Argon2id().hash(password);
console.log(hashedPassword) console.log(hashedPassword)

View File

@@ -1,5 +1,6 @@
<script> <script>
import { enhance } from "$app/forms"; import { enhance } from "$app/forms";
import AdventureCard from "$lib/components/AdventureCard.svelte";
export let data; export let data;
let username = data.user?.username; let username = data.user?.username;
@@ -7,12 +8,13 @@
let last_name = data.user?.last_name; let last_name = data.user?.last_name;
let user_id = data.user?.id; let user_id = data.user?.id;
let icon = data.user?.icon; let icon = data.user?.icon;
let signup_date = data.user?.signup_date;
let role = data.user?.role;
</script> </script>
<h1 class="text-center font-extrabold text-4xl mb-6">Settings Page</h1> <h1 class="text-center font-extrabold text-4xl mb-6">Settings Page</h1>
<h1 class="text-center font-extrabold text-xl">User Account Settings</h1> <h1 class="text-center font-extrabold text-xl">User Account Settings</h1>
<div class="flex justify-center"> <div class="flex justify-center">
<form method="post" use:enhance class="w-full max-w-xs"> <form method="post" use:enhance class="w-full max-w-xs">
<label for="username">Username</label> <label for="username">Username</label>
@@ -65,4 +67,6 @@
</form> </form>
</div> </div>
<small class="text-center">For Debug Use: UUID={user_id}</small> <small class="text-center"
><b>For Debug Use:</b> UUID={user_id} Signup Date={signup_date} Role={role}</small
>

View File

@@ -0,0 +1,121 @@
// routes/signup/+page.server.ts
import { lucia } from "$lib/server/auth";
import { fail, redirect } from "@sveltejs/kit";
import { generateId } from "lucia";
import { Argon2id } from "oslo/password";
import { db } from "$lib/db/db.server";
import type { DatabaseUser } from "$lib/server/auth";
import type { Actions } from "./$types";
import { userTable } from "$lib/db/schema";
import { eq } from "drizzle-orm";
export const actions: Actions = {
default: async (event) => {
const formData = await event.request.formData();
const username = formData.get("username");
const password = formData.get("password");
const firstName = formData.get("first_name");
const lastName = formData.get("last_name");
// username must be between 4 ~ 31 characters, and only consists of lowercase letters, 0-9, -, and _
// keep in mind some database (e.g. mysql) are case insensitive
// check all to make sure all fields are provided
if (!username || !password || !firstName || !lastName) {
return fail(400, {
message: "All fields are required",
});
}
if (
typeof username !== "string" ||
username.length < 3 ||
username.length > 31 ||
!/^[a-z0-9_-]+$/.test(username)
) {
return fail(400, {
message: "Invalid username",
});
}
if (
typeof password !== "string" ||
password.length < 6 ||
password.length > 255
) {
return fail(400, {
message: "Invalid password",
});
}
if (
typeof firstName !== "string" ||
firstName.length < 1 ||
firstName.length > 255
) {
return fail(400, {
message: "Invalid first name",
});
}
if (
typeof lastName !== "string" ||
lastName.length < 1 ||
lastName.length > 255
) {
return fail(400, {
message: "Invalid last name",
});
}
const userId = generateId(15);
const hashedPassword = await new Argon2id().hash(password);
const usernameTaken = await db
.select()
.from(userTable)
.where(eq(userTable.username, username))
.limit(1)
.then((results) => results[0] as unknown as DatabaseUser | undefined);
if (usernameTaken) {
return fail(400, {
message: "Username already taken",
});
}
let adminUser = await db
.select()
.from(userTable)
.where(eq(userTable.role, 'admin'))
.execute();
if (adminUser != null && adminUser.length > 0) {
return fail(400, {
message: "Admin user already exists",
});
}
await db
.insert(userTable)
.values({
id: userId,
username: username,
first_name: firstName,
last_name: lastName,
hashed_password: hashedPassword,
signup_date: new Date(),
role: "admin",
last_login: new Date(),
} as DatabaseUser)
.execute();
const session = await lucia.createSession(userId, {});
const sessionCookie = lucia.createSessionCookie(session.id);
event.cookies.set(sessionCookie.name, sessionCookie.value, {
path: ".",
...sessionCookie.attributes,
});
redirect(302, "/");
},
};

View File

@@ -0,0 +1,44 @@
<script lang="ts">
import { enhance } from "$app/forms";
</script>
<h1 class="text-center font-bold text-4xl">AdventureLog Setup</h1>
<!-- centered text descripton welcomeing the user -->
<p class="text-center mt-4">
Welcome to AdventureLog! Please follow the steps below to setup your server.
</p>
<!-- step 1 create admin user -->
<h2 class="text-center font-bold text-2xl mt-6">Create Admin User</h2>
<div class="flex justify-center">
<form method="post" use:enhance class="w-full max-w-xs">
<label for="username">Username</label>
<input
name="username"
id="username"
class="block mb-2 input input-bordered w-full max-w-xs"
/><br />
<label for="first_name">First Name</label>
<input
name="first_name"
id="first_name"
class="block mb-2 input input-bordered w-full max-w-xs"
/><br />
<label for="last_name">Last Name</label>
<input
name="last_name"
id="last_name"
class="block mb-2 input input-bordered w-full max-w-xs"
/><br />
<label for="password">Password</label>
<input
type="password"
name="password"
id="password"
class="block mb-2 input input-bordered w-full max-w-xs"
/><br />
<button class="py-2 px-4 btn btn-primary">Signup</button>
</form>
</div>

View File

@@ -90,6 +90,9 @@ export const actions: Actions = {
first_name: firstName, first_name: firstName,
last_name: lastName, last_name: lastName,
hashed_password: hashedPassword, hashed_password: hashedPassword,
signup_date: new Date(),
role: "user",
last_login: new Date(),
} as DatabaseUser) } as DatabaseUser)
.execute(); .execute();

View File

@@ -24,12 +24,18 @@ run_sql_scripts() {
echo "Finished running SQL scripts." echo "Finished running SQL scripts."
} }
# Start your application here # Start your application here
# Print message # Print message
echo "Starting AdventureLog" echo "Starting AdventureLog"
# Wait for the database to start up # Wait for the database to start up
if [ -z "$SKIP_DB_WAIT" ] || [ "$SKIP_DB_WAIT" = "false" ]; then
wait_for_db wait_for_db
fi
# Wait for the database to start up
# generate the schema # generate the schema
# npm run generate # npm run generate