diff --git a/asset-api/index.js b/asset-api/index.js
index ee553d6..43b8816 100644
--- a/asset-api/index.js
+++ b/asset-api/index.js
@@ -60,8 +60,8 @@ app.get("/crypto/algo", () => {
app.put("/asset", {
async handler(request, reply) {
- let user = await userFromSessionKey(request.query.session_key);
- if (user.assets.length >= user.limits.assetCount) {
+ let { user, limits } = await userFromSessionKey(request.query.session_key);
+ if (user.assets.length >= limits.maxAssetCount) {
reply.code(403);
return "Max asset count reached. Contact support or upgrade your plan";
}
@@ -102,7 +102,7 @@ app.put("/asset", {
app.get("/asset", {
async handler(request, reply) {
- let user = await userFromSessionKey(request.query.session_key);
+ let { user, limits } = await userFromSessionKey(request.query.session_key);
if ('statusCode' in user) {
reply.code(500);
diff --git a/identity-api/.env.example b/identity-api/.env.example
index 5699528..e1d5eec 100644
--- a/identity-api/.env.example
+++ b/identity-api/.env.example
@@ -2,4 +2,5 @@ IDENTITY_API_LANDING_MESSAGE = "identity-api v1.0.0"
IDENTITY_API_JWT_SECRET = "cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2"
IDENTITY_API_JWT_ALG = "HS256"
IDENTITY_API_ASSET_API_ENDPOINT = "http://localhost:3001"
-IDENTITY_API_ASSET_API_M2M_REFRESH_INTERVAL_MS = 60000
\ No newline at end of file
+IDENTITY_API_ASSET_API_M2M_REFRESH_INTERVAL_MS = 60000
+IDENTITY_SQLITE_PATH = ".database/identity.sqlite"
\ No newline at end of file
diff --git a/identity-api/.gitignore b/identity-api/.gitignore
index 94bf562..b2f3032 100644
--- a/identity-api/.gitignore
+++ b/identity-api/.gitignore
@@ -1,3 +1,5 @@
node_modules/
+dist/
.yarn
-.env
\ No newline at end of file
+.env
+.database
\ No newline at end of file
diff --git a/identity-api/docs/database/schema.dbml b/identity-api/docs/database/schema.dbml
new file mode 100644
index 0000000..7d65005
--- /dev/null
+++ b/identity-api/docs/database/schema.dbml
@@ -0,0 +1,76 @@
+// You can render this DBML file using specialized software or websites such as:
+// https://dbdiagram.io/
+
+Table limits {
+ id varchar [primary key]
+ current_asset_count integer [not null]
+ max_asset_count integer [not null]
+}
+
+Table users {
+ id varchar [primary key]
+ created_at timestamp [not null]
+ last_connected_at timestamp [not null]
+ email varchar [not null]
+ password varchar [not null]
+ name varchar [not null]
+ limits varchar [not null]
+ assets varchar [not null, note: 'Comma separated list']
+}
+
+Table session_keys {
+ key varchar [primary key]
+ user_id varchar [not null]
+}
+
+Table heirs {
+ id varchar [primary key]
+ user_id varchar [not null]
+ created_at timestamp [not null]
+ name varchar [not null]
+ email varchar
+}
+
+Table entries {
+ id varchar [primary key]
+ user_id varchar [not null]
+ created_at timestamp [not null]
+ feelings text [not null, note: 'Comma separated JSON-encoded list']
+ assets text [not null, note: 'Comma separated list']
+ title text
+ description text
+
+ kind varchar [not null, note: 'Kind of entry']
+ music_entry varchar
+ location_entry varchar
+ date_entry varchar
+}
+
+Table music_entries {
+ id varchar [primary key]
+ artist varchar [not null]
+ title varchar [not null]
+ links text [not null, note: 'Comma separated list']
+ universal_ids text [not null, note: 'Comma separated JSON-encoded list of Universal IDs']
+}
+
+Table location_entries {
+ id varchar [primary key]
+ location_text text
+ location_coordinates varchar [note: 'JSON encoded location']
+}
+
+Table date_entries {
+ id varchar [primary key]
+ referenced_date timestamp
+}
+
+Ref: users.limits > limits.id
+
+Ref: heirs.user_id > users.id
+Ref: entries.user_id > users.id
+Ref: session_keys.user_id > users.id
+
+Ref: entries.music_entry > music_entries.id
+Ref: entries.location_entry > location_entries.id
+Ref: entries.date_entry > date_entries.id
\ No newline at end of file
diff --git a/identity-api/package.json b/identity-api/package.json
index 43ca908..73b7297 100644
--- a/identity-api/package.json
+++ b/identity-api/package.json
@@ -8,19 +8,26 @@
"packageManager": "yarn@4.3.0",
"dependencies": {
"@fastify/cors": "^9.0.1",
+ "@fastify/type-provider-typebox": "^4.0.0",
+ "@sinclair/typebox": "^0.32.34",
+ "argon2": "^0.40.3",
+ "better-sqlite3": "^11.1.1",
"dotenv": "^16.4.5",
+ "drizzle-orm": "^0.31.2",
"fastify": "^4.27.0",
"jose": "^5.4.0"
},
"scripts": {
- "start": "node src/index.js",
+ "start": "tsc && node dist/index.js",
"lint:fix": "eslint --fix && prettier . --write",
"lint": "eslint && prettier . --check"
},
"devDependencies": {
"@eslint/js": "^9.5.0",
+ "@types/node": "^20.14.9",
"eslint": "9.x",
"globals": "^15.5.0",
- "prettier": "3.3.2"
+ "prettier": "3.3.2",
+ "typescript": "^5.5.2"
}
}
diff --git a/identity-api/src/app.js b/identity-api/src/app.ts
similarity index 80%
rename from identity-api/src/app.js
rename to identity-api/src/app.ts
index 6044e24..9d364e8 100644
--- a/identity-api/src/app.js
+++ b/identity-api/src/app.ts
@@ -14,8 +14,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
import Fastify from "fastify";
-export default Fastify({
+let app = Fastify({
logger: true,
-});
+}).withTypeProvider()
+
+export type AppInterface = typeof app;
+export default app;
diff --git a/identity-api/src/auth.js b/identity-api/src/auth.js
deleted file mode 100644
index 6610b15..0000000
--- a/identity-api/src/auth.js
+++ /dev/null
@@ -1,101 +0,0 @@
-// Identity. Store your memories and mental belongings
-// Copyright (C) 2024 Sofía Aritz
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published
-// by the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-import assert from "node:assert";
-import { randomUUID } from "node:crypto";
-import * as Jose from "jose";
-import { JWT_ALG, JWT_SECRET } from "./consts.js";
-
-export async function startAuth() {
- let session_keys = {
- "uid:005d6417-a23c-48bd-b348-eafeae649b94": "e381ba8c-e18a-4bca-afce-b212b37bc26b",
- "key:e381ba8c-e18a-4bca-afce-b212b37bc26b": "005d6417-a23c-48bd-b348-eafeae649b94",
- };
-
- let users = {
- "jane@identity.net": {
- uid: "005d6417-a23c-48bd-b348-eafeae649b94",
- email: "jane@identity.net",
- password: "12345678901234567890",
- name: "Jane Doe",
- assets: ["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"],
- limits: {
- assetCount: 5,
- },
- heirs: [
- {
- contactMethod: "email",
- name: "Sofía Aritz",
- value: "sofi@sofiaritz.com",
- },
- ],
- entries: JSON.parse(
- `[{"id":"0","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0a","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1a","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2a","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3a","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4a","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5a","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6a","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0b","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1b","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2b","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3b","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4b","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5b","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6b","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0c","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1c","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2c","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3c","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4c","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5c","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6c","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0d","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1d","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2d","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3d","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4d","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5d","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6d","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0e","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1e","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2e","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3e","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4e","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5e","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6e","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0f","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1f","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2f","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3f","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4f","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5f","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6f","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0g","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1g","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2g","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3g","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4g","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5g","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6g","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]}]`,
- ),
- },
- };
-
- let funcs = {
- user: async (uid) => {
- let user = Object.values(users).filter((v) => v.uid === uid);
- assert(user.length <= 1);
-
- return structuredClone(user[0]);
- },
- findUserByEmail: async (email) => {
- return structuredClone(users[email]);
- },
- findUserBySessionKey: async (session_key) => {
- let uid = session_keys[`key:${session_key}`];
- return await funcs.user(uid);
- },
- updateUser: async (uid, newUser) => {
- let user = await funcs.user(uid);
- users[user.email] = newUser;
- },
- addUser: async (user) => {
- user.uid = randomUUID().toString();
- users[user.email] = user;
-
- return structuredClone(users[user.email]);
- },
- createSessionKey: async (uid) => {
- let key = randomUUID().toString();
- session_keys[`uid:${uid}`] = key;
- session_keys[`key:${key}`] = uid;
-
- return key;
- },
- createJwt: async (uid) => {
- let user = await funcs.user(uid);
-
- return await new Jose.SignJWT({
- uid: user.uid,
- email: user.email,
- name: user.name,
- })
- .setProtectedHeader({ alg: JWT_ALG })
- .setIssuedAt()
- .setExpirationTime("4w")
- .sign(JWT_SECRET);
- },
- verifyJwt: async (jwt) => {
- return await Jose.jwtVerify(jwt, JWT_SECRET);
- },
- };
-
- return funcs;
-}
diff --git a/identity-api/src/auth.ts b/identity-api/src/auth.ts
new file mode 100644
index 0000000..ab1ea0b
--- /dev/null
+++ b/identity-api/src/auth.ts
@@ -0,0 +1,121 @@
+// Identity. Store your memories and mental belongings
+// Copyright (C) 2024 Sofía Aritz
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import * as argon2 from "argon2";
+import { randomUUID } from "node:crypto";
+import * as Jose from "jose";
+import { JWT_ALG, JWT_SECRET } from "./consts.js";
+import { DatabaseInterface, toDBList } from "./database.js";
+
+
+export type AuthInterface = Awaited>;
+
+export type User = {
+ id: string,
+ createdAt: number,
+ lastConnected: number,
+ name: string,
+ email: string,
+ password: string,
+ limitID: string,
+}
+
+export type NewUser = {
+ name: string,
+ email: string,
+ password: string,
+}
+
+export type UpdateUser = {
+ name?: string,
+ email?: string,
+ password?: string,
+ assets?: string[],
+}
+
+export async function startAuth(database: DatabaseInterface) {
+ let funcs = {
+ user: async (uid: string) => await database.user(uid) satisfies User,
+ findUserByEmail: async (email: string) => await database.findUserByEmail(email) satisfies User,
+ findUserBySessionKey: async (sessionKey: string) => {
+ let key = await database.sessionKey(sessionKey);
+ return await database.user(key.userID);
+ },
+ updateUser: async (uid: string, newUser: UpdateUser) => {
+ let user = newUser as any;
+ user.assets = toDBList(user.assets);
+
+ return await database.updateUser(uid, user);
+ },
+ addUser: async (user: NewUser) => {
+ let result = await database.insertUser({
+ id: randomUUID(),
+ createdAt: Date.now(),
+ lastConnected: Date.now(),
+ name: user.name,
+ email: user.email,
+ password: await argon2.hash(user.password),
+ assets: toDBList([]),
+ // FIXME: This shouldn't be required, the DB interface overwrites it.
+ limitID: "",
+ }, {
+ id: randomUUID(),
+ currentAssetCount: 0,
+ maxAssetCount: 5,
+ });
+
+ return result satisfies User;
+ },
+ verifyPassword: async (user: User, password: string) => {
+ return await argon2.verify(user.password, password);
+ },
+ createSessionKey: async (uid) => {
+ return await database.insertSessionKey({
+ userID: uid,
+ key: randomUUID(),
+ });
+ },
+ createJwt: async (uid) => {
+ let user = await funcs.user(uid);
+
+ return await new Jose.SignJWT({
+ uid: user.id,
+ email: user.email,
+ name: user.name,
+ })
+ .setProtectedHeader({ alg: JWT_ALG })
+ .setIssuedAt()
+ .setExpirationTime("4w")
+ .sign(JWT_SECRET);
+ },
+ verifyJwt: async (jwt) => {
+ return await Jose.jwtVerify<{
+ uid: string,
+ email: string,
+ name: string,
+ }>(jwt, JWT_SECRET);
+ },
+ cleanUser: (user: User) => {
+ let clean = user as any;
+ clean.password = undefined;
+ clean.limitID = undefined;
+
+ return clean;
+ }
+ };
+
+ return funcs;
+}
diff --git a/identity-api/src/consts.js b/identity-api/src/consts.ts
similarity index 79%
rename from identity-api/src/consts.js
rename to identity-api/src/consts.ts
index 291da48..fb56113 100644
--- a/identity-api/src/consts.js
+++ b/identity-api/src/consts.ts
@@ -17,7 +17,12 @@
import "dotenv/config";
import app from "./app.js";
-const REQUIRED_VARS = ["IDENTITY_API_JWT_SECRET", "IDENTITY_API_ASSET_API_ENDPOINT", "IDENTITY_API_JWT_ALG"];
+const REQUIRED_VARS = [
+ "IDENTITY_API_JWT_SECRET",
+ "IDENTITY_API_ASSET_API_ENDPOINT",
+ "IDENTITY_API_JWT_ALG",
+ "IDENTITY_SQLITE_PATH",
+];
REQUIRED_VARS.forEach((element) => {
if (
@@ -32,7 +37,8 @@ REQUIRED_VARS.forEach((element) => {
export const IDENTITY_API_LANDING_MESSAGE = process.env["IDENTITY_API_LANDING_MESSAGE"] || "identity-api v1.0.0";
export const JWT_SECRET = new TextEncoder().encode(process.env["IDENTITY_API_JWT_SECRET"]);
export const JWT_ALG = process.env["IDENTITY_API_JWT_ALG"];
-export const LISTEN_PORT = process.env["IDENTITY_API_LISTEN_PORT"] || 3000;
+export const LISTEN_PORT = Number(process.env["IDENTITY_API_LISTEN_PORT"]) || 3000;
export const ASSET_API_ENDPOINT = process.env["IDENTITY_API_ASSET_API_ENDPOINT"];
export const ASSET_API_M2M_REFRESH_INTERVAL =
- process.env["IDENTITY_API_ASSET_API_M2M_REFRESH_INTERVAL_MS"] || 60 * 1000;
+ Number(process.env["IDENTITY_API_ASSET_API_M2M_REFRESH_INTERVAL_MS"]) || 60 * 1000;
+export const SQLITE_PATH = process.env["IDENTITY_SQLITE_PATH"];
diff --git a/identity-api/src/database.ts b/identity-api/src/database.ts
new file mode 100644
index 0000000..915ddd2
--- /dev/null
+++ b/identity-api/src/database.ts
@@ -0,0 +1,316 @@
+// Identity. Store your memories and mental belongings
+// Copyright (C) 2024 Sofía Aritz
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import { drizzle } from "drizzle-orm/better-sqlite3";
+import Database from "better-sqlite3";
+import { SQLITE_PATH } from "./consts.js";
+import { sqliteTable } from "drizzle-orm/sqlite-core";
+import { text, integer } from "drizzle-orm/sqlite-core";
+import { asc, desc, eq, sql } from "drizzle-orm";
+
+export type DatabaseInterface = Awaited>
+
+export function toDBList(input: any[]): string {
+ return JSON.stringify(input);
+}
+
+export function fromDBList(input: string): Array {
+ return JSON.parse(input)
+}
+
+export async function startDatabase() {
+ let sqlite = new Database(SQLITE_PATH);
+ let database = drizzle(sqlite);
+
+ const limits = sqliteTable("limits", {
+ id: text("id").primaryKey(),
+ currentAssetCount: integer("current_asset_count").notNull(),
+ maxAssetCount: integer("max_asset_count").notNull(),
+ });
+
+ const users = sqliteTable("users", {
+ id: text("id").primaryKey(),
+ createdAt: integer("created_at").notNull(),
+ lastConnected: integer("last_connected_at").notNull(),
+ name: text("name").notNull(),
+ email: text("email").notNull(),
+ password: text("password").notNull(),
+ assets: text("assets").notNull(),
+ limitID: text("limits")
+ .notNull()
+ .references(() => limits.id),
+ });
+
+ const session_keys = sqliteTable("session_keys", {
+ key: text("key").primaryKey(),
+ userID: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ });
+
+ const heirs = sqliteTable("heirs", {
+ id: text("id").primaryKey(),
+ userID: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ createdAt: integer("created_at").notNull(),
+ name: text("name").notNull(),
+ email: text("email"),
+ });
+
+ const musicEntries = sqliteTable("music_entries", {
+ id: text("id").primaryKey(),
+ artist: text("artist").notNull(),
+ title: text("title").notNull(),
+ links: text("links").notNull(),
+ universalIDs: text("universal_ids").notNull(),
+ });
+
+ const locationEntries = sqliteTable("location_entries", {
+ id: text("id").primaryKey(),
+ locationText: text("location_text"),
+ locationCoordinates: text("location_coordinates"),
+ });
+
+ const dateEntries = sqliteTable("date_entries", {
+ id: text("id").primaryKey(),
+ referencedDate: integer("referenced_date"),
+ });
+
+ const entries = sqliteTable("entries", {
+ id: text("id").primaryKey(),
+ userID: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ createdAt: integer("created_at").notNull(),
+ feelings: text("feelings").notNull(),
+ assets: text("assets").notNull(),
+ title: text("title"),
+ description: text("description"),
+ kind: text("kind").notNull(),
+ musicEntry: text("music_entry").references(() => musicEntries.id),
+ locationEntry: text("location_entry").references(() => locationEntries.id),
+ dateEntry: text("date_entry").references(() => dateEntries.id),
+ });
+
+ await runMigrations(database);
+
+ let funcs = {
+ insertHeir: async (heir: typeof heirs.$inferInsert) => {
+ let result = await database.insert(heirs).values(heir).returning({ id: heirs.id });
+ return result[0].id;
+ },
+ removeHeir: async (id: string) => {
+ await database.delete(heirs).where(eq(heirs.id, id));
+ },
+ listHeirs: async (userID: string) => {
+ return await database.select().from(heirs).where(eq(heirs.userID, userID));
+ },
+ insertUser: async (user: typeof users.$inferInsert, limit: typeof limits.$inferInsert) => {
+ let limitsResult = await database.insert(limits).values(limit).returning({ id: limits.id });
+ user.limitID = limitsResult[0].id;
+
+ let userResult = await database.insert(users).values(user).returning();
+ return userResult[0];
+ },
+ user: async (userID: string) => {
+ let result = await database.select().from(users).where(eq(users.id, userID));
+ return result[0];
+ },
+ userLimits: async (limitsID: string) => {
+ let result = await database.select().from(limits).where(eq(limits.id, limitsID));
+ return result[0];
+ },
+ updateUser: async (userID: string, newUser: {
+ name?: string,
+ email?: string,
+ password?: string,
+ }) => {
+ let result = await database.update(users).set(newUser).where(eq(users.id, userID)).returning();
+ return result[0];
+ },
+ findUserByEmail: async (email: string) => {
+ let result = await database.select().from(users).where(eq(users.email, email));
+ return result[0];
+ },
+ insertSessionKey: async (key: typeof session_keys.$inferInsert) => {
+ let result = await database.insert(session_keys).values(key).returning({ key: session_keys.key });
+ return result[0].key;
+ },
+ sessionKey: async (key: string) => {
+ let result = await database.select().from(session_keys).where(eq(session_keys.key, key));
+ return result[0];
+ },
+ findSessionKeyByUserID: async (userID: string) => {
+ return await database.select().from(session_keys).where(eq(session_keys.userID, userID));
+ },
+ insertEntry: async (entry: typeof entries.$inferInsert, musicEntry?: typeof musicEntries.$inferInsert, locationEntry?: typeof locationEntries.$inferInsert, dateEntry?: typeof dateEntries.$inferInsert) => {
+ if (entry.kind === "album" || entry.kind === "song") {
+ let result = await database.insert(musicEntries).values(musicEntry).returning({ id: musicEntries.id });
+ entry.musicEntry = result[0].id;
+ } else if (entry.kind === "environment") {
+ let result = await database
+ .insert(locationEntries)
+ .values(locationEntry)
+ .returning({ id: locationEntries.id });
+ entry.locationEntry = result[0].id;
+ } else if (entry.kind === "date") {
+ let result = await database.insert(dateEntries).values(dateEntry).returning({ id: dateEntries.id });
+ entry.dateEntry = result[0].id;
+ }
+
+ let result = await database.insert(entries).values(entry).returning({ id: entries.id });
+ return result[0].id;
+ },
+ removeEntry: async (entryID: string) => {
+ await database.delete(entries).where(eq(entries.id, entryID));
+ },
+ entryPage: async (userID: string, offset: number, limit: number) => {
+ let result = await database
+ .select()
+ .from(entries)
+ .where(eq(entries.userID, userID))
+ .limit(limit)
+ .offset(offset)
+ .orderBy(desc(entries.createdAt));
+
+ for (let key in result) {
+ if (!result.hasOwnProperty(key)) { continue; }
+
+ let entry = structuredClone(result[key]);
+ let base = {};
+ if (entry.musicEntry != null) {
+ let musicDetails = (await database.select().from(musicEntries).where(eq(musicEntries.id, entry.musicEntry)))[0];
+ (musicDetails["link"] as any) = fromDBList(musicDetails.links);
+ (musicDetails["id"] as any) = fromDBList(musicDetails.universalIDs);
+
+ musicDetails["links"] = undefined;
+ musicDetails["universalIDs"] = undefined;
+ base = musicDetails;
+ } else if (entry.locationEntry != null) {
+ let locationDetails = (await database.select().from(locationEntries).where(eq(locationEntries.id, entry.locationEntry)))[0];
+
+ if (locationDetails.locationCoordinates != null) {
+ base = { location: JSON.parse(locationDetails.locationCoordinates) }
+ } else if (locationDetails.locationText != null) {
+ base = { location: locationDetails.locationText }
+ }
+ } else if (entry.dateEntry != null) {
+ let dateDetails = (await database.select().from(dateEntries).where(eq(dateEntries.id, entry.dateEntry)))[0];
+
+ base = {
+ referencedDate: new Date(dateDetails["referencedDate"]).toISOString()
+ };
+ }
+
+ base["kind"] = entry.kind
+
+ result[key]["creationDate"] = new Date(entry.createdAt).toISOString();
+ (result[key] as any)["feelings"] = fromDBList(entry.feelings);
+ (result[key] as any)["assets"] = fromDBList(entry.assets);
+ result[key]["base"] = base;
+
+ result[key].kind = undefined;
+ result[key].userID = undefined;
+ result[key].musicEntry = undefined;
+ result[key].locationEntry = undefined;
+ result[key].dateEntry = undefined;
+ }
+
+ return result;
+ },
+ };
+
+ return funcs;
+}
+
+async function runMigrations(database) {
+ await database.run(sql`CREATE TABLE IF NOT EXISTS limits (
+ id varchar PRIMARY KEY,
+ current_asset_count integer NOT NULL,
+ max_asset_count integer NOT NULL
+ );`);
+
+ await database.run(sql`CREATE TABLE IF NOT EXISTS users (
+ id varchar PRIMARY KEY,
+ created_at timestamp NOT NULL,
+ last_connected_at timestamp NOT NULL,
+ email varchar NOT NULL,
+ password varchar NOT NULL,
+ name varchar NOT NULL,
+ limits varchar NOT NULL,
+ assets varchar NOT NULL,
+ FOREIGN KEY (limits) REFERENCES limits (id)
+ );`);
+
+ await database.run(sql`
+ CREATE TABLE IF NOT EXISTS session_keys (
+ key varchar PRIMARY KEY,
+ user_id varchar NOT NULL,
+ FOREIGN KEY (user_id) REFERENCES users (id)
+ );`);
+
+ await database.run(sql`
+ CREATE TABLE IF NOT EXISTS heirs (
+ id varchar PRIMARY KEY,
+ user_id varchar NOT NULL,
+ created_at timestamp NOT NULL,
+ name varchar NOT NULL,
+ email varchar,
+ FOREIGN KEY (user_id) REFERENCES users (id)
+ );`);
+
+ await database.run(sql`
+ CREATE TABLE IF NOT EXISTS entries (
+ id varchar PRIMARY KEY,
+ user_id varchar NOT NULL,
+ created_at timestamp NOT NULL,
+ feelings text NOT NULL,
+ assets text NOT NULL,
+ title text,
+ description text,
+ kind varchar NOT NULL,
+ music_entry varchar,
+ location_entry varchar,
+ date_entry varchar,
+ FOREIGN KEY (user_id) REFERENCES users (id),
+ FOREIGN KEY (music_entry) REFERENCES music_entries (id),
+ FOREIGN KEY (location_entry) REFERENCES location_entries (id),
+ FOREIGN KEY (date_entry) REFERENCES date_entries (id)
+ );`);
+
+ await database.run(sql`
+ CREATE TABLE IF NOT EXISTS music_entries (
+ id varchar PRIMARY KEY,
+ artist varchar NOT NULL,
+ title varchar NOT NULL,
+ links text NOT NULL,
+ universal_ids text NOT NULL
+ );`);
+
+ await database.run(sql`
+ CREATE TABLE IF NOT EXISTS location_entries (
+ id varchar PRIMARY KEY,
+ location_text text,
+ location_coordinates varchar
+ );`);
+
+ await database.run(sql`
+ CREATE TABLE IF NOT EXISTS date_entries (
+ id varchar PRIMARY KEY,
+ referenced_date timestamp
+ );`);
+}
diff --git a/identity-api/src/index.js b/identity-api/src/index.ts
similarity index 89%
rename from identity-api/src/index.js
rename to identity-api/src/index.ts
index f5d4476..eac16ed 100644
--- a/identity-api/src/index.js
+++ b/identity-api/src/index.ts
@@ -20,8 +20,10 @@ import { startAuth } from "./auth.js";
import cors from "@fastify/cors";
import { registerRoutes } from "./routes/index.js";
+import { startDatabase } from "./database.js";
-let auth = await startAuth();
+let database = await startDatabase();
+let auth = await startAuth(database);
app.addSchema({
$id: "schema://identity/authorization",
@@ -36,7 +38,7 @@ app.register(cors, {
origin: true,
});
-registerRoutes(app, auth);
+registerRoutes(app, auth, database);
app.get("/", async () => {
return IDENTITY_API_LANDING_MESSAGE;
diff --git a/identity-api/src/m2m.js b/identity-api/src/m2m.ts
similarity index 100%
rename from identity-api/src/m2m.js
rename to identity-api/src/m2m.ts
diff --git a/identity-api/src/routes/asset/endpoint.js b/identity-api/src/routes/asset/endpoint.ts
similarity index 90%
rename from identity-api/src/routes/asset/endpoint.js
rename to identity-api/src/routes/asset/endpoint.ts
index aacf129..be0b2d8 100644
--- a/identity-api/src/routes/asset/endpoint.js
+++ b/identity-api/src/routes/asset/endpoint.ts
@@ -14,10 +14,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
import { ASSET_API_ENDPOINT } from "../../consts.js";
-export default function register(app) {
+import type { AppInterface } from "../../app.js";
+
+export default function register(app: AppInterface) {
app.get("/asset/endpoint", {
async handler() {
return ASSET_API_ENDPOINT;
diff --git a/identity-api/src/routes/asset/index.js b/identity-api/src/routes/asset/index.ts
similarity index 86%
rename from identity-api/src/routes/asset/index.js
rename to identity-api/src/routes/asset/index.ts
index 08965f4..1c1c937 100644
--- a/identity-api/src/routes/asset/index.js
+++ b/identity-api/src/routes/asset/index.ts
@@ -14,9 +14,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import type { AppInterface } from "../../app.js";
import endpoint from "./endpoint.js";
-export default function registerRoutes(app, auth) {
- endpoint(app, auth);
+export default function registerRoutes(app: AppInterface) {
+ endpoint(app);
}
diff --git a/identity-api/src/routes/auth/account.js b/identity-api/src/routes/auth/account.ts
similarity index 85%
rename from identity-api/src/routes/auth/account.js
rename to identity-api/src/routes/auth/account.ts
index 8a86148..4b5e9fc 100644
--- a/identity-api/src/routes/auth/account.js
+++ b/identity-api/src/routes/auth/account.ts
@@ -14,8 +14,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
-export default function register(app, auth) {
+export default function register(app: AppInterface, auth: AuthInterface) {
app.get("/auth/account", {
async handler(request, reply) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
@@ -27,9 +29,7 @@ export default function register(app, auth) {
}
let user = await auth.user(payload.uid);
- user.password = undefined;
- user.entries = undefined;
- return user;
+ return auth.cleanUser(user);
},
schema: {
headers: { $ref: "schema://identity/authorization" },
diff --git a/identity-api/src/routes/auth/genkey.js b/identity-api/src/routes/auth/genkey.ts
similarity index 87%
rename from identity-api/src/routes/auth/genkey.js
rename to identity-api/src/routes/auth/genkey.ts
index 484f200..d07f299 100644
--- a/identity-api/src/routes/auth/genkey.js
+++ b/identity-api/src/routes/auth/genkey.ts
@@ -14,8 +14,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
-export default function register(app, auth) {
+export default function register(app: AppInterface, auth: AuthInterface) {
app.get("/auth/genkey", {
async handler(request) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
diff --git a/identity-api/src/routes/auth/heirs.js b/identity-api/src/routes/auth/heirs.js
deleted file mode 100644
index 90c786b..0000000
--- a/identity-api/src/routes/auth/heirs.js
+++ /dev/null
@@ -1,41 +0,0 @@
-// Identity. Store your memories and mental belongings
-// Copyright (C) 2024 Sofía Aritz
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published
-// by the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-
-export default function register(app, auth) {
- app.post("/auth/heirs", {
- async handler(request, reply) {
- let jwt = request.headers["authorization"].replace("Bearer", "").trim();
- let { payload } = await auth.verifyJwt(jwt);
-
- if (payload.uid == null) {
- reply.status(401);
- return;
- }
-
- let user = await auth.user(payload.uid);
- user.heirs = request.body;
-
- await auth.updateUser(payload.uid, user);
- },
- schema: {
- headers: { $ref: "schema://identity/authorization" },
- body: {
- type: "array",
- },
- },
- });
-}
diff --git a/identity-api/src/routes/auth/heirs.ts b/identity-api/src/routes/auth/heirs.ts
new file mode 100644
index 0000000..9e2a8b3
--- /dev/null
+++ b/identity-api/src/routes/auth/heirs.ts
@@ -0,0 +1,90 @@
+// Identity. Store your memories and mental belongings
+// Copyright (C) 2024 Sofía Aritz
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import { randomUUID } from "node:crypto";
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import { DatabaseInterface } from "../../database.js";
+import { Static, Type } from "@sinclair/typebox";
+
+const Body = Type.Object({
+ contactMethod: Type.String(),
+ name: Type.String(),
+ value: Type.String(),
+})
+
+type BodyType = Static;
+
+export default function register(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
+ app.put<{ Body: BodyType }>("/auth/heirs", {
+ async handler(request, reply) {
+ let jwt = request.headers["authorization"].replace("Bearer", "").trim();
+ let { payload } = await auth.verifyJwt(jwt);
+
+ if (payload.uid == null) {
+ reply.status(401);
+ return;
+ }
+
+ if (request.body.contactMethod !== "email") {
+ reply.status(400);
+ return;
+ }
+
+ await database.insertHeir({
+ id: randomUUID(),
+ createdAt: Date.now(),
+ userID: payload.uid,
+ name: request.body.name,
+ email: request.body.value,
+ });
+
+ return (await database.listHeirs(payload.uid))
+ .map(v => v["contactMethod"] = "email")
+ .map(v => v["value"] = v["email"])
+ .map(v => v["email"] = undefined);
+ },
+ schema: {
+ headers: { $ref: "schema://identity/authorization" },
+ body: Body,
+ },
+ });
+
+ app.delete<{ Body: string }>("/auth/heirs", {
+ async handler(request, reply) {
+ let jwt = request.headers["authorization"].replace("Bearer", "").trim();
+ let { payload } = await auth.verifyJwt(jwt);
+
+ if (payload.uid == null) {
+ reply.status(401);
+ return;
+ }
+
+ await database.removeHeir(request.body);
+
+ return (await database.listHeirs(payload.uid))
+ .map(v => v["contactMethod"] = "email")
+ .map(v => v["value"] = v["email"])
+ .map(v => v["email"] = undefined);
+ },
+ schema: {
+ headers: { $ref: "schema://identity/authorization" },
+ body: {
+ type: "string",
+ },
+ },
+ });
+}
diff --git a/identity-api/src/routes/auth/index.js b/identity-api/src/routes/auth/index.ts
similarity index 77%
rename from identity-api/src/routes/auth/index.js
rename to identity-api/src/routes/auth/index.ts
index e9a7f16..45ad505 100644
--- a/identity-api/src/routes/auth/index.js
+++ b/identity-api/src/routes/auth/index.ts
@@ -14,6 +14,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import { DatabaseInterface } from "../../database.js";
import account from "./account.js";
import genkey from "./genkey.js";
@@ -21,10 +24,10 @@ import heirs from "./heirs.js";
import login from "./login.js";
import register from "./register.js";
-export default function registerRoutes(app, auth) {
+export default function registerRoutes(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
account(app, auth);
genkey(app, auth);
- heirs(app, auth);
+ heirs(app, auth, database);
login(app, auth);
register(app, auth);
}
diff --git a/identity-api/src/routes/auth/login.js b/identity-api/src/routes/auth/login.ts
similarity index 65%
rename from identity-api/src/routes/auth/login.js
rename to identity-api/src/routes/auth/login.ts
index 53445dd..a6931ca 100644
--- a/identity-api/src/routes/auth/login.js
+++ b/identity-api/src/routes/auth/login.ts
@@ -14,14 +14,24 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import { Static, Type } from "@sinclair/typebox";
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
-export default function register(app, auth) {
- app.post("/auth/login", {
+const Body = Type.Object({
+ email: Type.String({ format: "email" }),
+ password: Type.String(),
+});
+
+type BodyType = Static;
+
+export default function register(app: AppInterface, auth: AuthInterface) {
+ app.post<{ Body: BodyType }>("/auth/login", {
async handler(request, reply) {
let user = await auth.findUserByEmail(request.body.email);
- if (user != null && user.password == request.body.password) {
- let token = await auth.createJwt(user.uid);
+ if (user != null && auth.verifyPassword(user, request.body.password)) {
+ let token = await auth.createJwt(user.id);
return {
token,
@@ -34,14 +44,7 @@ export default function register(app, auth) {
};
},
schema: {
- body: {
- type: "object",
- properties: {
- email: { type: "string" },
- password: { type: "string" },
- },
- },
- required: ["email", "password"],
+ body: Body,
},
});
}
diff --git a/identity-api/src/routes/auth/register.js b/identity-api/src/routes/auth/register.ts
similarity index 67%
rename from identity-api/src/routes/auth/register.js
rename to identity-api/src/routes/auth/register.ts
index 426d94f..f3a0b68 100644
--- a/identity-api/src/routes/auth/register.js
+++ b/identity-api/src/routes/auth/register.ts
@@ -14,23 +14,29 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import { Static, Type } from "@sinclair/typebox";
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
-export default function register(app, auth) {
- app.post("/auth/register", {
+const Body = Type.Object({
+ name: Type.String(),
+ email: Type.String({ format: "email" }),
+ password: Type.String(),
+});
+
+type BodyType = Static;
+
+export default function register(app: AppInterface, auth: AuthInterface) {
+ app.post<{ Body: BodyType }>("/auth/register", {
async handler(request, reply) {
if ((await auth.findUserByEmail(request.body.email)) == null) {
let user = await auth.addUser({
email: request.body.email,
password: request.body.password,
name: request.body.name,
- assets: [],
- limits: {
- assetCount: 5,
- },
- entries: [],
});
-
- return { token: await auth.createJwt(user.uid) };
+
+ return { token: await auth.createJwt(user.id) };
}
reply.code(400);
@@ -39,15 +45,7 @@ export default function register(app, auth) {
};
},
schema: {
- body: {
- type: "object",
- properties: {
- name: { type: "string" },
- email: { type: "string" },
- password: { type: "string" },
- },
- required: ["name", "email", "password"],
- },
+ body: Body,
},
});
}
diff --git a/identity-api/src/routes/entry/index.js b/identity-api/src/routes/entry/index.js
deleted file mode 100644
index 3c29844..0000000
--- a/identity-api/src/routes/entry/index.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// Identity. Store your memories and mental belongings
-// Copyright (C) 2024 Sofía Aritz
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published
-// by the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-
-import { randomUUID } from "node:crypto";
-import list from "./list.js";
-
-export default function registerRoutes(app, auth) {
- list(app, auth);
-
- app.delete("/entry", {
- async handler(request) {
- let jwt = request.headers["authorization"].replace("Bearer", "").trim();
- let { payload } = await auth.verifyJwt(jwt);
-
- let user = await auth.user(payload.uid);
- user.entries = user.entries.filter((v) => v.id !== request.query.entry_id);
-
- await auth.updateUser(payload.uid, user);
- },
- schema: {
- headers: { $ref: "schema://identity/authorization" },
- query: {
- type: "object",
- properties: {
- entry_id: { type: "string" },
- },
- required: ["entry_id"],
- },
- },
- });
-
- app.put("/entry", {
- async handler(request) {
- let jwt = request.headers["authorization"].replace("Bearer", "").trim();
- let { payload } = await auth.verifyJwt(jwt);
-
- let user = await auth.user(payload.uid);
- request.body.entry.id = randomUUID().toString();
- user.entries = [request.body.entry, ...user.entries];
-
- await auth.updateUser(payload.uid, user);
- },
- schema: {
- headers: { $ref: "schema://identity/authorization" },
- body: {
- type: "object",
- properties: {
- entry: { type: "object" },
- },
- required: ["entry"],
- },
- },
- });
-}
diff --git a/identity-api/src/routes/entry/index.ts b/identity-api/src/routes/entry/index.ts
new file mode 100644
index 0000000..32d8b08
--- /dev/null
+++ b/identity-api/src/routes/entry/index.ts
@@ -0,0 +1,145 @@
+// Identity. Store your memories and mental belongings
+// Copyright (C) 2024 Sofía Aritz
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import { randomUUID } from "node:crypto";
+import list from "./list.js";
+
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import { toDBList, type DatabaseInterface } from "../../database.js";
+import { Static, Type } from "@sinclair/typebox";
+
+const EntryIDQuery = Type.Object({
+ entry_id: Type.String(),
+})
+
+type EntryIDQueryType = Static;
+
+const PutEntryBody = Type.Object({
+ entry: Type.Object({
+ title: Type.Optional(Type.String()),
+ description: Type.Optional(Type.String()),
+ creationDate: Type.String(),
+ assets: Type.Array(Type.String()),
+ feelings: Type.Array(
+ Type.Union([
+ Type.String(),
+ Type.Object({
+ identifier: Type.String(),
+ description: Type.String(),
+ backgroundColor: Type.String(),
+ textColor: Type.String(),
+ }),
+ ])
+ ),
+ base: Type.Union([
+ Type.Object({
+ kind: Type.String(),
+
+ }),
+ Type.Object({
+ kind: Type.String(),
+ artist: Type.String(),
+ title: Type.String(),
+ link: Type.Array(Type.String()),
+ id: Type.Array(Type.Object({
+ provider: Type.String(),
+ id: Type.String(),
+ })),
+ }),
+ Type.Object({
+ kind: Type.String(),
+ location: Type.Union([
+ Type.String(),
+ Type.Object({
+ latitude: Type.Number(),
+ longitude: Type.Number(),
+ }),
+ ]),
+ }),
+ Type.Object({
+ kind: Type.String(),
+ referencedDate: Type.String(),
+ }),
+ ]),
+ })
+});
+
+type PutEntryBodyType = Static;
+
+export default function registerRoutes(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
+ list(app, auth, database);
+
+ app.delete<{ Querystring: EntryIDQueryType }>("/entry", {
+ async handler(request) {
+ let jwt = request.headers["authorization"].replace("Bearer", "").trim();
+ let { payload } = await auth.verifyJwt(jwt);
+
+ let user = await auth.user(payload.uid);
+ database.removeEntry(request.query.entry_id);
+ },
+ schema: {
+ headers: { $ref: "schema://identity/authorization" },
+ querystring: EntryIDQuery,
+ },
+ });
+
+ app.put<{ Body: PutEntryBodyType }>("/entry", {
+ async handler(request) {
+ let jwt = request.headers["authorization"].replace("Bearer", "").trim();
+ let { payload } = await auth.verifyJwt(jwt);
+
+ let entry = request.body.entry;
+
+ let musicEntry, locationEntry, dateEntry;
+ if ((entry.base.kind === "album" || entry.base.kind === "song") && 'artist' in entry.base) {
+ musicEntry = {
+ id: randomUUID(),
+ title: entry.base.title,
+ artist: entry.base.artist,
+ links: toDBList(entry.base.link),
+ universalIDs: toDBList(entry.base.id),
+ }
+ } else if (entry.base.kind === "environment" && 'location' in entry.base) {
+ locationEntry = {
+ id: randomUUID(),
+ locationText: typeof entry.base.location === "string" ? entry.base.location : undefined,
+ locationCoordinates: typeof entry.base.location === "string" ? undefined : JSON.stringify(entry.base.location),
+ }
+ } else if (entry.base.kind === "date" && 'referencedDate' in entry.base) {
+ dateEntry = {
+ id: randomUUID(),
+ referencedDate: Date.parse(entry.base.referencedDate),
+ }
+ }
+
+ await database.insertEntry({
+ id: randomUUID(),
+ userID: payload.uid,
+ feelings: toDBList(entry.feelings),
+ assets: toDBList(entry.assets),
+ title: entry.title,
+ description: entry.description,
+ kind: entry.base.kind,
+ createdAt: Date.now(),
+ }, musicEntry, locationEntry, dateEntry);
+ },
+ schema: {
+ headers: { $ref: "schema://identity/authorization" },
+ body: PutEntryBody,
+ },
+ });
+}
diff --git a/identity-api/src/routes/entry/list.js b/identity-api/src/routes/entry/list.ts
similarity index 65%
rename from identity-api/src/routes/entry/list.js
rename to identity-api/src/routes/entry/list.ts
index 47dbe37..9b9680f 100644
--- a/identity-api/src/routes/entry/list.js
+++ b/identity-api/src/routes/entry/list.ts
@@ -14,9 +14,20 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
+import { Static, Type } from "@sinclair/typebox";
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import type { DatabaseInterface } from "../../database.js";
-export default function register(app, auth) {
- app.get("/entry/list", {
+const Query = Type.Object({
+ limit: Type.Number(),
+ offset: Type.Number(),
+})
+
+type QueryType = Static;
+
+export default function register(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
+ app.get<{ Querystring: QueryType }>("/entry/list", {
async handler(request, reply) {
if (request.query.offset < 0 || request.query.limit <= 0) {
reply.status(400);
@@ -26,19 +37,11 @@ export default function register(app, auth) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
- let user = await auth.user(payload.uid);
- return user.entries.slice(request.query.offset, request.query.offset + request.query.limit);
+ return await database.entryPage(payload.uid, request.query.offset, request.query.limit)
},
schema: {
headers: { $ref: "schema://identity/authorization" },
- query: {
- type: "object",
- properties: {
- limit: { type: "number" },
- offset: { type: "number" },
- },
- required: ["limit", "offset"],
- },
+ querystring: Query,
},
});
}
diff --git a/identity-api/src/routes/index.js b/identity-api/src/routes/index.ts
similarity index 71%
rename from identity-api/src/routes/index.js
rename to identity-api/src/routes/index.ts
index 75f2a13..406fc61 100644
--- a/identity-api/src/routes/index.js
+++ b/identity-api/src/routes/index.ts
@@ -14,15 +14,18 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
import m2m from "./m2m/index.js";
import asset from "./asset/index.js";
import entry from "./entry/index.js";
import authRoutes from "./auth/index.js";
-export function registerRoutes(app, auth) {
- m2m(app, auth);
- asset(app, auth);
- entry(app, auth);
- authRoutes(app, auth);
+import type { AppInterface } from "../app.js";
+import type { DatabaseInterface } from "../database.js";
+import type { AuthInterface } from "../auth.js";
+
+export function registerRoutes(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
+ m2m(app, auth, database);
+ asset(app);
+ entry(app, auth, database);
+ authRoutes(app, auth, database);
}
diff --git a/identity-api/src/routes/m2m/account.js b/identity-api/src/routes/m2m/account.ts
similarity index 67%
rename from identity-api/src/routes/m2m/account.js
rename to identity-api/src/routes/m2m/account.ts
index 623d42a..cf4e4c9 100644
--- a/identity-api/src/routes/m2m/account.js
+++ b/identity-api/src/routes/m2m/account.ts
@@ -14,24 +14,30 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
import { contentFromSigned, verifySignature } from "../../m2m.js";
-export default function register(app, auth) {
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import { DatabaseInterface, fromDBList } from "../../database.js";
+
+export default function register(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
app.post("/m2m/account", {
async handler(request, reply) {
if (!verifySignature(request.body)) {
- reply.statusCode(401);
+ reply.status(401);
return;
}
let body = JSON.parse(contentFromSigned(request.body));
-
+
let user = await auth.findUserBySessionKey(body.session_key);
- user.password = undefined;
- user.entries = undefined;
+ let limits = await database.userLimits(user.limitID);
+ (user.assets as any) = fromDBList(user.assets);
- return user;
+ return {
+ user: auth.cleanUser(user),
+ limits,
+ };
},
});
}
diff --git a/identity-api/src/routes/m2m/asset.js b/identity-api/src/routes/m2m/asset.ts
similarity index 72%
rename from identity-api/src/routes/m2m/asset.js
rename to identity-api/src/routes/m2m/asset.ts
index 13de09e..bb25280 100644
--- a/identity-api/src/routes/m2m/asset.js
+++ b/identity-api/src/routes/m2m/asset.ts
@@ -14,23 +14,29 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
import { contentFromSigned, verifySignature } from "../../m2m.js";
-export default function register(app, auth) {
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import { fromDBList } from "../../database.js";
+
+export default function register(app: AppInterface, auth: AuthInterface) {
app.put("/m2m/asset", {
async handler(request, reply) {
if (!verifySignature(request.body)) {
- reply.statusCode(401);
+ reply.status(401);
return;
}
let body = JSON.parse(contentFromSigned(request.body));
let user = await auth.findUserBySessionKey(body.session_key);
- user.assets.push(body.asset_id);
-
- await auth.updateUser(user.uid, user);
+ let assets = fromDBList(user.assets) as string[];
+ assets.push(body.asset_id);
+
+ await auth.updateUser(user.id, {
+ assets,
+ });
app.log.info((await auth.findUserBySessionKey(body.session_key)).assets);
},
});
diff --git a/identity-api/src/routes/m2m/index.js b/identity-api/src/routes/m2m/index.ts
similarity index 74%
rename from identity-api/src/routes/m2m/index.js
rename to identity-api/src/routes/m2m/index.ts
index 356e771..c50b56a 100644
--- a/identity-api/src/routes/m2m/index.js
+++ b/identity-api/src/routes/m2m/index.ts
@@ -14,11 +14,14 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-
import asset from "./asset.js";
import account from "./account.js";
-export default function registerRoutes(app, auth) {
+import type { AppInterface } from "../../app.js";
+import type { AuthInterface } from "../../auth.js";
+import { DatabaseInterface } from "../../database.js";
+
+export default function registerRoutes(app: AppInterface, auth: AuthInterface, database: DatabaseInterface) {
asset(app, auth);
- account(app, auth);
+ account(app, auth, database);
}
diff --git a/identity-api/tsconfig.json b/identity-api/tsconfig.json
new file mode 100644
index 0000000..7df0b1a
--- /dev/null
+++ b/identity-api/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "module": "NodeNext",
+ "target": "ES2021",
+ "moduleResolution": "NodeNext",
+ "sourceMap": true,
+ "outDir": "dist",
+ "types": ["node"],
+ "skipLibCheck": true
+ },
+ "include": ["./src/**/*"],
+ "exclude": ["./node_modules/**/*"]
+}
\ No newline at end of file
diff --git a/identity-api/yarn.lock b/identity-api/yarn.lock
index 9bf0a0a..2a2021b 100644
--- a/identity-api/yarn.lock
+++ b/identity-api/yarn.lock
@@ -111,6 +111,15 @@ __metadata:
languageName: node
linkType: hard
+"@fastify/type-provider-typebox@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@fastify/type-provider-typebox@npm:4.0.0"
+ peerDependencies:
+ "@sinclair/typebox": ">=0.26 <=0.32"
+ checksum: 10c0/1134f9e8873c4057a2dc18fc85729e3ea3a33bcaaf91efd66bfca63ac2bf9715f33f3412643ecba0a5120e7861235580b13f4bc1a46dd12c5c6ecc4ed5574a46
+ languageName: node
+ linkType: hard
+
"@humanwhocodes/module-importer@npm:^1.0.1":
version: 1.0.1
resolution: "@humanwhocodes/module-importer@npm:1.0.1"
@@ -125,6 +134,20 @@ __metadata:
languageName: node
linkType: hard
+"@isaacs/cliui@npm:^8.0.2":
+ version: 8.0.2
+ resolution: "@isaacs/cliui@npm:8.0.2"
+ dependencies:
+ string-width: "npm:^5.1.2"
+ string-width-cjs: "npm:string-width@^4.2.0"
+ strip-ansi: "npm:^7.0.1"
+ strip-ansi-cjs: "npm:strip-ansi@^6.0.1"
+ wrap-ansi: "npm:^8.1.0"
+ wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0"
+ checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e
+ languageName: node
+ linkType: hard
+
"@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5"
@@ -152,6 +175,65 @@ __metadata:
languageName: node
linkType: hard
+"@npmcli/agent@npm:^2.0.0":
+ version: 2.2.2
+ resolution: "@npmcli/agent@npm:2.2.2"
+ dependencies:
+ agent-base: "npm:^7.1.0"
+ http-proxy-agent: "npm:^7.0.0"
+ https-proxy-agent: "npm:^7.0.1"
+ lru-cache: "npm:^10.0.1"
+ socks-proxy-agent: "npm:^8.0.3"
+ checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae
+ languageName: node
+ linkType: hard
+
+"@npmcli/fs@npm:^3.1.0":
+ version: 3.1.1
+ resolution: "@npmcli/fs@npm:3.1.1"
+ dependencies:
+ semver: "npm:^7.3.5"
+ checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99
+ languageName: node
+ linkType: hard
+
+"@phc/format@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "@phc/format@npm:1.0.0"
+ checksum: 10c0/56cec2687ac3767298f77b2202c0d6f282878c1375948b01da16e03475dc293628847d33150469a793d55095700dce65ac1760ada271deeab15bd0c6d1ceb306
+ languageName: node
+ linkType: hard
+
+"@pkgjs/parseargs@npm:^0.11.0":
+ version: 0.11.0
+ resolution: "@pkgjs/parseargs@npm:0.11.0"
+ checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd
+ languageName: node
+ linkType: hard
+
+"@sinclair/typebox@npm:^0.32.34":
+ version: 0.32.34
+ resolution: "@sinclair/typebox@npm:0.32.34"
+ checksum: 10c0/7d0e2e950c8f7aed74501c1abc59171f1090e521b58700cf24a47c6a4e2c3b6da5b6b0e0f7c0878e64eaa811ae4c65ceca34ca396f000d254601638393b8dad6
+ languageName: node
+ linkType: hard
+
+"@types/node@npm:^20.14.9":
+ version: 20.14.9
+ resolution: "@types/node@npm:20.14.9"
+ dependencies:
+ undici-types: "npm:~5.26.4"
+ checksum: 10c0/911ffa444dc032897f4a23ed580c67903bd38ea1c5ec99b1d00fa10b83537a3adddef8e1f29710cbdd8e556a61407ed008e06537d834e48caf449ce59f87d387
+ languageName: node
+ linkType: hard
+
+"abbrev@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "abbrev@npm:2.0.0"
+ checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372
+ languageName: node
+ linkType: hard
+
"abort-controller@npm:^3.0.0":
version: 3.0.0
resolution: "abort-controller@npm:3.0.0"
@@ -186,6 +268,25 @@ __metadata:
languageName: node
linkType: hard
+"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1":
+ version: 7.1.1
+ resolution: "agent-base@npm:7.1.1"
+ dependencies:
+ debug: "npm:^4.3.4"
+ checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50
+ languageName: node
+ linkType: hard
+
+"aggregate-error@npm:^3.0.0":
+ version: 3.1.0
+ resolution: "aggregate-error@npm:3.1.0"
+ dependencies:
+ clean-stack: "npm:^2.0.0"
+ indent-string: "npm:^4.0.0"
+ checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039
+ languageName: node
+ linkType: hard
+
"ajv-formats@npm:^2.1.1":
version: 2.1.1
resolution: "ajv-formats@npm:2.1.1"
@@ -245,7 +346,14 @@ __metadata:
languageName: node
linkType: hard
-"ansi-styles@npm:^4.1.0":
+"ansi-regex@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "ansi-regex@npm:6.0.1"
+ checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08
+ languageName: node
+ linkType: hard
+
+"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0":
version: 4.3.0
resolution: "ansi-styles@npm:4.3.0"
dependencies:
@@ -254,6 +362,25 @@ __metadata:
languageName: node
linkType: hard
+"ansi-styles@npm:^6.1.0":
+ version: 6.2.1
+ resolution: "ansi-styles@npm:6.2.1"
+ checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c
+ languageName: node
+ linkType: hard
+
+"argon2@npm:^0.40.3":
+ version: 0.40.3
+ resolution: "argon2@npm:0.40.3"
+ dependencies:
+ "@phc/format": "npm:^1.0.0"
+ node-addon-api: "npm:^8.0.0"
+ node-gyp: "npm:latest"
+ node-gyp-build: "npm:^4.8.0"
+ checksum: 10c0/994cf1ae5625aeb5ec2d0e0de67f2cf64b8723e0cc8f3cca844b99b00f57e8ad5cc6eb43b2287c9bd0fb9bd15d147e9341327115a447a6208c47ca7cc78705f5
+ languageName: node
+ linkType: hard
+
"argparse@npm:^2.0.1":
version: 2.0.1
resolution: "argparse@npm:2.0.1"
@@ -292,6 +419,37 @@ __metadata:
languageName: node
linkType: hard
+"better-sqlite3@npm:^11.1.1":
+ version: 11.1.1
+ resolution: "better-sqlite3@npm:11.1.1"
+ dependencies:
+ bindings: "npm:^1.5.0"
+ node-gyp: "npm:latest"
+ prebuild-install: "npm:^7.1.1"
+ checksum: 10c0/60b67d89f22d78afb810cb18dd446e397d35b9f95895793a3934da17f257193ac0d112798f115af3fea5ea1f2318e98051abd632a443d530ff20760a08be7d57
+ languageName: node
+ linkType: hard
+
+"bindings@npm:^1.5.0":
+ version: 1.5.0
+ resolution: "bindings@npm:1.5.0"
+ dependencies:
+ file-uri-to-path: "npm:1.0.0"
+ checksum: 10c0/3dab2491b4bb24124252a91e656803eac24292473e56554e35bbfe3cc1875332cfa77600c3bac7564049dc95075bf6fcc63a4609920ff2d64d0fe405fcf0d4ba
+ languageName: node
+ linkType: hard
+
+"bl@npm:^4.0.3":
+ version: 4.1.0
+ resolution: "bl@npm:4.1.0"
+ dependencies:
+ buffer: "npm:^5.5.0"
+ inherits: "npm:^2.0.4"
+ readable-stream: "npm:^3.4.0"
+ checksum: 10c0/02847e1d2cb089c9dc6958add42e3cdeaf07d13f575973963335ac0fdece563a50ac770ac4c8fa06492d2dd276f6cc3b7f08c7cd9c7a7ad0f8d388b2a28def5f
+ languageName: node
+ linkType: hard
+
"brace-expansion@npm:^1.1.7":
version: 1.1.11
resolution: "brace-expansion@npm:1.1.11"
@@ -302,6 +460,25 @@ __metadata:
languageName: node
linkType: hard
+"brace-expansion@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "brace-expansion@npm:2.0.1"
+ dependencies:
+ balanced-match: "npm:^1.0.0"
+ checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f
+ languageName: node
+ linkType: hard
+
+"buffer@npm:^5.5.0":
+ version: 5.7.1
+ resolution: "buffer@npm:5.7.1"
+ dependencies:
+ base64-js: "npm:^1.3.1"
+ ieee754: "npm:^1.1.13"
+ checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e
+ languageName: node
+ linkType: hard
+
"buffer@npm:^6.0.3":
version: 6.0.3
resolution: "buffer@npm:6.0.3"
@@ -312,6 +489,26 @@ __metadata:
languageName: node
linkType: hard
+"cacache@npm:^18.0.0":
+ version: 18.0.3
+ resolution: "cacache@npm:18.0.3"
+ dependencies:
+ "@npmcli/fs": "npm:^3.1.0"
+ fs-minipass: "npm:^3.0.0"
+ glob: "npm:^10.2.2"
+ lru-cache: "npm:^10.0.1"
+ minipass: "npm:^7.0.3"
+ minipass-collect: "npm:^2.0.1"
+ minipass-flush: "npm:^1.0.5"
+ minipass-pipeline: "npm:^1.2.4"
+ p-map: "npm:^4.0.0"
+ ssri: "npm:^10.0.0"
+ tar: "npm:^6.1.11"
+ unique-filename: "npm:^3.0.0"
+ checksum: 10c0/dfda92840bb371fb66b88c087c61a74544363b37a265023223a99965b16a16bbb87661fe4948718d79df6e0cc04e85e62784fbcf1832b2a5e54ff4c46fbb45b7
+ languageName: node
+ linkType: hard
+
"callsites@npm:^3.0.0":
version: 3.1.0
resolution: "callsites@npm:3.1.0"
@@ -329,6 +526,27 @@ __metadata:
languageName: node
linkType: hard
+"chownr@npm:^1.1.1":
+ version: 1.1.4
+ resolution: "chownr@npm:1.1.4"
+ checksum: 10c0/ed57952a84cc0c802af900cf7136de643d3aba2eecb59d29344bc2f3f9bf703a301b9d84cdc71f82c3ffc9ccde831b0d92f5b45f91727d6c9da62f23aef9d9db
+ languageName: node
+ linkType: hard
+
+"chownr@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "chownr@npm:2.0.0"
+ checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6
+ languageName: node
+ linkType: hard
+
+"clean-stack@npm:^2.0.0":
+ version: 2.2.0
+ resolution: "clean-stack@npm:2.2.0"
+ checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1
+ languageName: node
+ linkType: hard
+
"color-convert@npm:^2.0.1":
version: 2.0.1
resolution: "color-convert@npm:2.0.1"
@@ -359,7 +577,7 @@ __metadata:
languageName: node
linkType: hard
-"cross-spawn@npm:^7.0.2":
+"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
dependencies:
@@ -370,7 +588,7 @@ __metadata:
languageName: node
linkType: hard
-"debug@npm:^4.3.1, debug@npm:^4.3.2":
+"debug@npm:4, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
version: 4.3.5
resolution: "debug@npm:4.3.5"
dependencies:
@@ -382,6 +600,22 @@ __metadata:
languageName: node
linkType: hard
+"decompress-response@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "decompress-response@npm:6.0.0"
+ dependencies:
+ mimic-response: "npm:^3.1.0"
+ checksum: 10c0/bd89d23141b96d80577e70c54fb226b2f40e74a6817652b80a116d7befb8758261ad073a8895648a29cc0a5947021ab66705cb542fa9c143c82022b27c5b175e
+ languageName: node
+ linkType: hard
+
+"deep-extend@npm:^0.6.0":
+ version: 0.6.0
+ resolution: "deep-extend@npm:0.6.0"
+ checksum: 10c0/1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566
+ languageName: node
+ linkType: hard
+
"deep-is@npm:^0.1.3":
version: 0.1.4
resolution: "deep-is@npm:0.1.4"
@@ -389,6 +623,13 @@ __metadata:
languageName: node
linkType: hard
+"detect-libc@npm:^2.0.0":
+ version: 2.0.3
+ resolution: "detect-libc@npm:2.0.3"
+ checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7
+ languageName: node
+ linkType: hard
+
"dotenv@npm:^16.4.5":
version: 16.4.5
resolution: "dotenv@npm:16.4.5"
@@ -396,6 +637,146 @@ __metadata:
languageName: node
linkType: hard
+"drizzle-orm@npm:^0.31.2":
+ version: 0.31.2
+ resolution: "drizzle-orm@npm:0.31.2"
+ peerDependencies:
+ "@aws-sdk/client-rds-data": ">=3"
+ "@cloudflare/workers-types": ">=3"
+ "@electric-sql/pglite": ">=0.1.1"
+ "@libsql/client": "*"
+ "@neondatabase/serverless": ">=0.1"
+ "@op-engineering/op-sqlite": ">=2"
+ "@opentelemetry/api": ^1.4.1
+ "@planetscale/database": ">=1"
+ "@tidbcloud/serverless": "*"
+ "@types/better-sqlite3": "*"
+ "@types/pg": "*"
+ "@types/react": ">=18"
+ "@types/sql.js": "*"
+ "@vercel/postgres": ">=0.8.0"
+ "@xata.io/client": "*"
+ better-sqlite3: ">=7"
+ bun-types: "*"
+ expo-sqlite: ">=13.2.0"
+ knex: "*"
+ kysely: "*"
+ mysql2: ">=2"
+ pg: ">=8"
+ postgres: ">=3"
+ react: ">=18"
+ sql.js: ">=1"
+ sqlite3: ">=5"
+ peerDependenciesMeta:
+ "@aws-sdk/client-rds-data":
+ optional: true
+ "@cloudflare/workers-types":
+ optional: true
+ "@electric-sql/pglite":
+ optional: true
+ "@libsql/client":
+ optional: true
+ "@neondatabase/serverless":
+ optional: true
+ "@op-engineering/op-sqlite":
+ optional: true
+ "@opentelemetry/api":
+ optional: true
+ "@planetscale/database":
+ optional: true
+ "@tidbcloud/serverless":
+ optional: true
+ "@types/better-sqlite3":
+ optional: true
+ "@types/pg":
+ optional: true
+ "@types/react":
+ optional: true
+ "@types/sql.js":
+ optional: true
+ "@vercel/postgres":
+ optional: true
+ "@xata.io/client":
+ optional: true
+ better-sqlite3:
+ optional: true
+ bun-types:
+ optional: true
+ expo-sqlite:
+ optional: true
+ knex:
+ optional: true
+ kysely:
+ optional: true
+ mysql2:
+ optional: true
+ pg:
+ optional: true
+ postgres:
+ optional: true
+ react:
+ optional: true
+ sql.js:
+ optional: true
+ sqlite3:
+ optional: true
+ checksum: 10c0/7fb7604dc50204047fc78745c1a956f395dd582f05db9dbf76cfcc658fb180fc3012cfec03fd669140e67184d2ca32419bb3c09aafeb5db5dbe0c2db73f2fe5a
+ languageName: node
+ linkType: hard
+
+"eastasianwidth@npm:^0.2.0":
+ version: 0.2.0
+ resolution: "eastasianwidth@npm:0.2.0"
+ checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39
+ languageName: node
+ linkType: hard
+
+"emoji-regex@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "emoji-regex@npm:8.0.0"
+ checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010
+ languageName: node
+ linkType: hard
+
+"emoji-regex@npm:^9.2.2":
+ version: 9.2.2
+ resolution: "emoji-regex@npm:9.2.2"
+ checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639
+ languageName: node
+ linkType: hard
+
+"encoding@npm:^0.1.13":
+ version: 0.1.13
+ resolution: "encoding@npm:0.1.13"
+ dependencies:
+ iconv-lite: "npm:^0.6.2"
+ checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039
+ languageName: node
+ linkType: hard
+
+"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1":
+ version: 1.4.4
+ resolution: "end-of-stream@npm:1.4.4"
+ dependencies:
+ once: "npm:^1.4.0"
+ checksum: 10c0/870b423afb2d54bb8d243c63e07c170409d41e20b47eeef0727547aea5740bd6717aca45597a9f2745525667a6b804c1e7bede41f856818faee5806dd9ff3975
+ languageName: node
+ linkType: hard
+
+"env-paths@npm:^2.2.0":
+ version: 2.2.1
+ resolution: "env-paths@npm:2.2.1"
+ checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4
+ languageName: node
+ linkType: hard
+
+"err-code@npm:^2.0.2":
+ version: 2.0.3
+ resolution: "err-code@npm:2.0.3"
+ checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66
+ languageName: node
+ linkType: hard
+
"escape-string-regexp@npm:^4.0.0":
version: 4.0.0
resolution: "escape-string-regexp@npm:4.0.0"
@@ -528,6 +909,20 @@ __metadata:
languageName: node
linkType: hard
+"expand-template@npm:^2.0.3":
+ version: 2.0.3
+ resolution: "expand-template@npm:2.0.3"
+ checksum: 10c0/1c9e7afe9acadf9d373301d27f6a47b34e89b3391b1ef38b7471d381812537ef2457e620ae7f819d2642ce9c43b189b3583813ec395e2938319abe356a9b2f51
+ languageName: node
+ linkType: hard
+
+"exponential-backoff@npm:^3.1.1":
+ version: 3.1.1
+ resolution: "exponential-backoff@npm:3.1.1"
+ checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579
+ languageName: node
+ linkType: hard
+
"fast-content-type-parse@npm:^1.1.0":
version: 1.1.0
resolution: "fast-content-type-parse@npm:1.1.0"
@@ -650,6 +1045,13 @@ __metadata:
languageName: node
linkType: hard
+"file-uri-to-path@npm:1.0.0":
+ version: 1.0.0
+ resolution: "file-uri-to-path@npm:1.0.0"
+ checksum: 10c0/3b545e3a341d322d368e880e1c204ef55f1d45cdea65f7efc6c6ce9e0c4d22d802d5629320eb779d006fe59624ac17b0e848d83cc5af7cd101f206cb704f5519
+ languageName: node
+ linkType: hard
+
"find-my-way@npm:^8.0.0":
version: 8.2.0
resolution: "find-my-way@npm:8.2.0"
@@ -688,6 +1090,16 @@ __metadata:
languageName: node
linkType: hard
+"foreground-child@npm:^3.1.0":
+ version: 3.2.1
+ resolution: "foreground-child@npm:3.2.1"
+ dependencies:
+ cross-spawn: "npm:^7.0.0"
+ signal-exit: "npm:^4.0.1"
+ checksum: 10c0/9a53a33dbd87090e9576bef65fb4a71de60f6863a8062a7b11bc1cbe3cc86d428677d7c0b9ef61cdac11007ac580006f78bd5638618d564cfd5e6fd713d6878f
+ languageName: node
+ linkType: hard
+
"forwarded@npm:0.2.0":
version: 0.2.0
resolution: "forwarded@npm:0.2.0"
@@ -695,6 +1107,38 @@ __metadata:
languageName: node
linkType: hard
+"fs-constants@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "fs-constants@npm:1.0.0"
+ checksum: 10c0/a0cde99085f0872f4d244e83e03a46aa387b74f5a5af750896c6b05e9077fac00e9932fdf5aef84f2f16634cd473c63037d7a512576da7d5c2b9163d1909f3a8
+ languageName: node
+ linkType: hard
+
+"fs-minipass@npm:^2.0.0":
+ version: 2.1.0
+ resolution: "fs-minipass@npm:2.1.0"
+ dependencies:
+ minipass: "npm:^3.0.0"
+ checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004
+ languageName: node
+ linkType: hard
+
+"fs-minipass@npm:^3.0.0":
+ version: 3.0.3
+ resolution: "fs-minipass@npm:3.0.3"
+ dependencies:
+ minipass: "npm:^7.0.3"
+ checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94
+ languageName: node
+ linkType: hard
+
+"github-from-package@npm:0.0.0":
+ version: 0.0.0
+ resolution: "github-from-package@npm:0.0.0"
+ checksum: 10c0/737ee3f52d0a27e26332cde85b533c21fcdc0b09fb716c3f8e522cfaa9c600d4a631dec9fcde179ec9d47cca89017b7848ed4d6ae6b6b78f936c06825b1fcc12
+ languageName: node
+ linkType: hard
+
"glob-parent@npm:^6.0.2":
version: 6.0.2
resolution: "glob-parent@npm:6.0.2"
@@ -704,6 +1148,22 @@ __metadata:
languageName: node
linkType: hard
+"glob@npm:^10.2.2, glob@npm:^10.3.10":
+ version: 10.4.2
+ resolution: "glob@npm:10.4.2"
+ dependencies:
+ foreground-child: "npm:^3.1.0"
+ jackspeak: "npm:^3.1.2"
+ minimatch: "npm:^9.0.4"
+ minipass: "npm:^7.1.2"
+ package-json-from-dist: "npm:^1.0.0"
+ path-scurry: "npm:^1.11.1"
+ bin:
+ glob: dist/esm/bin.mjs
+ checksum: 10c0/2c7296695fa75a935f3ad17dc62e4e170a8bb8752cf64d328be8992dd6ad40777939003754e10e9741ff8fbe43aa52fba32d6930d0ffa0e3b74bc3fb5eebaa2f
+ languageName: node
+ linkType: hard
+
"globals@npm:^14.0.0":
version: 14.0.0
resolution: "globals@npm:14.0.0"
@@ -718,6 +1178,13 @@ __metadata:
languageName: node
linkType: hard
+"graceful-fs@npm:^4.2.6":
+ version: 4.2.11
+ resolution: "graceful-fs@npm:4.2.11"
+ checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2
+ languageName: node
+ linkType: hard
+
"has-flag@npm:^4.0.0":
version: 4.0.0
resolution: "has-flag@npm:4.0.0"
@@ -725,22 +1192,65 @@ __metadata:
languageName: node
linkType: hard
+"http-cache-semantics@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "http-cache-semantics@npm:4.1.1"
+ checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc
+ languageName: node
+ linkType: hard
+
+"http-proxy-agent@npm:^7.0.0":
+ version: 7.0.2
+ resolution: "http-proxy-agent@npm:7.0.2"
+ dependencies:
+ agent-base: "npm:^7.1.0"
+ debug: "npm:^4.3.4"
+ checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921
+ languageName: node
+ linkType: hard
+
+"https-proxy-agent@npm:^7.0.1":
+ version: 7.0.5
+ resolution: "https-proxy-agent@npm:7.0.5"
+ dependencies:
+ agent-base: "npm:^7.0.2"
+ debug: "npm:4"
+ checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c
+ languageName: node
+ linkType: hard
+
+"iconv-lite@npm:^0.6.2":
+ version: 0.6.3
+ resolution: "iconv-lite@npm:0.6.3"
+ dependencies:
+ safer-buffer: "npm:>= 2.1.2 < 3.0.0"
+ checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1
+ languageName: node
+ linkType: hard
+
"identity-api@workspace:.":
version: 0.0.0-use.local
resolution: "identity-api@workspace:."
dependencies:
"@eslint/js": "npm:^9.5.0"
"@fastify/cors": "npm:^9.0.1"
+ "@fastify/type-provider-typebox": "npm:^4.0.0"
+ "@sinclair/typebox": "npm:^0.32.34"
+ "@types/node": "npm:^20.14.9"
+ argon2: "npm:^0.40.3"
+ better-sqlite3: "npm:^11.1.1"
dotenv: "npm:^16.4.5"
+ drizzle-orm: "npm:^0.31.2"
eslint: "npm:9.x"
fastify: "npm:^4.27.0"
globals: "npm:^15.5.0"
jose: "npm:^5.4.0"
prettier: "npm:3.3.2"
+ typescript: "npm:^5.5.2"
languageName: unknown
linkType: soft
-"ieee754@npm:^1.2.1":
+"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1":
version: 1.2.1
resolution: "ieee754@npm:1.2.1"
checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb
@@ -771,6 +1281,37 @@ __metadata:
languageName: node
linkType: hard
+"indent-string@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "indent-string@npm:4.0.0"
+ checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f
+ languageName: node
+ linkType: hard
+
+"inherits@npm:^2.0.3, inherits@npm:^2.0.4":
+ version: 2.0.4
+ resolution: "inherits@npm:2.0.4"
+ checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2
+ languageName: node
+ linkType: hard
+
+"ini@npm:~1.3.0":
+ version: 1.3.8
+ resolution: "ini@npm:1.3.8"
+ checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a
+ languageName: node
+ linkType: hard
+
+"ip-address@npm:^9.0.5":
+ version: 9.0.5
+ resolution: "ip-address@npm:9.0.5"
+ dependencies:
+ jsbn: "npm:1.1.0"
+ sprintf-js: "npm:^1.1.3"
+ checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc
+ languageName: node
+ linkType: hard
+
"ipaddr.js@npm:1.9.1":
version: 1.9.1
resolution: "ipaddr.js@npm:1.9.1"
@@ -785,6 +1326,13 @@ __metadata:
languageName: node
linkType: hard
+"is-fullwidth-code-point@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "is-fullwidth-code-point@npm:3.0.0"
+ checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc
+ languageName: node
+ linkType: hard
+
"is-glob@npm:^4.0.0, is-glob@npm:^4.0.3":
version: 4.0.3
resolution: "is-glob@npm:4.0.3"
@@ -794,6 +1342,13 @@ __metadata:
languageName: node
linkType: hard
+"is-lambda@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "is-lambda@npm:1.0.1"
+ checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d
+ languageName: node
+ linkType: hard
+
"is-path-inside@npm:^3.0.3":
version: 3.0.3
resolution: "is-path-inside@npm:3.0.3"
@@ -808,6 +1363,26 @@ __metadata:
languageName: node
linkType: hard
+"isexe@npm:^3.1.1":
+ version: 3.1.1
+ resolution: "isexe@npm:3.1.1"
+ checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7
+ languageName: node
+ linkType: hard
+
+"jackspeak@npm:^3.1.2":
+ version: 3.4.0
+ resolution: "jackspeak@npm:3.4.0"
+ dependencies:
+ "@isaacs/cliui": "npm:^8.0.2"
+ "@pkgjs/parseargs": "npm:^0.11.0"
+ dependenciesMeta:
+ "@pkgjs/parseargs":
+ optional: true
+ checksum: 10c0/7e42d1ea411b4d57d43ea8a6afbca9224382804359cb72626d0fc45bb8db1de5ad0248283c3db45fe73e77210750d4fcc7c2b4fe5d24fda94aaa24d658295c5f
+ languageName: node
+ linkType: hard
+
"jose@npm:^5.4.0":
version: 5.4.0
resolution: "jose@npm:5.4.0"
@@ -826,6 +1401,13 @@ __metadata:
languageName: node
linkType: hard
+"jsbn@npm:1.1.0":
+ version: 1.1.0
+ resolution: "jsbn@npm:1.1.0"
+ checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96
+ languageName: node
+ linkType: hard
+
"json-buffer@npm:3.0.1":
version: 3.0.1
resolution: "json-buffer@npm:3.0.1"
@@ -909,6 +1491,40 @@ __metadata:
languageName: node
linkType: hard
+"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0":
+ version: 10.3.0
+ resolution: "lru-cache@npm:10.3.0"
+ checksum: 10c0/02d57024d90672774d66e0b76328a8975483b782c68118078363be17b8e0efb4f2bee89d98ce87e72f42d68fe7cb4ad14b1205d43e4f9954f5c91e3be4eaceb8
+ languageName: node
+ linkType: hard
+
+"make-fetch-happen@npm:^13.0.0":
+ version: 13.0.1
+ resolution: "make-fetch-happen@npm:13.0.1"
+ dependencies:
+ "@npmcli/agent": "npm:^2.0.0"
+ cacache: "npm:^18.0.0"
+ http-cache-semantics: "npm:^4.1.1"
+ is-lambda: "npm:^1.0.1"
+ minipass: "npm:^7.0.2"
+ minipass-fetch: "npm:^3.0.0"
+ minipass-flush: "npm:^1.0.5"
+ minipass-pipeline: "npm:^1.2.4"
+ negotiator: "npm:^0.6.3"
+ proc-log: "npm:^4.2.0"
+ promise-retry: "npm:^2.0.1"
+ ssri: "npm:^10.0.0"
+ checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e
+ languageName: node
+ linkType: hard
+
+"mimic-response@npm:^3.1.0":
+ version: 3.1.0
+ resolution: "mimic-response@npm:3.1.0"
+ checksum: 10c0/0d6f07ce6e03e9e4445bee655202153bdb8a98d67ee8dc965ac140900d7a2688343e6b4c9a72cfc9ef2f7944dfd76eef4ab2482eb7b293a68b84916bac735362
+ languageName: node
+ linkType: hard
+
"minimatch@npm:^3.0.5, minimatch@npm:^3.1.2":
version: 3.1.2
resolution: "minimatch@npm:3.1.2"
@@ -918,6 +1534,122 @@ __metadata:
languageName: node
linkType: hard
+"minimatch@npm:^9.0.4":
+ version: 9.0.5
+ resolution: "minimatch@npm:9.0.5"
+ dependencies:
+ brace-expansion: "npm:^2.0.1"
+ checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed
+ languageName: node
+ linkType: hard
+
+"minimist@npm:^1.2.0, minimist@npm:^1.2.3":
+ version: 1.2.8
+ resolution: "minimist@npm:1.2.8"
+ checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6
+ languageName: node
+ linkType: hard
+
+"minipass-collect@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "minipass-collect@npm:2.0.1"
+ dependencies:
+ minipass: "npm:^7.0.3"
+ checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e
+ languageName: node
+ linkType: hard
+
+"minipass-fetch@npm:^3.0.0":
+ version: 3.0.5
+ resolution: "minipass-fetch@npm:3.0.5"
+ dependencies:
+ encoding: "npm:^0.1.13"
+ minipass: "npm:^7.0.3"
+ minipass-sized: "npm:^1.0.3"
+ minizlib: "npm:^2.1.2"
+ dependenciesMeta:
+ encoding:
+ optional: true
+ checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b
+ languageName: node
+ linkType: hard
+
+"minipass-flush@npm:^1.0.5":
+ version: 1.0.5
+ resolution: "minipass-flush@npm:1.0.5"
+ dependencies:
+ minipass: "npm:^3.0.0"
+ checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd
+ languageName: node
+ linkType: hard
+
+"minipass-pipeline@npm:^1.2.4":
+ version: 1.2.4
+ resolution: "minipass-pipeline@npm:1.2.4"
+ dependencies:
+ minipass: "npm:^3.0.0"
+ checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2
+ languageName: node
+ linkType: hard
+
+"minipass-sized@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "minipass-sized@npm:1.0.3"
+ dependencies:
+ minipass: "npm:^3.0.0"
+ checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb
+ languageName: node
+ linkType: hard
+
+"minipass@npm:^3.0.0":
+ version: 3.3.6
+ resolution: "minipass@npm:3.3.6"
+ dependencies:
+ yallist: "npm:^4.0.0"
+ checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c
+ languageName: node
+ linkType: hard
+
+"minipass@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "minipass@npm:5.0.0"
+ checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462
+ languageName: node
+ linkType: hard
+
+"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2":
+ version: 7.1.2
+ resolution: "minipass@npm:7.1.2"
+ checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557
+ languageName: node
+ linkType: hard
+
+"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2":
+ version: 2.1.2
+ resolution: "minizlib@npm:2.1.2"
+ dependencies:
+ minipass: "npm:^3.0.0"
+ yallist: "npm:^4.0.0"
+ checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78
+ languageName: node
+ linkType: hard
+
+"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3":
+ version: 0.5.3
+ resolution: "mkdirp-classic@npm:0.5.3"
+ checksum: 10c0/95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168
+ languageName: node
+ linkType: hard
+
+"mkdirp@npm:^1.0.3":
+ version: 1.0.4
+ resolution: "mkdirp@npm:1.0.4"
+ bin:
+ mkdirp: bin/cmd.js
+ checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf
+ languageName: node
+ linkType: hard
+
"mnemonist@npm:0.39.6":
version: 0.39.6
resolution: "mnemonist@npm:0.39.6"
@@ -934,6 +1666,13 @@ __metadata:
languageName: node
linkType: hard
+"napi-build-utils@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "napi-build-utils@npm:1.0.2"
+ checksum: 10c0/37fd2cd0ff2ad20073ce78d83fd718a740d568b225924e753ae51cb69d68f330c80544d487e5e5bd18e28702ed2ca469c2424ad948becd1862c1b0209542b2e9
+ languageName: node
+ linkType: hard
+
"natural-compare@npm:^1.4.0":
version: 1.4.0
resolution: "natural-compare@npm:1.4.0"
@@ -941,6 +1680,73 @@ __metadata:
languageName: node
linkType: hard
+"negotiator@npm:^0.6.3":
+ version: 0.6.3
+ resolution: "negotiator@npm:0.6.3"
+ checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2
+ languageName: node
+ linkType: hard
+
+"node-abi@npm:^3.3.0":
+ version: 3.65.0
+ resolution: "node-abi@npm:3.65.0"
+ dependencies:
+ semver: "npm:^7.3.5"
+ checksum: 10c0/112672015d8f27d6be2f18d64569f28f5d6a15a94cc510da513c69c3e3ab5df6dac196ef13ff115a8fadb69b554974c47ef89b4f6350a2b02de2bca5c23db1e5
+ languageName: node
+ linkType: hard
+
+"node-addon-api@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "node-addon-api@npm:8.0.0"
+ dependencies:
+ node-gyp: "npm:latest"
+ checksum: 10c0/20eb231362cc07c62d9839164473744d985be5d82685214f3750d990d9f61ef366e0ba112a766c925d640ed29b2a500b83568e895dc2444dcd5db01e615aac2b
+ languageName: node
+ linkType: hard
+
+"node-gyp-build@npm:^4.8.0":
+ version: 4.8.1
+ resolution: "node-gyp-build@npm:4.8.1"
+ bin:
+ node-gyp-build: bin.js
+ node-gyp-build-optional: optional.js
+ node-gyp-build-test: build-test.js
+ checksum: 10c0/e36ca3d2adf2b9cca316695d7687207c19ac6ed326d6d7c68d7112cebe0de4f82d6733dff139132539fcc01cf5761f6c9082a21864ab9172edf84282bc849ce7
+ languageName: node
+ linkType: hard
+
+"node-gyp@npm:latest":
+ version: 10.1.0
+ resolution: "node-gyp@npm:10.1.0"
+ dependencies:
+ env-paths: "npm:^2.2.0"
+ exponential-backoff: "npm:^3.1.1"
+ glob: "npm:^10.3.10"
+ graceful-fs: "npm:^4.2.6"
+ make-fetch-happen: "npm:^13.0.0"
+ nopt: "npm:^7.0.0"
+ proc-log: "npm:^3.0.0"
+ semver: "npm:^7.3.5"
+ tar: "npm:^6.1.2"
+ which: "npm:^4.0.0"
+ bin:
+ node-gyp: bin/node-gyp.js
+ checksum: 10c0/9cc821111ca244a01fb7f054db7523ab0a0cd837f665267eb962eb87695d71fb1e681f9e21464cc2fd7c05530dc4c81b810bca1a88f7d7186909b74477491a3c
+ languageName: node
+ linkType: hard
+
+"nopt@npm:^7.0.0":
+ version: 7.2.1
+ resolution: "nopt@npm:7.2.1"
+ dependencies:
+ abbrev: "npm:^2.0.0"
+ bin:
+ nopt: bin/nopt.js
+ checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81
+ languageName: node
+ linkType: hard
+
"obliterator@npm:^2.0.1":
version: 2.0.4
resolution: "obliterator@npm:2.0.4"
@@ -955,6 +1761,15 @@ __metadata:
languageName: node
linkType: hard
+"once@npm:^1.3.1, once@npm:^1.4.0":
+ version: 1.4.0
+ resolution: "once@npm:1.4.0"
+ dependencies:
+ wrappy: "npm:1"
+ checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0
+ languageName: node
+ linkType: hard
+
"optionator@npm:^0.9.3":
version: 0.9.4
resolution: "optionator@npm:0.9.4"
@@ -987,6 +1802,22 @@ __metadata:
languageName: node
linkType: hard
+"p-map@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "p-map@npm:4.0.0"
+ dependencies:
+ aggregate-error: "npm:^3.0.0"
+ checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75
+ languageName: node
+ linkType: hard
+
+"package-json-from-dist@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "package-json-from-dist@npm:1.0.0"
+ checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033
+ languageName: node
+ linkType: hard
+
"parent-module@npm:^1.0.0":
version: 1.0.1
resolution: "parent-module@npm:1.0.1"
@@ -1010,6 +1841,16 @@ __metadata:
languageName: node
linkType: hard
+"path-scurry@npm:^1.11.1":
+ version: 1.11.1
+ resolution: "path-scurry@npm:1.11.1"
+ dependencies:
+ lru-cache: "npm:^10.2.0"
+ minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0"
+ checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d
+ languageName: node
+ linkType: hard
+
"pino-abstract-transport@npm:^1.2.0":
version: 1.2.0
resolution: "pino-abstract-transport@npm:1.2.0"
@@ -1048,6 +1889,28 @@ __metadata:
languageName: node
linkType: hard
+"prebuild-install@npm:^7.1.1":
+ version: 7.1.2
+ resolution: "prebuild-install@npm:7.1.2"
+ dependencies:
+ detect-libc: "npm:^2.0.0"
+ expand-template: "npm:^2.0.3"
+ github-from-package: "npm:0.0.0"
+ minimist: "npm:^1.2.3"
+ mkdirp-classic: "npm:^0.5.3"
+ napi-build-utils: "npm:^1.0.1"
+ node-abi: "npm:^3.3.0"
+ pump: "npm:^3.0.0"
+ rc: "npm:^1.2.7"
+ simple-get: "npm:^4.0.0"
+ tar-fs: "npm:^2.0.0"
+ tunnel-agent: "npm:^0.6.0"
+ bin:
+ prebuild-install: bin.js
+ checksum: 10c0/e64868ba9ef2068fd7264f5b03e5298a901e02a450acdb1f56258d88c09dea601eefdb3d1dfdff8513fdd230a92961712be0676192626a3b4d01ba154d48bdd3
+ languageName: node
+ linkType: hard
+
"prelude-ls@npm:^1.2.1":
version: 1.2.1
resolution: "prelude-ls@npm:1.2.1"
@@ -1064,6 +1927,20 @@ __metadata:
languageName: node
linkType: hard
+"proc-log@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "proc-log@npm:3.0.0"
+ checksum: 10c0/f66430e4ff947dbb996058f6fd22de2c66612ae1a89b097744e17fb18a4e8e7a86db99eda52ccf15e53f00b63f4ec0b0911581ff2aac0355b625c8eac509b0dc
+ languageName: node
+ linkType: hard
+
+"proc-log@npm:^4.2.0":
+ version: 4.2.0
+ resolution: "proc-log@npm:4.2.0"
+ checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9
+ languageName: node
+ linkType: hard
+
"process-warning@npm:^3.0.0":
version: 3.0.0
resolution: "process-warning@npm:3.0.0"
@@ -1078,6 +1955,16 @@ __metadata:
languageName: node
linkType: hard
+"promise-retry@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "promise-retry@npm:2.0.1"
+ dependencies:
+ err-code: "npm:^2.0.2"
+ retry: "npm:^0.12.0"
+ checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96
+ languageName: node
+ linkType: hard
+
"proxy-addr@npm:^2.0.7":
version: 2.0.7
resolution: "proxy-addr@npm:2.0.7"
@@ -1088,6 +1975,16 @@ __metadata:
languageName: node
linkType: hard
+"pump@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "pump@npm:3.0.0"
+ dependencies:
+ end-of-stream: "npm:^1.1.0"
+ once: "npm:^1.3.1"
+ checksum: 10c0/bbdeda4f747cdf47db97428f3a135728669e56a0ae5f354a9ac5b74556556f5446a46f720a8f14ca2ece5be9b4d5d23c346db02b555f46739934cc6c093a5478
+ languageName: node
+ linkType: hard
+
"punycode@npm:^2.1.0":
version: 2.3.1
resolution: "punycode@npm:2.3.1"
@@ -1109,6 +2006,31 @@ __metadata:
languageName: node
linkType: hard
+"rc@npm:^1.2.7":
+ version: 1.2.8
+ resolution: "rc@npm:1.2.8"
+ dependencies:
+ deep-extend: "npm:^0.6.0"
+ ini: "npm:~1.3.0"
+ minimist: "npm:^1.2.0"
+ strip-json-comments: "npm:~2.0.1"
+ bin:
+ rc: ./cli.js
+ checksum: 10c0/24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15
+ languageName: node
+ linkType: hard
+
+"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0":
+ version: 3.6.2
+ resolution: "readable-stream@npm:3.6.2"
+ dependencies:
+ inherits: "npm:^2.0.3"
+ string_decoder: "npm:^1.1.1"
+ util-deprecate: "npm:^1.0.1"
+ checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7
+ languageName: node
+ linkType: hard
+
"readable-stream@npm:^4.0.0":
version: 4.5.2
resolution: "readable-stream@npm:4.5.2"
@@ -1150,6 +2072,13 @@ __metadata:
languageName: node
linkType: hard
+"retry@npm:^0.12.0":
+ version: 0.12.0
+ resolution: "retry@npm:0.12.0"
+ checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe
+ languageName: node
+ linkType: hard
+
"reusify@npm:^1.0.4":
version: 1.0.4
resolution: "reusify@npm:1.0.4"
@@ -1173,7 +2102,7 @@ __metadata:
languageName: node
linkType: hard
-"safe-buffer@npm:~5.2.0":
+"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
@@ -1196,6 +2125,13 @@ __metadata:
languageName: node
linkType: hard
+"safer-buffer@npm:>= 2.1.2 < 3.0.0":
+ version: 2.1.2
+ resolution: "safer-buffer@npm:2.1.2"
+ checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4
+ languageName: node
+ linkType: hard
+
"secure-json-parse@npm:^2.7.0":
version: 2.7.0
resolution: "secure-json-parse@npm:2.7.0"
@@ -1203,7 +2139,7 @@ __metadata:
languageName: node
linkType: hard
-"semver@npm:^7.5.4":
+"semver@npm:^7.3.5, semver@npm:^7.5.4":
version: 7.6.2
resolution: "semver@npm:7.6.2"
bin:
@@ -1235,6 +2171,59 @@ __metadata:
languageName: node
linkType: hard
+"signal-exit@npm:^4.0.1":
+ version: 4.1.0
+ resolution: "signal-exit@npm:4.1.0"
+ checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83
+ languageName: node
+ linkType: hard
+
+"simple-concat@npm:^1.0.0":
+ version: 1.0.1
+ resolution: "simple-concat@npm:1.0.1"
+ checksum: 10c0/62f7508e674414008910b5397c1811941d457dfa0db4fd5aa7fa0409eb02c3609608dfcd7508cace75b3a0bf67a2a77990711e32cd213d2c76f4fd12ee86d776
+ languageName: node
+ linkType: hard
+
+"simple-get@npm:^4.0.0":
+ version: 4.0.1
+ resolution: "simple-get@npm:4.0.1"
+ dependencies:
+ decompress-response: "npm:^6.0.0"
+ once: "npm:^1.3.1"
+ simple-concat: "npm:^1.0.0"
+ checksum: 10c0/b0649a581dbca741babb960423248899203165769747142033479a7dc5e77d7b0fced0253c731cd57cf21e31e4d77c9157c3069f4448d558ebc96cf9e1eebcf0
+ languageName: node
+ linkType: hard
+
+"smart-buffer@npm:^4.2.0":
+ version: 4.2.0
+ resolution: "smart-buffer@npm:4.2.0"
+ checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539
+ languageName: node
+ linkType: hard
+
+"socks-proxy-agent@npm:^8.0.3":
+ version: 8.0.4
+ resolution: "socks-proxy-agent@npm:8.0.4"
+ dependencies:
+ agent-base: "npm:^7.1.1"
+ debug: "npm:^4.3.4"
+ socks: "npm:^2.8.3"
+ checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a
+ languageName: node
+ linkType: hard
+
+"socks@npm:^2.8.3":
+ version: 2.8.3
+ resolution: "socks@npm:2.8.3"
+ dependencies:
+ ip-address: "npm:^9.0.5"
+ smart-buffer: "npm:^4.2.0"
+ checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7
+ languageName: node
+ linkType: hard
+
"sonic-boom@npm:^4.0.1":
version: 4.0.1
resolution: "sonic-boom@npm:4.0.1"
@@ -1251,7 +2240,45 @@ __metadata:
languageName: node
linkType: hard
-"string_decoder@npm:^1.3.0":
+"sprintf-js@npm:^1.1.3":
+ version: 1.1.3
+ resolution: "sprintf-js@npm:1.1.3"
+ checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec
+ languageName: node
+ linkType: hard
+
+"ssri@npm:^10.0.0":
+ version: 10.0.6
+ resolution: "ssri@npm:10.0.6"
+ dependencies:
+ minipass: "npm:^7.0.3"
+ checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227
+ languageName: node
+ linkType: hard
+
+"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0":
+ version: 4.2.3
+ resolution: "string-width@npm:4.2.3"
+ dependencies:
+ emoji-regex: "npm:^8.0.0"
+ is-fullwidth-code-point: "npm:^3.0.0"
+ strip-ansi: "npm:^6.0.1"
+ checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b
+ languageName: node
+ linkType: hard
+
+"string-width@npm:^5.0.1, string-width@npm:^5.1.2":
+ version: 5.1.2
+ resolution: "string-width@npm:5.1.2"
+ dependencies:
+ eastasianwidth: "npm:^0.2.0"
+ emoji-regex: "npm:^9.2.2"
+ strip-ansi: "npm:^7.0.1"
+ checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca
+ languageName: node
+ linkType: hard
+
+"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0":
version: 1.3.0
resolution: "string_decoder@npm:1.3.0"
dependencies:
@@ -1260,7 +2287,7 @@ __metadata:
languageName: node
linkType: hard
-"strip-ansi@npm:^6.0.1":
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
version: 6.0.1
resolution: "strip-ansi@npm:6.0.1"
dependencies:
@@ -1269,6 +2296,15 @@ __metadata:
languageName: node
linkType: hard
+"strip-ansi@npm:^7.0.1":
+ version: 7.1.0
+ resolution: "strip-ansi@npm:7.1.0"
+ dependencies:
+ ansi-regex: "npm:^6.0.1"
+ checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4
+ languageName: node
+ linkType: hard
+
"strip-json-comments@npm:^3.1.1":
version: 3.1.1
resolution: "strip-json-comments@npm:3.1.1"
@@ -1276,6 +2312,13 @@ __metadata:
languageName: node
linkType: hard
+"strip-json-comments@npm:~2.0.1":
+ version: 2.0.1
+ resolution: "strip-json-comments@npm:2.0.1"
+ checksum: 10c0/b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43
+ languageName: node
+ linkType: hard
+
"supports-color@npm:^7.1.0":
version: 7.2.0
resolution: "supports-color@npm:7.2.0"
@@ -1285,6 +2328,45 @@ __metadata:
languageName: node
linkType: hard
+"tar-fs@npm:^2.0.0":
+ version: 2.1.1
+ resolution: "tar-fs@npm:2.1.1"
+ dependencies:
+ chownr: "npm:^1.1.1"
+ mkdirp-classic: "npm:^0.5.2"
+ pump: "npm:^3.0.0"
+ tar-stream: "npm:^2.1.4"
+ checksum: 10c0/871d26a934bfb7beeae4c4d8a09689f530b565f79bd0cf489823ff0efa3705da01278160da10bb006d1a793fa0425cf316cec029b32a9159eacbeaff4965fb6d
+ languageName: node
+ linkType: hard
+
+"tar-stream@npm:^2.1.4":
+ version: 2.2.0
+ resolution: "tar-stream@npm:2.2.0"
+ dependencies:
+ bl: "npm:^4.0.3"
+ end-of-stream: "npm:^1.4.1"
+ fs-constants: "npm:^1.0.0"
+ inherits: "npm:^2.0.3"
+ readable-stream: "npm:^3.1.1"
+ checksum: 10c0/2f4c910b3ee7196502e1ff015a7ba321ec6ea837667220d7bcb8d0852d51cb04b87f7ae471008a6fb8f5b1a1b5078f62f3a82d30c706f20ada1238ac797e7692
+ languageName: node
+ linkType: hard
+
+"tar@npm:^6.1.11, tar@npm:^6.1.2":
+ version: 6.2.1
+ resolution: "tar@npm:6.2.1"
+ dependencies:
+ chownr: "npm:^2.0.0"
+ fs-minipass: "npm:^2.0.0"
+ minipass: "npm:^5.0.0"
+ minizlib: "npm:^2.1.1"
+ mkdirp: "npm:^1.0.3"
+ yallist: "npm:^4.0.0"
+ checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537
+ languageName: node
+ linkType: hard
+
"text-table@npm:^0.2.0":
version: 0.2.0
resolution: "text-table@npm:0.2.0"
@@ -1308,6 +2390,15 @@ __metadata:
languageName: node
linkType: hard
+"tunnel-agent@npm:^0.6.0":
+ version: 0.6.0
+ resolution: "tunnel-agent@npm:0.6.0"
+ dependencies:
+ safe-buffer: "npm:^5.0.1"
+ checksum: 10c0/4c7a1b813e7beae66fdbf567a65ec6d46313643753d0beefb3c7973d66fcec3a1e7f39759f0a0b4465883499c6dc8b0750ab8b287399af2e583823e40410a17a
+ languageName: node
+ linkType: hard
+
"type-check@npm:^0.4.0, type-check@npm:~0.4.0":
version: 0.4.0
resolution: "type-check@npm:0.4.0"
@@ -1317,6 +2408,51 @@ __metadata:
languageName: node
linkType: hard
+"typescript@npm:^5.5.2":
+ version: 5.5.2
+ resolution: "typescript@npm:5.5.2"
+ bin:
+ tsc: bin/tsc
+ tsserver: bin/tsserver
+ checksum: 10c0/8ca39b27b5f9bd7f32db795045933ab5247897660627251e8254180b792a395bf061ea7231947d5d7ffa5cb4cc771970fd4ef543275f9b559f08c9325cccfce3
+ languageName: node
+ linkType: hard
+
+"typescript@patch:typescript@npm%3A^5.5.2#optional!builtin":
+ version: 5.5.2
+ resolution: "typescript@patch:typescript@npm%3A5.5.2#optional!builtin::version=5.5.2&hash=b45daf"
+ bin:
+ tsc: bin/tsc
+ tsserver: bin/tsserver
+ checksum: 10c0/6721ac8933a70c252d7b640b345792e103d881811ff660355617c1836526dbb71c2044e2e77a8823fb3570b469f33276875a4cab6d3c4de4ae7d7ee1c3074ae4
+ languageName: node
+ linkType: hard
+
+"undici-types@npm:~5.26.4":
+ version: 5.26.5
+ resolution: "undici-types@npm:5.26.5"
+ checksum: 10c0/bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501
+ languageName: node
+ linkType: hard
+
+"unique-filename@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "unique-filename@npm:3.0.0"
+ dependencies:
+ unique-slug: "npm:^4.0.0"
+ checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f
+ languageName: node
+ linkType: hard
+
+"unique-slug@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "unique-slug@npm:4.0.0"
+ dependencies:
+ imurmurhash: "npm:^0.1.4"
+ checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635
+ languageName: node
+ linkType: hard
+
"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1":
version: 4.4.1
resolution: "uri-js@npm:4.4.1"
@@ -1326,6 +2462,13 @@ __metadata:
languageName: node
linkType: hard
+"util-deprecate@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "util-deprecate@npm:1.0.2"
+ checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942
+ languageName: node
+ linkType: hard
+
"which@npm:^2.0.1":
version: 2.0.2
resolution: "which@npm:2.0.2"
@@ -1337,6 +2480,17 @@ __metadata:
languageName: node
linkType: hard
+"which@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "which@npm:4.0.0"
+ dependencies:
+ isexe: "npm:^3.1.1"
+ bin:
+ node-which: bin/which.js
+ checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a
+ languageName: node
+ linkType: hard
+
"word-wrap@npm:^1.2.5":
version: 1.2.5
resolution: "word-wrap@npm:1.2.5"
@@ -1344,6 +2498,42 @@ __metadata:
languageName: node
linkType: hard
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+ version: 7.0.0
+ resolution: "wrap-ansi@npm:7.0.0"
+ dependencies:
+ ansi-styles: "npm:^4.0.0"
+ string-width: "npm:^4.1.0"
+ strip-ansi: "npm:^6.0.0"
+ checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da
+ languageName: node
+ linkType: hard
+
+"wrap-ansi@npm:^8.1.0":
+ version: 8.1.0
+ resolution: "wrap-ansi@npm:8.1.0"
+ dependencies:
+ ansi-styles: "npm:^6.1.0"
+ string-width: "npm:^5.0.1"
+ strip-ansi: "npm:^7.0.1"
+ checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60
+ languageName: node
+ linkType: hard
+
+"wrappy@npm:1":
+ version: 1.0.2
+ resolution: "wrappy@npm:1.0.2"
+ checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0
+ languageName: node
+ linkType: hard
+
+"yallist@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "yallist@npm:4.0.0"
+ checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a
+ languageName: node
+ linkType: hard
+
"yocto-queue@npm:^0.1.0":
version: 0.1.0
resolution: "yocto-queue@npm:0.1.0"
diff --git a/identity-web/src/lib/api.ts b/identity-web/src/lib/api.ts
index 131af7e..3d47c8a 100644
--- a/identity-web/src/lib/api.ts
+++ b/identity-web/src/lib/api.ts
@@ -14,7 +14,14 @@ export type Credentials = {
token: string;
};
+export type InsertHeir = {
+ contactMethod: 'email';
+ name: string;
+ value: string;
+};
+
export type AccountHeir = {
+ id: string;
contactMethod: 'email';
name: string;
value: string;
@@ -22,8 +29,8 @@ export type AccountHeir = {
export type Account = {
uid: string;
+ email: string;
name: string;
- heirs: AccountHeir[];
};
function sendRequest(
@@ -119,14 +126,21 @@ export async function deleteEntry(credentials: Credentials, entry_id: string): P
await sendRequest('/entry', credentials, { method: 'DELETE' }, `?entry_id=${entry_id}`);
}
-export async function updateHeirs(credentials: Credentials, heirs: AccountHeir[]): Promise {
- await sendRequest('/auth/heirs', credentials, {
- method: 'POST',
+export async function insertHeir(credentials: Credentials, heirs: InsertHeir): Promise {
+ return await asJson(sendRequest('/auth/heirs', credentials, {
+ method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(heirs)
- });
+ }));
+}
+
+export async function removeHeir(credentials: Credentials, heirID: string): Promise {
+ return await asJson(sendRequest('/auth/heirs', credentials, {
+ method: 'DELETE',
+ body: heirID,
+ }));
}
export async function uploadAsset(session_key: string, file: File): Promise {
diff --git a/identity-web/src/routes/auth/account/+page.svelte b/identity-web/src/routes/auth/account/+page.svelte
index a808714..7b4e6fc 100644
--- a/identity-web/src/routes/auth/account/+page.svelte
+++ b/identity-web/src/routes/auth/account/+page.svelte
@@ -5,7 +5,7 @@