diff --git a/app/routes/app.$assetslug.$entry._index.tsx b/app/routes/app.$assetslug.$entry._index.tsx
index 4f10ba2..032f96c 100644
--- a/app/routes/app.$assetslug.$entry._index.tsx
+++ b/app/routes/app.$assetslug.$entry._index.tsx
@@ -5,7 +5,11 @@ import {
json
} from '@remix-run/node'
import {Link, useLoaderData} from '@remix-run/react'
-import {type Entry} from '@prisma/client'
+import {
+ getEntryValues,
+ getEntryRevisions,
+ getEntryRelations
+} from '@prisma/client/sql'
import {ensureUser} from '~/lib/utils/ensure-user'
import {getPrisma} from '~/lib/prisma.server'
@@ -39,39 +43,14 @@ export const loader = async ({request, params}: LoaderFunctionArgs) => {
})
)
- const values = await time(
- 'getValues',
- 'Get Values',
- () => prisma.$queryRaw<
- Array<{
- id: string
- value: string
- order: number
- type: string
- meta: string
- fieldId: string
- fieldName: string
- }>
- >`SELECT Value.id, Value.value, AssetField."order", Field.type, Field.meta, Value.fieldId, Field.name as fieldName FROM Value
- INNER JOIN Entry ON Entry.Id = Value.entryId
- INNER JOIN Asset on Asset.Id = Entry.assetId
- INNER JOIN AssetField on AssetField.assetId = Asset.id AND AssetField.fieldId = Value.fieldId
- INNER JOIN Field on Field.id = Value.fieldId
- WHERE entryId = ${entry.id}
- ORDER BY AssetField."order" ASC`
+ const values = await time('getValues', 'Get Values', () =>
+ prisma.$queryRawTyped(getEntryValues(entry.id))
)
- const relations = await time(
- 'getRelations',
- 'Get Relations',
- () => prisma.$queryRaw<
- Array<
- Entry & {value: string; slug: string; entryId: string; icon: string}
- >
- >`SELECT * FROM Entry
- INNER JOIN Value value ON fieldId = (SELECT nameFieldId FROM Asset WHERE Asset.id = entry.assetId) AND entryId = Entry.id
- INNER JOIN Asset ON Entry.assetId = Asset.id
- WHERE Entry.id IN (SELECT entryId FROM Value WHERE value LIKE ${`%${entry.id}%`}) AND deleted = false`
+ const relations = await time('getRelations', 'Get Relations', () =>
+ prisma.$queryRawTyped(
+ getEntryRelations(`%${entry.id}%`, user.role, user.id)
+ )
)
const documents = await time('getDocuments', 'Get Documents', () =>
@@ -80,23 +59,8 @@ export const loader = async ({request, params}: LoaderFunctionArgs) => {
})
)
- const revisions = await time(
- 'getRevisions',
- 'Get Revisions',
- () => prisma.$queryRaw<
- Array<{
- id: string
- createdAt: string
- changeNote: string
- fieldName: string
- userName: string
- }>
- >`SELECT ValueHistory.id, ValueHistory.createdAt, ValueHistory.changeNote, Field.name as fieldName, User.name as userName FROM ValueHistory
- INNER JOIN Value on Value.id = ValueHistory.valueId
- INNER JOIN Field on Field.id = Value.fieldId
- INNER JOIN User on User.id = ValueHistory.editedById
- WHERE Value.entryId = ${params.entry}
- ORDER BY ValueHistory.createdAt DESC`
+ const revisions = await time('getRevisions', 'Get Revisions', () =>
+ prisma.$queryRawTyped(getEntryRevisions(entry.id))
)
const name = values.reduce((n, v) => {
@@ -164,11 +128,11 @@ const AssetEntry = () => {
{relations.length === 0
? 'No Linked Entries'
- : relations.map(({entryId, value, slug, icon}) => {
+ : relations.map(({id, value, slug, icon}) => {
return (
{icon} {value}
diff --git a/package-lock.json b/package-lock.json
index 24b0ce2..401f7de 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,7 +8,7 @@
"dependencies": {
"@arcath/utils": "^3.15.0",
"@epic-web/totp": "^1.1.2",
- "@prisma/client": "^5.18.0",
+ "@prisma/client": "^5.19.0",
"@remix-run/node": "^2.11.1",
"@remix-run/react": "^2.11.1",
"@remix-run/serve": "^2.11.1",
@@ -54,7 +54,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.41",
"prettier": "^3.3.3",
- "prisma": "^5.18.0",
+ "prisma": "^5.19.0",
"tailwindcss": "^3.4.10",
"typescript": "^5.5.4",
"vite-tsconfig-paths": "^4.3.2",
@@ -2786,10 +2786,11 @@
}
},
"node_modules/@prisma/client": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.18.0.tgz",
- "integrity": "sha512-BWivkLh+af1kqC89zCJYkHsRcyWsM8/JHpsDMM76DjP3ZdEquJhXa4IeX+HkWPnwJ5FanxEJFZZDTWiDs/Kvyw==",
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.19.0.tgz",
+ "integrity": "sha512-CzOpau+q1kEWQyoQMvlnXIHqPvwmWbh48xZ4n8KWbAql0p8PC0BIgSTYW5ncxXa4JSEff0tcoxSZB874wDstdg==",
"hasInstallScript": true,
+ "license": "Apache-2.0",
"engines": {
"node": ">=16.13"
},
@@ -2803,48 +2804,53 @@
}
},
"node_modules/@prisma/debug": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.18.0.tgz",
- "integrity": "sha512-f+ZvpTLidSo3LMJxQPVgAxdAjzv5OpzAo/eF8qZqbwvgi2F5cTOI9XCpdRzJYA0iGfajjwjOKKrVq64vkxEfUw==",
- "devOptional": true
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.19.0.tgz",
+ "integrity": "sha512-+b/G0ubAZlrS+JSiDhXnYV5DF/aTJ3pinktkiV/L4TtLRLZO6SVGyFELgxBsicCTWJ2ZMu5vEV/jTtYCdjFTRA==",
+ "devOptional": true,
+ "license": "Apache-2.0"
},
"node_modules/@prisma/engines": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.18.0.tgz",
- "integrity": "sha512-ofmpGLeJ2q2P0wa/XaEgTnX/IsLnvSp/gZts0zjgLNdBhfuj2lowOOPmDcfKljLQUXMvAek3lw5T01kHmCG8rg==",
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.19.0.tgz",
+ "integrity": "sha512-UtW+0m4HYoRSSR3LoDGKF3Ud4BSMWYlLEt4slTnuP1mI+vrV3zaDoiAPmejdAT76vCN5UqnWURbkXxf66nSylQ==",
"devOptional": true,
"hasInstallScript": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@prisma/debug": "5.18.0",
- "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169",
- "@prisma/fetch-engine": "5.18.0",
- "@prisma/get-platform": "5.18.0"
+ "@prisma/debug": "5.19.0",
+ "@prisma/engines-version": "5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f",
+ "@prisma/fetch-engine": "5.19.0",
+ "@prisma/get-platform": "5.19.0"
}
},
"node_modules/@prisma/engines-version": {
- "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169",
- "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz",
- "integrity": "sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==",
- "devOptional": true
+ "version": "5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f.tgz",
+ "integrity": "sha512-GimI9aZIFy/yvvR11KfXRn3pliFn1QAkdebVlsXlnoh5uk0YhLblVmeYiHfsu+wDA7BeKqYT4sFfzg8mutzuWw==",
+ "devOptional": true,
+ "license": "Apache-2.0"
},
"node_modules/@prisma/fetch-engine": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.18.0.tgz",
- "integrity": "sha512-I/3u0x2n31rGaAuBRx2YK4eB7R/1zCuayo2DGwSpGyrJWsZesrV7QVw7ND0/Suxeo/vLkJ5OwuBqHoCxvTHpOg==",
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.19.0.tgz",
+ "integrity": "sha512-oOiPNtmJX0cP/ebu7BBEouJvCw8T84/MFD/Hf2zlqjxkK4ojl38bB9i9J5LAxotL6WlYVThKdxc7HqoWnPOhqQ==",
"devOptional": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@prisma/debug": "5.18.0",
- "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169",
- "@prisma/get-platform": "5.18.0"
+ "@prisma/debug": "5.19.0",
+ "@prisma/engines-version": "5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f",
+ "@prisma/get-platform": "5.19.0"
}
},
"node_modules/@prisma/get-platform": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.18.0.tgz",
- "integrity": "sha512-Tk+m7+uhqcKDgnMnFN0lRiH7Ewea0OEsZZs9pqXa7i3+7svS3FSCqDBCaM9x5fmhhkufiG0BtunJVDka+46DlA==",
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.19.0.tgz",
+ "integrity": "sha512-s9DWkZKnuP4Y8uy6yZfvqQ/9X3/+2KYf3IZUVZz5OstJdGBJrBlbmIuMl81917wp5TuK/1k2TpHNCEdpYLPKmg==",
"devOptional": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@prisma/debug": "5.18.0"
+ "@prisma/debug": "5.19.0"
}
},
"node_modules/@remix-run/dev": {
@@ -16910,19 +16916,23 @@
}
},
"node_modules/prisma": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.18.0.tgz",
- "integrity": "sha512-+TrSIxZsh64OPOmaSgVPH7ALL9dfU0jceYaMJXsNrTkFHO7/3RANi5K2ZiPB1De9+KDxCWn7jvRq8y8pvk+o9g==",
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.19.0.tgz",
+ "integrity": "sha512-Pu7lUKpVyTx8cVwM26dYh8NdvMOkMnJXzE8L6cikFuR4JwyMU5NKofQkWyxJKlTT4fNjmcnibTvklV8oVMrn+g==",
"devOptional": true,
"hasInstallScript": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@prisma/engines": "5.18.0"
+ "@prisma/engines": "5.19.0"
},
"bin": {
"prisma": "build/index.js"
},
"engines": {
"node": ">=16.13"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.3"
}
},
"node_modules/proc-log": {
diff --git a/package.json b/package.json
index 398a792..138d927 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"dependencies": {
"@arcath/utils": "^3.15.0",
"@epic-web/totp": "^1.1.2",
- "@prisma/client": "^5.18.0",
+ "@prisma/client": "^5.19.0",
"@remix-run/node": "^2.11.1",
"@remix-run/react": "^2.11.1",
"@remix-run/serve": "^2.11.1",
@@ -68,7 +68,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.41",
"prettier": "^3.3.3",
- "prisma": "^5.18.0",
+ "prisma": "^5.19.0",
"tailwindcss": "^3.4.10",
"typescript": "^5.5.4",
"vite-tsconfig-paths": "^4.3.2",
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 2f072fa..546e919 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -6,6 +6,7 @@
generator client {
provider = "prisma-client-js"
+ previewFeatures = ["typedSql"]
}
datasource db {
diff --git a/prisma/sql/getEntryRelations.sql b/prisma/sql/getEntryRelations.sql
new file mode 100644
index 0000000..2abb08e
--- /dev/null
+++ b/prisma/sql/getEntryRelations.sql
@@ -0,0 +1,18 @@
+-- @param {String} $1:entryId The ID of the entry to collect relations for
+-- @param {String} $2:userRole The role of the current user
+-- @param {String} $3:userId The ID of the current user
+SELECT Entry.id, Value.value, Asset.icon, Asset.slug FROM Entry
+ INNER JOIN Value value ON fieldId = (SELECT nameFieldId FROM Asset WHERE Asset.id = entry.assetId) AND entryId = Entry.id
+ INNER JOIN Asset ON Entry.assetId = Asset.id
+ WHERE
+ Entry.id IN (SELECT entryId FROM Value WHERE value LIKE $1)
+ AND
+ deleted = false
+ AND
+ Entry.aclId IN (SELECT aclId FROM ACLEntry
+ WHERE read = true AND (
+ (type = "role" AND target = $2)
+ OR
+ (type = "user" AND target = $3)
+ )
+ )
\ No newline at end of file
diff --git a/prisma/sql/getEntryRevisions.sql b/prisma/sql/getEntryRevisions.sql
new file mode 100644
index 0000000..dae0f74
--- /dev/null
+++ b/prisma/sql/getEntryRevisions.sql
@@ -0,0 +1,7 @@
+-- @param {String} $1:entryId The ID of the entry to collect revisions for
+SELECT ValueHistory.id, ValueHistory.createdAt, ValueHistory.changeNote, Field.name as fieldName, User.name as userName FROM ValueHistory
+ INNER JOIN Value on Value.id = ValueHistory.valueId
+ INNER JOIN Field on Field.id = Value.fieldId
+ INNER JOIN User on User.id = ValueHistory.editedById
+ WHERE Value.entryId = $1
+ ORDER BY ValueHistory.createdAt DESC
\ No newline at end of file
diff --git a/prisma/sql/getEntryValues.sql b/prisma/sql/getEntryValues.sql
new file mode 100644
index 0000000..4f4e2d5
--- /dev/null
+++ b/prisma/sql/getEntryValues.sql
@@ -0,0 +1,8 @@
+-- @param {String} $1:entryId The ID of the entry to collect values for
+SELECT Value.id, Value.value, AssetField."order", Field.type, Field.meta, Value.fieldId, Field.name as fieldName FROM Value
+ INNER JOIN Entry ON Entry.Id = Value.entryId
+ INNER JOIN Asset on Asset.Id = Entry.assetId
+ INNER JOIN AssetField on AssetField.assetId = Asset.id AND AssetField.fieldId = Value.fieldId
+ INNER JOIN Field on Field.id = Value.fieldId
+ WHERE entryId = $1
+ ORDER BY AssetField."order" ASC
\ No newline at end of file