From fa73708d9779c23ce4553dcab2e004a8712117f4 Mon Sep 17 00:00:00 2001 From: Zimeng Xiong Date: Mon, 24 Nov 2025 14:32:37 -0800 Subject: [PATCH] allow importing of libraries via URL, update db schema --- .../migration.sql | 7 + backend/prisma/prisma/dev.db | Bin 36864 -> 36864 bytes backend/prisma/prisma/dev.db-journal | Bin 12824 -> 12824 bytes backend/prisma/schema.prisma | 7 + backend/src/generated/client/edge.js | 17 +- backend/src/generated/client/index-browser.js | 10 +- backend/src/generated/client/index.d.ts | 1085 ++++++++++++++++- backend/src/generated/client/index.js | 17 +- backend/src/generated/client/package.json | 2 +- backend/src/generated/client/schema.prisma | 7 + backend/src/generated/client/wasm.js | 10 +- backend/src/index.ts | 52 + frontend/src/api/index.ts | 12 + frontend/src/pages/Editor.tsx | 91 +- 14 files changed, 1301 insertions(+), 16 deletions(-) create mode 100644 backend/prisma/migrations/20251124220546_add_library_model/migration.sql diff --git a/backend/prisma/migrations/20251124220546_add_library_model/migration.sql b/backend/prisma/migrations/20251124220546_add_library_model/migration.sql new file mode 100644 index 0000000..24dda6e --- /dev/null +++ b/backend/prisma/migrations/20251124220546_add_library_model/migration.sql @@ -0,0 +1,7 @@ +-- CreateTable +CREATE TABLE "Library" ( + "id" TEXT NOT NULL PRIMARY KEY DEFAULT 'default', + "items" TEXT NOT NULL DEFAULT '[]', + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); diff --git a/backend/prisma/prisma/dev.db b/backend/prisma/prisma/dev.db index 78817f79d6a0c86760b99c380558f330d3757ce9..6d2ea4ca5301cdc2caa89081b0360d3831b72413 100644 GIT binary patch delta 485 zcmZozz|^pSX@ayMHv{ zfXj8WpulnV&CVRWjK+;cob2M#(u~d4C5cHnsXm!WMTtd~P>Rht$kj2#RUyRD$;VYe z2`W1IKaZNMf{Ux0W2jGvf_h47T4HHViMkG#0uU%=mZauRj^&nOj*eBIe33iBkV{jS zi%r~7nvo$hFD132xG)E(BtEgUBp=L=hngC12xYKuF5#NM%EQ9DfPue&?gD2 zSejcJS(+wV0tHNx&C(1LQ&Wr$Qj<(m6H|G!voZoLWCIGl=bsqBx+#ELU^BPDSAGC! CNhLo3 diff --git a/backend/prisma/prisma/dev.db-journal b/backend/prisma/prisma/dev.db-journal index 1b10b30333405bc314ada468b61c8540de76a966..d187e71bd0863ce407b587a572cd0e1eb816b197 100644 GIT binary patch literal 12824 zcmeI2&2Jk;6u@_rG;R#094bZ716x<3jl`n)*snPtVVrFh)p3gLh<<>U+4)FUwH>qG zv{Z;g)C%<<;L;01NF2DK9{2;`#2m3&Du`lM!irKsWZ}Q*Yn=I_vSax zZ&n@~hHfu8frXj^uvGirI5T?f_t)N254vdrnt&#t31|YEfF_^`XabsmCZGwtKmz+` zm#W+QHDl8-POT8)Bf$Z;DU!bJNJedf5wt}h5o82o;c(&;L|jT#hr>Jxso)rh*cFsx zM!i7BAa-z!pzA{rPzni>5OM4f;PW_k5kM}4$Uz9Wju%nRqka;nG`$}UcDd-AkAM2( z*H8D~Sj@vZbu|ww_5(*!hHQy2vK^`dB!YQ1kxU8#0Ow3{i9JWgZp@KnF=B`XUI08G zxyN8ES>VLn;lPoEASZDAn8uU{OmRT4Kt!02e|+ogCuML5c&_8RMQ}3di*dwu`+I|7 zq4e?o*@YsuMjjjDOj&S!8vu{l4iO4j;1N6UV1Pm36NX(kh#g7-3Ji)7*U)-*PZl;I+_Q7Y~x;$9)YxnDDjuy7t0 z_hJ$&k2Z1%wjDryo4C@o9Smh2q{9WI%w-A=p~9Ec2NHNO^96<;V!(sG!~}aZ&H*AW z0*VM?oUqsf+((4C=)mnXECfB5M9DD83c+=U|MIm;>`Iy3rn)b`z(m)sH33aP6VL=S z0Zl*?&;&FAO+XXS1T+Cn;5ia_(E8_3W!~(5*h(^C$=!57GYcE98>VTzZ&^yVQeOFQ z1qXLyxDMov_ghtzP4UR%q2r zg}QaAYN=LFc-`uS*LzlbOI_QomUXSOvDxU{u&#zT-Z{`2(t$XpRZ2u(48$-SKV3>k zqi#mC6UG*&Nyi3S>*3|bcB^My{Nl@trH}Gt=RmXUyDQRhvOBC>8|_|rCG5NBqVY?UQ(r&M@d9570H{vG_K2T|H zwY$AeL&Y~`o}ZjeV~OM)aldX|-s*%KSK2vj>r(x&LVeBZgqK6*z8Q9{dUHBfEnU89 zYt~j<;cA6yZM$K)cB*UpT0R}C+2}SK>tS`xJ-xiTaltffb#I(AjbzBh=i|@%>IF2S zd)aRBd6G8~Ec0XK;hQSA&Yhd&R@q(NbWTmz@km;-mn5f#JC*%gi)TytKS}<@`xsmf1`qID0tSSw2Rp^7~%VUsF%Td+Ihy+QrxxFZ$6RF&$ydVE{(h^mq} zYm?$wYE5So9qbCF;?oTFcX!mrFxPU`(pZ`oH6F#3-8t;_n9FfSQ&p)CYve{JTGJ^{ zHxIU#rfOG;vSc9C;K8VLr}m?Mq702QG0OkPus1AbI@v?E+g(+P!}WQCpt{yvSYG`I ao|F;u3m3upzD4ymaXNpac=F8;fBg%>_U14E delta 92 zcmbP{G9zUJ2NM@FpECo00pCqN=go>jrhFWY!pvNujl2w#Jq0p1?-1}|hBd7 diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index bd3369f..23da027 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -33,3 +33,10 @@ model Drawing { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } + +model Library { + id String @id @default("default") // Singleton pattern - use "default" ID + items String @default("[]") // Stored as JSON string array of library items + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/backend/src/generated/client/edge.js b/backend/src/generated/client/edge.js index 93c2a87..ded6d83 100644 --- a/backend/src/generated/client/edge.js +++ b/backend/src/generated/client/edge.js @@ -107,6 +107,13 @@ exports.Prisma.DrawingScalarFieldEnum = { updatedAt: 'updatedAt' }; +exports.Prisma.LibraryScalarFieldEnum = { + id: 'id', + items: 'items', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + exports.Prisma.SortOrder = { asc: 'asc', desc: 'desc' @@ -120,7 +127,8 @@ exports.Prisma.NullsOrder = { exports.Prisma.ModelName = { Collection: 'Collection', - Drawing: 'Drawing' + Drawing: 'Drawing', + Library: 'Library' }; /** * Create the Client @@ -169,7 +177,6 @@ const config = { "db" ], "activeProvider": "sqlite", - "postinstall": false, "inlineDatasources": { "db": { "url": { @@ -178,13 +185,13 @@ const config = { } } }, - "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"../src/generated/client\"\n binaryTargets = [\"native\", \"linux-musl-arm64-openssl-3.0.x\", \"linux-musl-openssl-3.0.x\"]\n}\n\ndatasource db {\n provider = \"sqlite\"\n url = env(\"DATABASE_URL\")\n}\n\nmodel Collection {\n id String @id @default(uuid())\n name String\n drawings Drawing[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Drawing {\n id String @id @default(uuid())\n name String\n elements String // Stored as JSON string\n appState String // Stored as JSON string\n files String @default(\"{}\") // Stored as JSON string\n preview String? // SVG string for thumbnail\n version Int @default(1)\n collectionId String?\n collection Collection? @relation(fields: [collectionId], references: [id])\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", - "inlineSchemaHash": "30da526c2a5efdf3e5097c3736a52d47246ca4da8e5bd0401a3f28dd46ab5c3e", + "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"../src/generated/client\"\n binaryTargets = [\"native\", \"linux-musl-arm64-openssl-3.0.x\", \"linux-musl-openssl-3.0.x\"]\n}\n\ndatasource db {\n provider = \"sqlite\"\n url = env(\"DATABASE_URL\")\n}\n\nmodel Collection {\n id String @id @default(uuid())\n name String\n drawings Drawing[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Drawing {\n id String @id @default(uuid())\n name String\n elements String // Stored as JSON string\n appState String // Stored as JSON string\n files String @default(\"{}\") // Stored as JSON string\n preview String? // SVG string for thumbnail\n version Int @default(1)\n collectionId String?\n collection Collection? @relation(fields: [collectionId], references: [id])\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Library {\n id String @id @default(\"default\") // Singleton pattern - use \"default\" ID\n items String @default(\"[]\") // Stored as JSON string array of library items\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", + "inlineSchemaHash": "a6a8e55dadb0695c66246575cd1a63af3afd912ce070b4798d2e56269d371c87", "copyEngine": true } config.dirname = '/' -config.runtimeDataModel = JSON.parse("{\"models\":{\"Collection\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"drawings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Drawing\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Drawing\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"elements\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"appState\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"files\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"{}\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"preview\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"version\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collectionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collection\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Collection\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[\"collectionId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"Collection\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"drawings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Drawing\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Drawing\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"elements\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"appState\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"files\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"{}\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"preview\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"version\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collectionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collection\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Collection\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[\"collectionId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Library\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"default\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"items\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"[]\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{},\"types\":{}}") defineDmmfProperty(exports.Prisma, config.runtimeDataModel) config.engineWasm = undefined diff --git a/backend/src/generated/client/index-browser.js b/backend/src/generated/client/index-browser.js index 6d1f1d8..d303df9 100644 --- a/backend/src/generated/client/index-browser.js +++ b/backend/src/generated/client/index-browser.js @@ -139,6 +139,13 @@ exports.Prisma.DrawingScalarFieldEnum = { updatedAt: 'updatedAt' }; +exports.Prisma.LibraryScalarFieldEnum = { + id: 'id', + items: 'items', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + exports.Prisma.SortOrder = { asc: 'asc', desc: 'desc' @@ -152,7 +159,8 @@ exports.Prisma.NullsOrder = { exports.Prisma.ModelName = { Collection: 'Collection', - Drawing: 'Drawing' + Drawing: 'Drawing', + Library: 'Library' }; /** diff --git a/backend/src/generated/client/index.d.ts b/backend/src/generated/client/index.d.ts index eec957f..bca9643 100644 --- a/backend/src/generated/client/index.d.ts +++ b/backend/src/generated/client/index.d.ts @@ -23,6 +23,11 @@ export type Collection = $Result.DefaultSelection * */ export type Drawing = $Result.DefaultSelection +/** + * Model Library + * + */ +export type Library = $Result.DefaultSelection /** * ## Prisma Client ʲˢ @@ -166,6 +171,16 @@ export class PrismaClient< * ``` */ get drawing(): Prisma.DrawingDelegate; + + /** + * `prisma.library`: Exposes CRUD operations for the **Library** model. + * Example usage: + * ```ts + * // Fetch zero or more Libraries + * const libraries = await prisma.library.findMany() + * ``` + */ + get library(): Prisma.LibraryDelegate; } export namespace Prisma { @@ -608,7 +623,8 @@ export namespace Prisma { export const ModelName: { Collection: 'Collection', - Drawing: 'Drawing' + Drawing: 'Drawing', + Library: 'Library' }; export type ModelName = (typeof ModelName)[keyof typeof ModelName] @@ -624,7 +640,7 @@ export namespace Prisma { export type TypeMap = { meta: { - modelProps: "collection" | "drawing" + modelProps: "collection" | "drawing" | "library" txIsolationLevel: Prisma.TransactionIsolationLevel } model: { @@ -768,6 +784,76 @@ export namespace Prisma { } } } + Library: { + payload: Prisma.$LibraryPayload + fields: Prisma.LibraryFieldRefs + operations: { + findUnique: { + args: Prisma.LibraryFindUniqueArgs + result: $Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.LibraryFindUniqueOrThrowArgs + result: $Utils.PayloadToResult + } + findFirst: { + args: Prisma.LibraryFindFirstArgs + result: $Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.LibraryFindFirstOrThrowArgs + result: $Utils.PayloadToResult + } + findMany: { + args: Prisma.LibraryFindManyArgs + result: $Utils.PayloadToResult[] + } + create: { + args: Prisma.LibraryCreateArgs + result: $Utils.PayloadToResult + } + createMany: { + args: Prisma.LibraryCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.LibraryCreateManyAndReturnArgs + result: $Utils.PayloadToResult[] + } + delete: { + args: Prisma.LibraryDeleteArgs + result: $Utils.PayloadToResult + } + update: { + args: Prisma.LibraryUpdateArgs + result: $Utils.PayloadToResult + } + deleteMany: { + args: Prisma.LibraryDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.LibraryUpdateManyArgs + result: BatchPayload + } + upsert: { + args: Prisma.LibraryUpsertArgs + result: $Utils.PayloadToResult + } + aggregate: { + args: Prisma.LibraryAggregateArgs + result: $Utils.Optional + } + groupBy: { + args: Prisma.LibraryGroupByArgs + result: $Utils.Optional[] + } + count: { + args: Prisma.LibraryCountArgs + result: $Utils.Optional | number + } + } + } } } & { other: { @@ -2933,6 +3019,870 @@ export namespace Prisma { } + /** + * Model Library + */ + + export type AggregateLibrary = { + _count: LibraryCountAggregateOutputType | null + _min: LibraryMinAggregateOutputType | null + _max: LibraryMaxAggregateOutputType | null + } + + export type LibraryMinAggregateOutputType = { + id: string | null + items: string | null + createdAt: Date | null + updatedAt: Date | null + } + + export type LibraryMaxAggregateOutputType = { + id: string | null + items: string | null + createdAt: Date | null + updatedAt: Date | null + } + + export type LibraryCountAggregateOutputType = { + id: number + items: number + createdAt: number + updatedAt: number + _all: number + } + + + export type LibraryMinAggregateInputType = { + id?: true + items?: true + createdAt?: true + updatedAt?: true + } + + export type LibraryMaxAggregateInputType = { + id?: true + items?: true + createdAt?: true + updatedAt?: true + } + + export type LibraryCountAggregateInputType = { + id?: true + items?: true + createdAt?: true + updatedAt?: true + _all?: true + } + + export type LibraryAggregateArgs = { + /** + * Filter which Library to aggregate. + */ + where?: LibraryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Libraries to fetch. + */ + orderBy?: LibraryOrderByWithRelationInput | LibraryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: LibraryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Libraries from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Libraries. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned Libraries + **/ + _count?: true | LibraryCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: LibraryMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: LibraryMaxAggregateInputType + } + + export type GetLibraryAggregateType = { + [P in keyof T & keyof AggregateLibrary]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : GetScalarType + : GetScalarType + } + + + + + export type LibraryGroupByArgs = { + where?: LibraryWhereInput + orderBy?: LibraryOrderByWithAggregationInput | LibraryOrderByWithAggregationInput[] + by: LibraryScalarFieldEnum[] | LibraryScalarFieldEnum + having?: LibraryScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: LibraryCountAggregateInputType | true + _min?: LibraryMinAggregateInputType + _max?: LibraryMaxAggregateInputType + } + + export type LibraryGroupByOutputType = { + id: string + items: string + createdAt: Date + updatedAt: Date + _count: LibraryCountAggregateOutputType | null + _min: LibraryMinAggregateOutputType | null + _max: LibraryMaxAggregateOutputType | null + } + + type GetLibraryGroupByPayload = Prisma.PrismaPromise< + Array< + PickEnumerable & + { + [P in ((keyof T) & (keyof LibraryGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : GetScalarType + : GetScalarType + } + > + > + + + export type LibrarySelect = $Extensions.GetSelect<{ + id?: boolean + items?: boolean + createdAt?: boolean + updatedAt?: boolean + }, ExtArgs["result"]["library"]> + + export type LibrarySelectCreateManyAndReturn = $Extensions.GetSelect<{ + id?: boolean + items?: boolean + createdAt?: boolean + updatedAt?: boolean + }, ExtArgs["result"]["library"]> + + export type LibrarySelectScalar = { + id?: boolean + items?: boolean + createdAt?: boolean + updatedAt?: boolean + } + + + export type $LibraryPayload = { + name: "Library" + objects: {} + scalars: $Extensions.GetPayloadResult<{ + id: string + items: string + createdAt: Date + updatedAt: Date + }, ExtArgs["result"]["library"]> + composites: {} + } + + type LibraryGetPayload = $Result.GetResult + + type LibraryCountArgs = + Omit & { + select?: LibraryCountAggregateInputType | true + } + + export interface LibraryDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['Library'], meta: { name: 'Library' } } + /** + * Find zero or one Library that matches the filter. + * @param {LibraryFindUniqueArgs} args - Arguments to find a Library + * @example + * // Get one Library + * const library = await prisma.library.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "findUnique"> | null, null, ExtArgs> + + /** + * Find one Library that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {LibraryFindUniqueOrThrowArgs} args - Arguments to find a Library + * @example + * // Get one Library + * const library = await prisma.library.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "findUniqueOrThrow">, never, ExtArgs> + + /** + * Find the first Library that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryFindFirstArgs} args - Arguments to find a Library + * @example + * // Get one Library + * const library = await prisma.library.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "findFirst"> | null, null, ExtArgs> + + /** + * Find the first Library that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryFindFirstOrThrowArgs} args - Arguments to find a Library + * @example + * // Get one Library + * const library = await prisma.library.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "findFirstOrThrow">, never, ExtArgs> + + /** + * Find zero or more Libraries that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all Libraries + * const libraries = await prisma.library.findMany() + * + * // Get first 10 Libraries + * const libraries = await prisma.library.findMany({ take: 10 }) + * + * // Only select the `id` + * const libraryWithIdOnly = await prisma.library.findMany({ select: { id: true } }) + * + */ + findMany(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany">> + + /** + * Create a Library. + * @param {LibraryCreateArgs} args - Arguments to create a Library. + * @example + * // Create one Library + * const Library = await prisma.library.create({ + * data: { + * // ... data to create a Library + * } + * }) + * + */ + create(args: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "create">, never, ExtArgs> + + /** + * Create many Libraries. + * @param {LibraryCreateManyArgs} args - Arguments to create many Libraries. + * @example + * // Create many Libraries + * const library = await prisma.library.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: SelectSubset>): Prisma.PrismaPromise + + /** + * Create many Libraries and returns the data saved in the database. + * @param {LibraryCreateManyAndReturnArgs} args - Arguments to create many Libraries. + * @example + * // Create many Libraries + * const library = await prisma.library.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many Libraries and only return the `id` + * const libraryWithIdOnly = await prisma.library.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "createManyAndReturn">> + + /** + * Delete a Library. + * @param {LibraryDeleteArgs} args - Arguments to delete one Library. + * @example + * // Delete one Library + * const Library = await prisma.library.delete({ + * where: { + * // ... filter to delete one Library + * } + * }) + * + */ + delete(args: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "delete">, never, ExtArgs> + + /** + * Update one Library. + * @param {LibraryUpdateArgs} args - Arguments to update one Library. + * @example + * // Update one Library + * const library = await prisma.library.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "update">, never, ExtArgs> + + /** + * Delete zero or more Libraries. + * @param {LibraryDeleteManyArgs} args - Arguments to filter Libraries to delete. + * @example + * // Delete a few Libraries + * const { count } = await prisma.library.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Libraries. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many Libraries + * const library = await prisma.library.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: SelectSubset>): Prisma.PrismaPromise + + /** + * Create or update one Library. + * @param {LibraryUpsertArgs} args - Arguments to update or create a Library. + * @example + * // Update or create a Library + * const library = await prisma.library.upsert({ + * create: { + * // ... data to create a Library + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the Library we want to update + * } + * }) + */ + upsert(args: SelectSubset>): Prisma__LibraryClient<$Result.GetResult, T, "upsert">, never, ExtArgs> + + + /** + * Count the number of Libraries. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryCountArgs} args - Arguments to filter Libraries to count. + * @example + * // Count the number of Libraries + * const count = await prisma.library.count({ + * where: { + * // ... the filter for the Libraries we want to count + * } + * }) + **/ + count( + args?: Subset, + ): Prisma.PrismaPromise< + T extends $Utils.Record<'select', any> + ? T['select'] extends true + ? number + : GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a Library. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Subset): Prisma.PrismaPromise> + + /** + * Group by Library. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {LibraryGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends LibraryGroupByArgs, + HasSelectOrTake extends Or< + Extends<'skip', Keys>, + Extends<'take', Keys> + >, + OrderByArg extends True extends HasSelectOrTake + ? { orderBy: LibraryGroupByArgs['orderBy'] } + : { orderBy?: LibraryGroupByArgs['orderBy'] }, + OrderFields extends ExcludeUnderscoreKeys>>, + ByFields extends MaybeTupleToUnion, + ByValid extends Has, + HavingFields extends GetHavingFields, + HavingValid extends Has, + ByEmpty extends T['by'] extends never[] ? True : False, + InputErrors extends ByEmpty extends True + ? `Error: "by" must not be empty.` + : HavingValid extends False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Keys + ? 'orderBy' extends Keys + ? ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Keys + ? 'orderBy' extends Keys + ? ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: SubsetIntersection & InputErrors): {} extends InputErrors ? GetLibraryGroupByPayload : Prisma.PrismaPromise + /** + * Fields of the Library model + */ + readonly fields: LibraryFieldRefs; + } + + /** + * The delegate class that acts as a "Promise-like" for Library. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ + export interface Prisma__LibraryClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): $Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): $Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): $Utils.JsPromise + } + + + + + /** + * Fields of the Library model + */ + interface LibraryFieldRefs { + readonly id: FieldRef<"Library", 'String'> + readonly items: FieldRef<"Library", 'String'> + readonly createdAt: FieldRef<"Library", 'DateTime'> + readonly updatedAt: FieldRef<"Library", 'DateTime'> + } + + + // Custom InputTypes + /** + * Library findUnique + */ + export type LibraryFindUniqueArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * Filter, which Library to fetch. + */ + where: LibraryWhereUniqueInput + } + + /** + * Library findUniqueOrThrow + */ + export type LibraryFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * Filter, which Library to fetch. + */ + where: LibraryWhereUniqueInput + } + + /** + * Library findFirst + */ + export type LibraryFindFirstArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * Filter, which Library to fetch. + */ + where?: LibraryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Libraries to fetch. + */ + orderBy?: LibraryOrderByWithRelationInput | LibraryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Libraries. + */ + cursor?: LibraryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Libraries from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Libraries. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Libraries. + */ + distinct?: LibraryScalarFieldEnum | LibraryScalarFieldEnum[] + } + + /** + * Library findFirstOrThrow + */ + export type LibraryFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * Filter, which Library to fetch. + */ + where?: LibraryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Libraries to fetch. + */ + orderBy?: LibraryOrderByWithRelationInput | LibraryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Libraries. + */ + cursor?: LibraryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Libraries from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Libraries. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Libraries. + */ + distinct?: LibraryScalarFieldEnum | LibraryScalarFieldEnum[] + } + + /** + * Library findMany + */ + export type LibraryFindManyArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * Filter, which Libraries to fetch. + */ + where?: LibraryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Libraries to fetch. + */ + orderBy?: LibraryOrderByWithRelationInput | LibraryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing Libraries. + */ + cursor?: LibraryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Libraries from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Libraries. + */ + skip?: number + distinct?: LibraryScalarFieldEnum | LibraryScalarFieldEnum[] + } + + /** + * Library create + */ + export type LibraryCreateArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * The data needed to create a Library. + */ + data: XOR + } + + /** + * Library createMany + */ + export type LibraryCreateManyArgs = { + /** + * The data used to create many Libraries. + */ + data: LibraryCreateManyInput | LibraryCreateManyInput[] + } + + /** + * Library createManyAndReturn + */ + export type LibraryCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelectCreateManyAndReturn | null + /** + * The data used to create many Libraries. + */ + data: LibraryCreateManyInput | LibraryCreateManyInput[] + } + + /** + * Library update + */ + export type LibraryUpdateArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * The data needed to update a Library. + */ + data: XOR + /** + * Choose, which Library to update. + */ + where: LibraryWhereUniqueInput + } + + /** + * Library updateMany + */ + export type LibraryUpdateManyArgs = { + /** + * The data used to update Libraries. + */ + data: XOR + /** + * Filter which Libraries to update + */ + where?: LibraryWhereInput + } + + /** + * Library upsert + */ + export type LibraryUpsertArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * The filter to search for the Library to update in case it exists. + */ + where: LibraryWhereUniqueInput + /** + * In case the Library found by the `where` argument doesn't exist, create a new Library with this data. + */ + create: XOR + /** + * In case the Library was found with the provided `where` argument, update it with this data. + */ + update: XOR + } + + /** + * Library delete + */ + export type LibraryDeleteArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + /** + * Filter which Library to delete. + */ + where: LibraryWhereUniqueInput + } + + /** + * Library deleteMany + */ + export type LibraryDeleteManyArgs = { + /** + * Filter which Libraries to delete + */ + where?: LibraryWhereInput + } + + /** + * Library without action + */ + export type LibraryDefaultArgs = { + /** + * Select specific fields to fetch from the Library + */ + select?: LibrarySelect | null + } + + /** * Enums */ @@ -2970,6 +3920,16 @@ export namespace Prisma { export type DrawingScalarFieldEnum = (typeof DrawingScalarFieldEnum)[keyof typeof DrawingScalarFieldEnum] + export const LibraryScalarFieldEnum: { + id: 'id', + items: 'items', + createdAt: 'createdAt', + updatedAt: 'updatedAt' + }; + + export type LibraryScalarFieldEnum = (typeof LibraryScalarFieldEnum)[keyof typeof LibraryScalarFieldEnum] + + export const SortOrder: { asc: 'asc', desc: 'desc' @@ -3154,6 +4114,53 @@ export namespace Prisma { updatedAt?: DateTimeWithAggregatesFilter<"Drawing"> | Date | string } + export type LibraryWhereInput = { + AND?: LibraryWhereInput | LibraryWhereInput[] + OR?: LibraryWhereInput[] + NOT?: LibraryWhereInput | LibraryWhereInput[] + id?: StringFilter<"Library"> | string + items?: StringFilter<"Library"> | string + createdAt?: DateTimeFilter<"Library"> | Date | string + updatedAt?: DateTimeFilter<"Library"> | Date | string + } + + export type LibraryOrderByWithRelationInput = { + id?: SortOrder + items?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + + export type LibraryWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: LibraryWhereInput | LibraryWhereInput[] + OR?: LibraryWhereInput[] + NOT?: LibraryWhereInput | LibraryWhereInput[] + items?: StringFilter<"Library"> | string + createdAt?: DateTimeFilter<"Library"> | Date | string + updatedAt?: DateTimeFilter<"Library"> | Date | string + }, "id"> + + export type LibraryOrderByWithAggregationInput = { + id?: SortOrder + items?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + _count?: LibraryCountOrderByAggregateInput + _max?: LibraryMaxOrderByAggregateInput + _min?: LibraryMinOrderByAggregateInput + } + + export type LibraryScalarWhereWithAggregatesInput = { + AND?: LibraryScalarWhereWithAggregatesInput | LibraryScalarWhereWithAggregatesInput[] + OR?: LibraryScalarWhereWithAggregatesInput[] + NOT?: LibraryScalarWhereWithAggregatesInput | LibraryScalarWhereWithAggregatesInput[] + id?: StringWithAggregatesFilter<"Library"> | string + items?: StringWithAggregatesFilter<"Library"> | string + createdAt?: DateTimeWithAggregatesFilter<"Library"> | Date | string + updatedAt?: DateTimeWithAggregatesFilter<"Library"> | Date | string + } + export type CollectionCreateInput = { id?: string name: string @@ -3297,6 +4304,55 @@ export namespace Prisma { updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } + export type LibraryCreateInput = { + id?: string + items?: string + createdAt?: Date | string + updatedAt?: Date | string + } + + export type LibraryUncheckedCreateInput = { + id?: string + items?: string + createdAt?: Date | string + updatedAt?: Date | string + } + + export type LibraryUpdateInput = { + id?: StringFieldUpdateOperationsInput | string + items?: StringFieldUpdateOperationsInput | string + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type LibraryUncheckedUpdateInput = { + id?: StringFieldUpdateOperationsInput | string + items?: StringFieldUpdateOperationsInput | string + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type LibraryCreateManyInput = { + id?: string + items?: string + createdAt?: Date | string + updatedAt?: Date | string + } + + export type LibraryUpdateManyMutationInput = { + id?: StringFieldUpdateOperationsInput | string + items?: StringFieldUpdateOperationsInput | string + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type LibraryUncheckedUpdateManyInput = { + id?: StringFieldUpdateOperationsInput | string + items?: StringFieldUpdateOperationsInput | string + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + export type StringFilter<$PrismaModel = never> = { equals?: string | StringFieldRefInput<$PrismaModel> in?: string[] @@ -3499,6 +4555,27 @@ export namespace Prisma { _max?: NestedIntFilter<$PrismaModel> } + export type LibraryCountOrderByAggregateInput = { + id?: SortOrder + items?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + + export type LibraryMaxOrderByAggregateInput = { + id?: SortOrder + items?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + + export type LibraryMinOrderByAggregateInput = { + id?: SortOrder + items?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + export type DrawingCreateNestedManyWithoutCollectionInput = { create?: XOR | DrawingCreateWithoutCollectionInput[] | DrawingUncheckedCreateWithoutCollectionInput[] connectOrCreate?: DrawingCreateOrConnectWithoutCollectionInput | DrawingCreateOrConnectWithoutCollectionInput[] @@ -3887,6 +4964,10 @@ export namespace Prisma { * @deprecated Use DrawingDefaultArgs instead */ export type DrawingArgs = DrawingDefaultArgs + /** + * @deprecated Use LibraryDefaultArgs instead + */ + export type LibraryArgs = LibraryDefaultArgs /** * Batch Payload for updateMany & deleteMany & createMany diff --git a/backend/src/generated/client/index.js b/backend/src/generated/client/index.js index 08e0ca4..96defd5 100644 --- a/backend/src/generated/client/index.js +++ b/backend/src/generated/client/index.js @@ -108,6 +108,13 @@ exports.Prisma.DrawingScalarFieldEnum = { updatedAt: 'updatedAt' }; +exports.Prisma.LibraryScalarFieldEnum = { + id: 'id', + items: 'items', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + exports.Prisma.SortOrder = { asc: 'asc', desc: 'desc' @@ -121,7 +128,8 @@ exports.Prisma.NullsOrder = { exports.Prisma.ModelName = { Collection: 'Collection', - Drawing: 'Drawing' + Drawing: 'Drawing', + Library: 'Library' }; /** * Create the Client @@ -170,7 +178,6 @@ const config = { "db" ], "activeProvider": "sqlite", - "postinstall": false, "inlineDatasources": { "db": { "url": { @@ -179,8 +186,8 @@ const config = { } } }, - "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"../src/generated/client\"\n binaryTargets = [\"native\", \"linux-musl-arm64-openssl-3.0.x\", \"linux-musl-openssl-3.0.x\"]\n}\n\ndatasource db {\n provider = \"sqlite\"\n url = env(\"DATABASE_URL\")\n}\n\nmodel Collection {\n id String @id @default(uuid())\n name String\n drawings Drawing[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Drawing {\n id String @id @default(uuid())\n name String\n elements String // Stored as JSON string\n appState String // Stored as JSON string\n files String @default(\"{}\") // Stored as JSON string\n preview String? // SVG string for thumbnail\n version Int @default(1)\n collectionId String?\n collection Collection? @relation(fields: [collectionId], references: [id])\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", - "inlineSchemaHash": "30da526c2a5efdf3e5097c3736a52d47246ca4da8e5bd0401a3f28dd46ab5c3e", + "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"../src/generated/client\"\n binaryTargets = [\"native\", \"linux-musl-arm64-openssl-3.0.x\", \"linux-musl-openssl-3.0.x\"]\n}\n\ndatasource db {\n provider = \"sqlite\"\n url = env(\"DATABASE_URL\")\n}\n\nmodel Collection {\n id String @id @default(uuid())\n name String\n drawings Drawing[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Drawing {\n id String @id @default(uuid())\n name String\n elements String // Stored as JSON string\n appState String // Stored as JSON string\n files String @default(\"{}\") // Stored as JSON string\n preview String? // SVG string for thumbnail\n version Int @default(1)\n collectionId String?\n collection Collection? @relation(fields: [collectionId], references: [id])\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Library {\n id String @id @default(\"default\") // Singleton pattern - use \"default\" ID\n items String @default(\"[]\") // Stored as JSON string array of library items\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", + "inlineSchemaHash": "a6a8e55dadb0695c66246575cd1a63af3afd912ce070b4798d2e56269d371c87", "copyEngine": true } @@ -201,7 +208,7 @@ if (!fs.existsSync(path.join(__dirname, 'schema.prisma'))) { config.isBundled = true } -config.runtimeDataModel = JSON.parse("{\"models\":{\"Collection\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"drawings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Drawing\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Drawing\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"elements\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"appState\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"files\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"{}\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"preview\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"version\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collectionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collection\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Collection\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[\"collectionId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"Collection\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"drawings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Drawing\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Drawing\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"uuid(4)\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"elements\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"appState\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"files\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"{}\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"preview\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"version\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":1,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collectionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"collection\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Collection\",\"relationName\":\"CollectionToDrawing\",\"relationFromFields\":[\"collectionId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Library\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"default\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"items\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"[]\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{},\"types\":{}}") defineDmmfProperty(exports.Prisma, config.runtimeDataModel) config.engineWasm = undefined diff --git a/backend/src/generated/client/package.json b/backend/src/generated/client/package.json index 8a74595..b653243 100644 --- a/backend/src/generated/client/package.json +++ b/backend/src/generated/client/package.json @@ -1,5 +1,5 @@ { - "name": "prisma-client-6afe3d9baa793154c8d01c79f8418d91423e5ccaec794547bf848a451459cf53", + "name": "prisma-client-8eed3ee5004eaec649fc60571177778f25acb4a3cdc2c238bbb8e70dd820d0ff", "main": "index.js", "types": "index.d.ts", "browser": "index-browser.js", diff --git a/backend/src/generated/client/schema.prisma b/backend/src/generated/client/schema.prisma index bd3369f..23da027 100644 --- a/backend/src/generated/client/schema.prisma +++ b/backend/src/generated/client/schema.prisma @@ -33,3 +33,10 @@ model Drawing { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } + +model Library { + id String @id @default("default") // Singleton pattern - use "default" ID + items String @default("[]") // Stored as JSON string array of library items + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/backend/src/generated/client/wasm.js b/backend/src/generated/client/wasm.js index 6d1f1d8..d303df9 100644 --- a/backend/src/generated/client/wasm.js +++ b/backend/src/generated/client/wasm.js @@ -139,6 +139,13 @@ exports.Prisma.DrawingScalarFieldEnum = { updatedAt: 'updatedAt' }; +exports.Prisma.LibraryScalarFieldEnum = { + id: 'id', + items: 'items', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + exports.Prisma.SortOrder = { asc: 'asc', desc: 'desc' @@ -152,7 +159,8 @@ exports.Prisma.NullsOrder = { exports.Prisma.ModelName = { Collection: 'Collection', - Drawing: 'Drawing' + Drawing: 'Drawing', + Library: 'Library' }; /** diff --git a/backend/src/index.ts b/backend/src/index.ts index 74f3833..b7b3bf4 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -801,6 +801,58 @@ app.delete("/collections/:id", async (req, res) => { } }); +// --- Library --- + +// GET /library - Fetch stored library items +app.get("/library", async (req, res) => { + try { + const library = await prisma.library.findUnique({ + where: { id: "default" }, + }); + + if (!library) { + // Return empty array if no library exists yet + return res.json({ items: [] }); + } + + res.json({ + items: JSON.parse(library.items), + }); + } catch (error) { + console.error("Failed to fetch library:", error); + res.status(500).json({ error: "Failed to fetch library" }); + } +}); + +// PUT /library - Update/create library items +app.put("/library", async (req, res) => { + try { + const { items } = req.body; + + if (!Array.isArray(items)) { + return res.status(400).json({ error: "Items must be an array" }); + } + + const library = await prisma.library.upsert({ + where: { id: "default" }, + update: { + items: JSON.stringify(items), + }, + create: { + id: "default", + items: JSON.stringify(items), + }, + }); + + res.json({ + items: JSON.parse(library.items), + }); + } catch (error) { + console.error("Failed to update library:", error); + res.status(500).json({ error: "Failed to update library" }); + } +}); + // --- Export/Import Endpoints --- // GET /export - Export SQLite database (supports .sqlite and .db extensions) diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 158ca02..0bd9856 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -84,3 +84,15 @@ export const deleteCollection = async (id: string) => { const response = await api.delete<{ success: true }>(`/collections/${id}`); return response.data; }; + +// --- Library --- + +export const getLibrary = async () => { + const response = await api.get<{ items: any[] }>("/library"); + return response.data.items; +}; + +export const updateLibrary = async (items: any[]) => { + const response = await api.put<{ items: any[] }>("/library", { items }); + return response.data.items; +}; diff --git a/frontend/src/pages/Editor.tsx b/frontend/src/pages/Editor.tsx index 01f874d..a82b99f 100644 --- a/frontend/src/pages/Editor.tsx +++ b/frontend/src/pages/Editor.tsx @@ -241,6 +241,59 @@ export const Editor: React.FC = () => { setIsReady(true); }, []); + // Handle #addLibrary URL hash parameter for importing libraries from links + useEffect(() => { + if (!isReady || !excalidrawAPI.current) return; + + const hash = window.location.hash; + if (!hash.includes('addLibrary=')) return; + + const params = new URLSearchParams(hash.slice(1)); // Remove the leading # + const libraryUrl = params.get('addLibrary'); + + if (!libraryUrl) return; + + const importLibraryFromUrl = async () => { + try { + console.log('[Editor] Importing library from URL:', libraryUrl); + toast.loading('Importing library...', { id: 'library-import' }); + + const response = await fetch(libraryUrl); + if (!response.ok) { + throw new Error(`Failed to fetch library: ${response.statusText}`); + } + + const blob = await response.blob(); + + // Use Excalidraw's updateLibrary API with proper settings: + // - defaultStatus: "published" puts items in "Excalidraw library" section + // - merge: true preserves existing library items + // - openLibraryMenu: true shows the library sidebar after import + await excalidrawAPI.current.updateLibrary({ + libraryItems: blob, + merge: true, + defaultStatus: "published", + openLibraryMenu: true, + }); + + // Get the updated library items and persist to server + const updatedItems = excalidrawAPI.current.getAppState().libraryItems || []; + await api.updateLibrary([...updatedItems]); + + toast.success('Library imported successfully', { id: 'library-import' }); + console.log('[Editor] Library import complete'); + + // Clear the hash to prevent re-importing on refresh + window.history.replaceState(null, '', window.location.pathname + window.location.search); + } catch (err) { + console.error('[Editor] Failed to import library:', err); + toast.error('Failed to import library', { id: 'library-import' }); + } + }; + + importLibraryFromUrl(); + }, [isReady]); + const buildEmptyScene = useCallback(() => ({ elements: [], appState: { @@ -259,6 +312,7 @@ export const Editor: React.FC = () => { // ------------------------------------------------------------------ const saveDataRef = useRef<((elements: readonly any[], appState: any) => Promise) | null>(null); const savePreviewRef = useRef<((elements: readonly any[], appState: any, files: any) => Promise) | null>(null); + const saveLibraryRef = useRef<((items: any[]) => Promise) | null>(null); // Update the ref on every render to ensure it has access to the latest props/state saveDataRef.current = async (elements: readonly any[], appState: any) => { @@ -326,6 +380,17 @@ export const Editor: React.FC = () => { } }; + saveLibraryRef.current = async (items: any[]) => { + try { + console.log("[Editor] Saving library", { itemCount: items.length }); + await api.updateLibrary(items); + console.log("[Editor] Library save complete"); + } catch (err) { + console.error('Failed to save library', err); + toast.error("Failed to save library"); + } + }; + // Create the debounced function ONLY ONCE. // It simply calls whatever is currently in saveDataRef.current const debouncedSave = useCallback( @@ -346,6 +411,15 @@ export const Editor: React.FC = () => { [] ); + const debouncedSaveLibrary = useCallback( + debounce((items: any[]) => { + if (saveLibraryRef.current) { + saveLibraryRef.current(items); + } + }, 1000), + [] + ); + const broadcastChanges = useCallback( throttle((elements: readonly any[]) => { if (!socketRef.current || !id) return; @@ -391,7 +465,14 @@ export const Editor: React.FC = () => { return; } try { - const data = await api.getDrawing(id); + // Fetch drawing and library in parallel + const [data, libraryItems] = await Promise.all([ + api.getDrawing(id), + api.getLibrary().catch((err) => { + console.warn('Failed to load library, using empty:', err); + return []; + }) + ]); setDrawingName(data.name); // Use elements directly without converting - they're already normalized during import @@ -417,6 +498,7 @@ export const Editor: React.FC = () => { appState: hydratedAppState, files, scrollToContent: true, + libraryItems, }); } catch (err) { console.error('Failed to load drawing', err); @@ -537,6 +619,12 @@ export const Editor: React.FC = () => { } }; + // Handle library changes and persist to server + const handleLibraryChange = useCallback((items: readonly any[]) => { + console.log("[Editor] Library changed", { itemCount: items.length }); + debouncedSaveLibrary([...items]); + }, [debouncedSaveLibrary]); + // Disable native Excalidraw save dialogs // UIOptions is now defined outside the component @@ -639,6 +727,7 @@ export const Editor: React.FC = () => { initialData={initialData} onChange={handleCanvasChange} onPointerUpdate={onPointerUpdate} + onLibraryChange={handleLibraryChange} excalidrawAPI={setExcalidrawAPI} UIOptions={UIOptions} />