Umstellung auf PostgresDB & user Table & update drizzle

This commit is contained in:
Andreas Knuth 2025-02-06 17:42:16 -06:00
parent 260fc5a01a
commit 5b475f197a
15 changed files with 513 additions and 643 deletions

View File

@ -1,8 +1,9 @@
// drizzle.service.ts // drizzle.service.ts
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { and, eq, sql } from 'drizzle-orm'; import { and, eq, sql } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/libsql'; //import { drizzle } from 'drizzle-orm/libsql';
import { Deck, SelectDeck, User } from '../db/schema'; import { drizzle } from 'drizzle-orm/node-postgres';
import { deck, SelectDeck, User } from '../db/schema';
import { SqlLoggerService } from './sql-logger.service'; import { SqlLoggerService } from './sql-logger.service';
@Injectable() @Injectable()
@ -10,20 +11,27 @@ export class DrizzleService {
// private readonly logger = new Logger(DrizzleService.name); // private readonly logger = new Logger(DrizzleService.name);
private db: any; private db: any;
constructor(private sqlLogger: SqlLoggerService) { constructor(private sqlLogger: SqlLoggerService) {
this.db = drizzle('file:local.db', { // this.db = drizzle('file:local.db', {
// logger: {
// logQuery: (query: string, params: any[]) => {
// this.sqlLogger.logQuery(query, params);
// },
// },
// });
this.db = drizzle('postgresql://haiky:xieng7Seih@localhost:15432/haiky', {
logger: { logger: {
logQuery: (query: string, params: any[]) => { logQuery: (query: string, params: any[]) => {
this.sqlLogger.logQuery(query, params); this.sqlLogger.logQuery(query, params);
}, },
}, },
}); }); //drizzle(process.env.DATABASE_URL);
} }
/** /**
* Methode zum Abrufen aller Decks eines Benutzers * Methode zum Abrufen aller Decks eines Benutzers
*/ */
async getDecks(user: User) { async getDecks(user: User) {
return this.db.select().from(Deck).where(eq(Deck.user, user.email)); return this.db.select().from(deck).where(eq(deck.user, user.email));
} }
/** /**
@ -32,7 +40,7 @@ export class DrizzleService {
async createDeck(deckname: string, user: User) { async createDeck(deckname: string, user: User) {
// 'inserted' und 'updated' werden automatisch von der Datenbank gesetzt // 'inserted' und 'updated' werden automatisch von der Datenbank gesetzt
const result = await this.db const result = await this.db
.insert(Deck) .insert(deck)
.values({ .values({
deckname, deckname,
user: user.email, user: user.email,
@ -48,8 +56,8 @@ export class DrizzleService {
async getDeckByName(deckname: string, user: User) { async getDeckByName(deckname: string, user: User) {
return this.db return this.db
.select() .select()
.from(Deck) .from(deck)
.where(and(eq(Deck.deckname, deckname), eq(Deck.user, user.email))); .where(and(eq(deck.deckname, deckname), eq(deck.user, user.email)));
} }
/** /**
@ -61,7 +69,7 @@ export class DrizzleService {
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND); throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
} }
await this.db.delete(Deck).where(and(eq(Deck.deckname, deckname), eq(Deck.user, user.email))); await this.db.delete(deck).where(and(eq(deck.deckname, deckname), eq(deck.user, user.email)));
return { status: 'success' }; return { status: 'success' };
} }
@ -80,12 +88,12 @@ export class DrizzleService {
} }
await this.db await this.db
.update(Deck) .update(deck)
.set({ .set({
deckname: newDeckname, deckname: newDeckname,
updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP
}) })
.where(and(eq(Deck.deckname, oldDeckname), eq(Deck.user, user.email))); .where(and(eq(deck.deckname, oldDeckname), eq(deck.user, user.email)));
return { status: 'success', message: 'Deck renamed successfully' }; return { status: 'success', message: 'Deck renamed successfully' };
} }
@ -116,7 +124,7 @@ export class DrizzleService {
for (let index = 0; index < newEntries.length; index++) { for (let index = 0; index < newEntries.length; index++) {
const box = newEntries[index]; const box = newEntries[index];
const result = await this.db const result = await this.db
.insert(Deck) .insert(deck)
.values({ .values({
deckname: data.deckname, deckname: data.deckname,
bildname: data.bildname, bildname: data.bildname,
@ -138,7 +146,7 @@ export class DrizzleService {
const existingDeck = existingDecks.find(d => d.id === box.id); const existingDeck = existingDecks.find(d => d.id === box.id);
if (existingDeck && (existingDeck.x1 !== box.x1 || existingDeck.x2 !== box.x2 || existingDeck.y1 !== box.y1 || existingDeck.y2 !== box.y2)) { if (existingDeck && (existingDeck.x1 !== box.x1 || existingDeck.x2 !== box.x2 || existingDeck.y1 !== box.y1 || existingDeck.y2 !== box.y2)) {
const result = await this.db const result = await this.db
.update(Deck) .update(deck)
.set({ .set({
x1: box.x1, x1: box.x1,
x2: box.x2, x2: box.x2,
@ -146,7 +154,7 @@ export class DrizzleService {
y2: box.y2, y2: box.y2,
updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP
}) })
.where(and(eq(Deck.user, user.email), eq(Deck.bildid, data.bildid), eq(Deck.deckname, data.deckname), eq(Deck.id, box.id!!))); .where(and(eq(deck.user, user.email), eq(deck.bildid, data.bildid), eq(deck.deckname, data.deckname), eq(deck.id, box.id!!)));
if (result.rowsAffected === 0) { if (result.rowsAffected === 0) {
throw new HttpException(`Box with id ${box.id} not found`, HttpStatus.NOT_FOUND); throw new HttpException(`Box with id ${box.id} not found`, HttpStatus.NOT_FOUND);
} }
@ -164,7 +172,7 @@ export class DrizzleService {
const idsToDelete = existingIdsInDb.filter(id => !incomingIds.includes(id)); const idsToDelete = existingIdsInDb.filter(id => !incomingIds.includes(id));
if (idsToDelete.length > 0) { if (idsToDelete.length > 0) {
await this.db.delete(Deck).where(and(eq(Deck.deckname, data.deckname), eq(Deck.bildid, data.bildid), eq(Deck.user, user.email), sql`id in ${idsToDelete}`)); await this.db.delete(deck).where(and(eq(deck.deckname, data.deckname), eq(deck.bildid, data.bildid), eq(deck.user, user.email), sql`id in ${idsToDelete}`));
} }
return { status: 'success', inserted_images: insertedImages }; return { status: 'success', inserted_images: insertedImages };
@ -175,16 +183,16 @@ export class DrizzleService {
*/ */
async deleteImagesByBildId(bildid: string, user: User) { async deleteImagesByBildId(bildid: string, user: User) {
const affectedDecks = await this.db const affectedDecks = await this.db
.select({ deckname: Deck.deckname }) .select({ deckname: deck.deckname })
.from(Deck) .from(deck)
.where(and(eq(Deck.bildid, bildid), eq(Deck.user, user.email))) .where(and(eq(deck.bildid, bildid), eq(deck.user, user.email)))
.all(); .all();
if (affectedDecks.length === 0) { if (affectedDecks.length === 0) {
throw new HttpException('No entries found for the given image ID', HttpStatus.NOT_FOUND); throw new HttpException('No entries found for the given image ID', HttpStatus.NOT_FOUND);
} }
await this.db.delete(Deck).where(and(eq(Deck.bildid, bildid), eq(Deck.user, user.email))); await this.db.delete(deck).where(and(eq(deck.bildid, bildid), eq(deck.user, user.email)));
return { return {
status: 'success', status: 'success',
@ -198,8 +206,8 @@ export class DrizzleService {
async moveImage(bildid: string, targetDeckId: string, user: User) { async moveImage(bildid: string, targetDeckId: string, user: User) {
const existingImages = await this.db const existingImages = await this.db
.select() .select()
.from(Deck) .from(deck)
.where(and(eq(Deck.bildid, bildid), eq(Deck.user, user.email))) .where(and(eq(deck.bildid, bildid), eq(deck.user, user.email)))
.all(); .all();
if (existingImages.length === 0) { if (existingImages.length === 0) {
@ -207,12 +215,12 @@ export class DrizzleService {
} }
await this.db await this.db
.update(Deck) .update(deck)
.set({ .set({
deckname: targetDeckId, deckname: targetDeckId,
updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP
}) })
.where(and(eq(Deck.bildid, bildid), eq(Deck.user, user.email))); .where(and(eq(deck.bildid, bildid), eq(deck.user, user.email)));
return { status: 'success', moved_entries: existingImages.length }; return { status: 'success', moved_entries: existingImages.length };
} }
@ -222,8 +230,8 @@ export class DrizzleService {
async renameImage(bildId: string, newImagename: string, user: User) { async renameImage(bildId: string, newImagename: string, user: User) {
const existingImages = this.db const existingImages = this.db
.select() .select()
.from(Deck) .from(deck)
.where(and(eq(Deck.bildid, bildId), eq(Deck.user, user.email))); .where(and(eq(deck.bildid, bildId), eq(deck.user, user.email)));
if (existingImages.length === 0) { if (existingImages.length === 0) {
throw new HttpException('Deck not found', HttpStatus.NOT_FOUND); throw new HttpException('Deck not found', HttpStatus.NOT_FOUND);
} }
@ -234,12 +242,12 @@ export class DrizzleService {
// } // }
await this.db await this.db
.update(Deck) .update(deck)
.set({ .set({
bildname: newImagename, bildname: newImagename,
updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP updated: sql`CURRENT_TIMESTAMP`, // Setze 'updated' auf CURRENT_TIMESTAMP
}) })
.where(and(eq(Deck.bildid, bildId), eq(Deck.user, user.email))); .where(and(eq(deck.bildid, bildId), eq(deck.user, user.email)));
return { status: 'success', message: 'Image Entries renamed successfully' }; return { status: 'success', message: 'Image Entries renamed successfully' };
} }
/** /**
@ -264,9 +272,9 @@ export class DrizzleService {
updateData.updated = sql`CURRENT_TIMESTAMP`; // Setze 'updated' auf CURRENT_TIMESTAMP updateData.updated = sql`CURRENT_TIMESTAMP`; // Setze 'updated' auf CURRENT_TIMESTAMP
const result = await this.db const result = await this.db
.update(Deck) .update(deck)
.set(updateData) .set(updateData)
.where(and(eq(Deck.id, id), eq(Deck.user, user.email))); .where(and(eq(deck.id, id), eq(deck.user, user.email)));
if (result.rowsAffected === 0) { if (result.rowsAffected === 0) {
throw new HttpException('Box not found', HttpStatus.NOT_FOUND); throw new HttpException('Box not found', HttpStatus.NOT_FOUND);
@ -280,7 +288,7 @@ export class DrizzleService {
*/ */
async getDistinctBildIds(user: User): Promise<string[]> { async getDistinctBildIds(user: User): Promise<string[]> {
try { try {
const result = await this.db.selectDistinct([Deck.bildid]).from(Deck).all(); const result = await this.db.selectDistinct([deck.bildid]).from(deck).all();
// Extrahiere die bildid Werte aus dem Ergebnis // Extrahiere die bildid Werte aus dem Ergebnis
const usedIds = result.map((row: any) => row['0']).filter((id: string | null) => id !== null) as string[]; const usedIds = result.map((row: any) => row['0']).filter((id: string | null) => id !== null) as string[];

View File

@ -1,37 +1,45 @@
import { sql } from 'drizzle-orm'; import { sql } from 'drizzle-orm';
import * as t from 'drizzle-orm/sqlite-core'; import * as t from 'drizzle-orm/pg-core';
import { integer, real, sqliteTable as table, text } from 'drizzle-orm/sqlite-core'; import { pgEnum, pgTable as table } from 'drizzle-orm/pg-core';
export const Deck = table( export const rolesEnum = pgEnum('roles', ['admin', 'guest', 'pro']);
'Deck',
export const deck = table(
'deck',
{ {
id: integer('id').primaryKey({ autoIncrement: true }), id: t.integer('id').primaryKey().generatedAlwaysAsIdentity(),
deckname: text('deckname').notNull(), deckname: t.varchar('deckname').notNull(),
bildname: text('bildname'), bildname: t.varchar('bildname'),
bildid: text('bildid'), bildid: t.varchar('bildid'),
x1: real('x1'), x1: t.real('x1'),
x2: real('x2'), x2: t.real('x2'),
y1: real('y1'), y1: t.real('y1'),
y2: real('y2'), y2: t.real('y2'),
due: integer('due'), due: t.integer('due'),
ivl: real('ivl'), ivl: t.real('ivl'),
factor: real('factor'), factor: t.real('factor'),
reps: integer('reps'), reps: t.integer('reps'),
lapses: integer('lapses'), lapses: t.integer('lapses'),
isGraduated: integer('isGraduated'), isGraduated: t.integer('isgraduated'),
user: text('user').notNull(), user: t.varchar('user').notNull(),
inserted: text().default(sql`(CURRENT_TIMESTAMP)`), // Neue Spalte inserted: t.varchar().default(sql`(CURRENT_TIMESTAMP)`), // Neue Spalte
updated: text().default(sql`(CURRENT_TIMESTAMP)`), // Neue Spalte updated: t.varchar().default(sql`(CURRENT_TIMESTAMP)`), // Neue Spalte
},
table => {
return {
index: t.uniqueIndex('email_idx').on(table.id),
};
}, },
table => [t.uniqueIndex('deck_idx').on(table.id)],
); );
export const users = table(
export type InsertDeck = typeof Deck.$inferInsert; 'users',
export type SelectDeck = typeof Deck.$inferSelect; {
id: t.integer().primaryKey().generatedAlwaysAsIdentity(),
name: t.varchar('name', { length: 256 }),
email: t.varchar().notNull(),
role: rolesEnum().default('guest'),
sign_in_provider: t.varchar('sign_in_provider', { length: 50 }),
},
table => [t.uniqueIndex('users_idx').on(table.id)],
);
export type InsertDeck = typeof deck.$inferInsert;
export type SelectDeck = typeof deck.$inferSelect;
export interface User { export interface User {
name: string; name: string;
picture: string; picture: string;

View File

@ -3,8 +3,8 @@ import { defineConfig } from 'drizzle-kit';
export default defineConfig({ export default defineConfig({
out: './drizzle', out: './drizzle',
schema: './api/src/db/schema.ts', schema: './api/src/db/schema.ts',
dialect: 'sqlite', dialect: 'postgresql',
dbCredentials: { dbCredentials: {
url: 'file:local1.db', url: process.env['DATABASE_URL'],
}, },
}); });

View File

@ -1,19 +0,0 @@
CREATE TABLE `Deck` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`deckname` text NOT NULL,
`bildname` text,
`bildid` text,
`iconindex` integer,
`x1` real,
`x2` real,
`y1` real,
`y2` real,
`due` integer,
`ivl` real,
`factor` real,
`reps` integer,
`lapses` integer,
`isGraduated` integer
);
--> statement-breakpoint
CREATE UNIQUE INDEX `email_idx` ON `Deck` (`id`);

View File

@ -0,0 +1,31 @@
CREATE TYPE "public"."roles" AS ENUM('admin', 'guest', 'pro');--> statement-breakpoint
CREATE TABLE "Deck" (
"id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "Deck_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
"deckname" varchar NOT NULL,
"bildname" varchar,
"bildid" varchar,
"x1" real,
"x2" real,
"y1" real,
"y2" real,
"due" integer,
"ivl" real,
"factor" real,
"reps" integer,
"lapses" integer,
"isGraduated" integer,
"user" varchar NOT NULL,
"inserted" varchar DEFAULT (CURRENT_TIMESTAMP),
"updated" varchar DEFAULT (CURRENT_TIMESTAMP)
);
--> statement-breakpoint
CREATE TABLE "users" (
"id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "users_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
"name" varchar(256),
"email" varchar NOT NULL,
"role" "roles" DEFAULT 'guest',
"sign_in_provider" varchar(50)
);
--> statement-breakpoint
CREATE UNIQUE INDEX "deck_idx" ON "Deck" USING btree ("id");--> statement-breakpoint
CREATE UNIQUE INDEX "users_idx" ON "users" USING btree ("id");

View File

@ -1 +0,0 @@
ALTER TABLE `Deck` ADD `user` text NOT NULL;

View File

@ -1,2 +0,0 @@
ALTER TABLE `Deck` ADD `inserted` text DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
ALTER TABLE `Deck` ADD `updated` text DEFAULT (CURRENT_TIMESTAMP);

View File

@ -1 +0,0 @@
ALTER TABLE `Deck` DROP COLUMN `iconindex`;

View File

@ -1,141 +1,245 @@
{ {
"version": "6", "id": "ad8762e3-d7ad-4605-b2fc-b10a0de0f08a",
"dialect": "sqlite",
"id": "3996df1c-a197-4842-869e-2e3b4f10064a",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": { "tables": {
"Deck": { "public.Deck": {
"name": "Deck", "name": "Deck",
"schema": "",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
"type": "integer", "type": "integer",
"primaryKey": true, "primaryKey": true,
"notNull": true, "notNull": true,
"autoincrement": true "identity": {
"type": "always",
"name": "Deck_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
}, },
"deckname": { "deckname": {
"name": "deckname", "name": "deckname",
"type": "text", "type": "varchar",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"autoincrement": false
}, },
"bildname": { "bildname": {
"name": "bildname", "name": "bildname",
"type": "text", "type": "varchar",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"bildid": { "bildid": {
"name": "bildid", "name": "bildid",
"type": "text", "type": "varchar",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
},
"iconindex": {
"name": "iconindex",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}, },
"x1": { "x1": {
"name": "x1", "name": "x1",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"x2": { "x2": {
"name": "x2", "name": "x2",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"y1": { "y1": {
"name": "y1", "name": "y1",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"y2": { "y2": {
"name": "y2", "name": "y2",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"due": { "due": {
"name": "due", "name": "due",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"ivl": { "ivl": {
"name": "ivl", "name": "ivl",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"factor": { "factor": {
"name": "factor", "name": "factor",
"type": "real", "type": "real",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"reps": { "reps": {
"name": "reps", "name": "reps",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"lapses": { "lapses": {
"name": "lapses", "name": "lapses",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false
"autoincrement": false
}, },
"isGraduated": { "isGraduated": {
"name": "isGraduated", "name": "isGraduated",
"type": "integer", "type": "integer",
"primaryKey": false, "primaryKey": false,
"notNull": false
},
"user": {
"name": "user",
"type": "varchar",
"primaryKey": false,
"notNull": true
},
"inserted": {
"name": "inserted",
"type": "varchar",
"primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "default": "(CURRENT_TIMESTAMP)"
},
"updated": {
"name": "updated",
"type": "varchar",
"primaryKey": false,
"notNull": false,
"default": "(CURRENT_TIMESTAMP)"
} }
}, },
"indexes": { "indexes": {
"email_idx": { "deck_idx": {
"name": "email_idx", "name": "deck_idx",
"columns": [ "columns": [
"id" {
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
], ],
"isUnique": true "isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
} }
}, },
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {}, "uniqueConstraints": {},
"checkConstraints": {} "policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "users_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
},
"name": {
"name": "name",
"type": "varchar(256)",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "varchar",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "roles",
"typeSchema": "public",
"primaryKey": false,
"notNull": false,
"default": "'guest'"
},
"sign_in_provider": {
"name": "sign_in_provider",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"users_idx": {
"name": "users_idx",
"columns": [
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
} }
}, },
"views": {}, "enums": {
"enums": {}, "public.roles": {
"_meta": { "name": "roles",
"schemas": {}, "schema": "public",
"tables": {}, "values": [
"columns": {} "admin",
"guest",
"pro"
]
}
}, },
"internal": { "schemas": {},
"indexes": {} "sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
} }
} }

View File

@ -1,148 +0,0 @@
{
"version": "6",
"dialect": "sqlite",
"id": "a3cf5e86-4f1b-4cdc-9688-cf9063ba6936",
"prevId": "3996df1c-a197-4842-869e-2e3b4f10064a",
"tables": {
"Deck": {
"name": "Deck",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"deckname": {
"name": "deckname",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"bildname": {
"name": "bildname",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"bildid": {
"name": "bildid",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"iconindex": {
"name": "iconindex",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"x1": {
"name": "x1",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"x2": {
"name": "x2",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"y1": {
"name": "y1",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"y2": {
"name": "y2",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"due": {
"name": "due",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"ivl": {
"name": "ivl",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"factor": {
"name": "factor",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"reps": {
"name": "reps",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"lapses": {
"name": "lapses",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"isGraduated": {
"name": "isGraduated",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user": {
"name": "user",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"email_idx": {
"name": "email_idx",
"columns": [
"id"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -1,164 +0,0 @@
{
"version": "6",
"dialect": "sqlite",
"id": "1e5421d8-df58-434e-93c8-85dcbe6ec9ee",
"prevId": "a3cf5e86-4f1b-4cdc-9688-cf9063ba6936",
"tables": {
"Deck": {
"name": "Deck",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"deckname": {
"name": "deckname",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"bildname": {
"name": "bildname",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"bildid": {
"name": "bildid",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"iconindex": {
"name": "iconindex",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"x1": {
"name": "x1",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"x2": {
"name": "x2",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"y1": {
"name": "y1",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"y2": {
"name": "y2",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"due": {
"name": "due",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"ivl": {
"name": "ivl",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"factor": {
"name": "factor",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"reps": {
"name": "reps",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"lapses": {
"name": "lapses",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"isGraduated": {
"name": "isGraduated",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user": {
"name": "user",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"inserted": {
"name": "inserted",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated": {
"name": "updated",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {
"email_idx": {
"name": "email_idx",
"columns": [
"id"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -1,157 +0,0 @@
{
"version": "6",
"dialect": "sqlite",
"id": "a0b561cf-8404-43ea-bc72-8b32671580bd",
"prevId": "1e5421d8-df58-434e-93c8-85dcbe6ec9ee",
"tables": {
"Deck": {
"name": "Deck",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"deckname": {
"name": "deckname",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"bildname": {
"name": "bildname",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"bildid": {
"name": "bildid",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"x1": {
"name": "x1",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"x2": {
"name": "x2",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"y1": {
"name": "y1",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"y2": {
"name": "y2",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"due": {
"name": "due",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"ivl": {
"name": "ivl",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"factor": {
"name": "factor",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"reps": {
"name": "reps",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"lapses": {
"name": "lapses",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"isGraduated": {
"name": "isGraduated",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user": {
"name": "user",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"inserted": {
"name": "inserted",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated": {
"name": "updated",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {
"email_idx": {
"name": "email_idx",
"columns": [
"id"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -1,33 +1,12 @@
{ {
"version": "7", "version": "7",
"dialect": "sqlite", "dialect": "postgresql",
"entries": [ "entries": [
{ {
"idx": 0, "idx": 0,
"version": "6", "version": "7",
"when": 1737229773082, "when": 1738881267759,
"tag": "0000_ambitious_hercules", "tag": "0000_dapper_the_watchers",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1737229845910,
"tag": "0001_smooth_iron_lad",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1738103858394,
"tag": "0002_aromatic_zodiak",
"breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1738235979220,
"tag": "0003_hard_cable",
"breakpoints": true "breakpoints": true
} }
] ]

246
package-lock.json generated
View File

@ -28,6 +28,7 @@
"firebase-admin": "^13.0.2", "firebase-admin": "^13.0.2",
"flowbite": "^2.5.2", "flowbite": "^2.5.2",
"http-server": "^14.1.1", "http-server": "^14.1.1",
"pg": "^8.13.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
@ -54,10 +55,11 @@
"@swc/helpers": "~0.5.11", "@swc/helpers": "~0.5.11",
"@types/fabric": "^5.3.9", "@types/fabric": "^5.3.9",
"@types/node": "~18.16.9", "@types/node": "~18.16.9",
"@types/pg": "^8.11.11",
"chalk": "^5.4.1", "chalk": "^5.4.1",
"concurrently": "^9.1.2", "concurrently": "^9.1.2",
"drizzle-kit": "^0.30.2", "drizzle-kit": "^0.30.4",
"drizzle-orm": "^0.38.4", "drizzle-orm": "^0.39.2",
"nx": "20.3.2", "nx": "20.3.2",
"prettier": "^2.6.2", "prettier": "^2.6.2",
"tailwindcss": "^3.4.15", "tailwindcss": "^3.4.15",
@ -10318,6 +10320,80 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/pg": {
"version": "8.11.11",
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.11.tgz",
"integrity": "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*",
"pg-protocol": "*",
"pg-types": "^4.0.1"
}
},
"node_modules/@types/pg/node_modules/pg-types": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz",
"integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==",
"dev": true,
"license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"pg-numeric": "1.0.2",
"postgres-array": "~3.0.1",
"postgres-bytea": "~3.0.0",
"postgres-date": "~2.1.0",
"postgres-interval": "^3.0.0",
"postgres-range": "^1.1.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@types/pg/node_modules/postgres-array": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz",
"integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
}
},
"node_modules/@types/pg/node_modules/postgres-bytea": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz",
"integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==",
"dev": true,
"license": "MIT",
"dependencies": {
"obuf": "~1.1.2"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/@types/pg/node_modules/postgres-date": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz",
"integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
}
},
"node_modules/@types/pg/node_modules/postgres-interval": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz",
"integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
}
},
"node_modules/@types/qs": { "node_modules/@types/qs": {
"version": "6.9.17", "version": "6.9.17",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz",
@ -13812,9 +13888,9 @@
} }
}, },
"node_modules/drizzle-kit": { "node_modules/drizzle-kit": {
"version": "0.30.2", "version": "0.30.4",
"resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.30.2.tgz", "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.30.4.tgz",
"integrity": "sha512-vhdLrxWA32WNVF77NabpSnX7pQBornx64VDQDmKddRonOB2Xe/yY4glQ7rECoa+ogqcQNo7VblLUbeBK6Zn9Ow==", "integrity": "sha512-B2oJN5UkvwwNHscPWXDG5KqAixu7AUzZ3qbe++KU9SsQ+cZWR4DXEPYcvWplyFAno0dhRJECNEhNxiDmFaPGyQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -14258,9 +14334,9 @@
} }
}, },
"node_modules/drizzle-orm": { "node_modules/drizzle-orm": {
"version": "0.38.4", "version": "0.39.2",
"resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.38.4.tgz", "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.39.2.tgz",
"integrity": "sha512-s7/5BpLKO+WJRHspvpqTydxFob8i1vo2rEx4pY6TGY7QSMuUfWUuzaY0DIpXCkgHOo37BaFC+SJQb99dDUXT3Q==", "integrity": "sha512-cuopo+udkKEGGpSxCML9ZRQ43R01zYCTsbqCrb9kJkabx1QEwFlPIFoQfx6E6tuawtiX930Gwyrkwj4inlpzDg==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peerDependencies": { "peerDependencies": {
@ -22790,6 +22866,105 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/pg": {
"version": "8.13.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz",
"integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==",
"license": "MIT",
"dependencies": {
"pg-connection-string": "^2.7.0",
"pg-pool": "^3.7.0",
"pg-protocol": "^1.7.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
},
"engines": {
"node": ">= 8.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.1.1"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
"integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
"license": "MIT",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz",
"integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==",
"license": "MIT"
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"license": "ISC",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-numeric": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz",
"integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=4"
}
},
"node_modules/pg-pool": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz",
"integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==",
"license": "MIT",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz",
"integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==",
"license": "MIT"
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"license": "MIT",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -23680,6 +23855,52 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-range": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz",
"integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==",
"dev": true,
"license": "MIT"
},
"node_modules/prelude-ls": { "node_modules/prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -25283,6 +25504,15 @@
"wbuf": "^1.7.3" "wbuf": "^1.7.3"
} }
}, },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/sprintf-js": { "node_modules/sprintf-js": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",

View File

@ -30,6 +30,7 @@
"firebase-admin": "^13.0.2", "firebase-admin": "^13.0.2",
"flowbite": "^2.5.2", "flowbite": "^2.5.2",
"http-server": "^14.1.1", "http-server": "^14.1.1",
"pg": "^8.13.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
@ -56,10 +57,11 @@
"@swc/helpers": "~0.5.11", "@swc/helpers": "~0.5.11",
"@types/fabric": "^5.3.9", "@types/fabric": "^5.3.9",
"@types/node": "~18.16.9", "@types/node": "~18.16.9",
"@types/pg": "^8.11.11",
"chalk": "^5.4.1", "chalk": "^5.4.1",
"concurrently": "^9.1.2", "concurrently": "^9.1.2",
"drizzle-kit": "^0.30.2", "drizzle-kit": "^0.30.4",
"drizzle-orm": "^0.38.4", "drizzle-orm": "^0.39.2",
"nx": "20.3.2", "nx": "20.3.2",
"prettier": "^2.6.2", "prettier": "^2.6.2",
"tailwindcss": "^3.4.15", "tailwindcss": "^3.4.15",
@ -67,4 +69,4 @@
"typescript": "~5.5.2", "typescript": "~5.5.2",
"webpack-cli": "^5.1.4" "webpack-cli": "^5.1.4"
} }
} }