chore: dependency updates (#900)

This commit is contained in:
Andrew Smith 2025-12-21 07:55:44 -05:00 committed by GitHub
parent e2a3ded384
commit 733a0891cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 6326 additions and 5015 deletions

View File

@ -1,11 +1,11 @@
{
"name": "devenv",
"devDependencies": {
"@types/node": "^22.16.5",
"@types/shelljs": "^0.8.17",
"debug": "^4.4.1",
"@types/node": "^24.10.4",
"@types/shelljs": "^0.10.0",
"debug": "^4.4.3",
"dev-logger": "workspace:*",
"esbuild": "^0.25.10",
"esbuild": "^0.27.2",
"esbuild-register": "^3.6.0",
"shelljs": "^0.10.0"
}

File diff suppressed because one or more lines are too long

View File

@ -3,25 +3,25 @@ enableGlobalCache: true
nodeLinker: node-modules
packageExtensions:
'@apollo/client-react-streaming@*':
"@apollo/client-react-streaming@*":
dependencies:
graphql: '*'
'@prisma/client@*':
graphql: "*"
"@prisma/client@*":
dependencies:
prisma: '*'
prisma: "*"
cypress@*:
dependencies:
react: '*'
react-dom: '*'
react: "*"
react-dom: "*"
jest-config@*:
dependencies:
ts-node: '*'
ts-node: "*"
jest@*:
dependencies:
ts-node: '*'
ts-node: "*"
ts-jest@*:
dependencies:
jest-util: '*'
jest-util: "*"
pnpEnableEsmLoader: true
@ -41,4 +41,4 @@ supportedArchitectures:
- darwin
- win32
yarnPath: .yarn/releases/yarn-4.10.3.cjs
yarnPath: .yarn/releases/yarn-4.12.0.cjs

View File

@ -3,17 +3,17 @@
"description": "Playnite extension to automate starting/stopping of games via MQTT.",
"version": "4.0.2",
"devDependencies": {
"@types/shelljs": "^0.8.15",
"cpy": "^11.1.0",
"cpy-cli": "^5.0.0",
"esbuild": "^0.25.10",
"@types/shelljs": "^0.10.0",
"cpy": "^12.1.0",
"cpy-cli": "^6.0.0",
"esbuild": "^0.27.2",
"esbuild-register": "^3.6.0",
"nx": "^21.6.10",
"prettier": "^3.6.2",
"nx": "^22.3.3",
"prettier": "^3.7.4",
"rimraf": "^6.1.2",
"shelljs": "^0.8.5",
"typescript": "^5.9.2",
"shelljs": "^0.10.0",
"typescript": "^5.9.3",
"versioning": "workspace:*",
"yaml": "^2.7.0"
"yaml": "^2.8.2"
}
}

View File

@ -3,17 +3,17 @@
"description": "Playnite extension required for Playnite Web.",
"version": "4.0.2",
"devDependencies": {
"@types/shelljs": "^0.8.17",
"cpy": "^12.0.1",
"@types/shelljs": "^0.10.0",
"cpy": "^12.1.0",
"cpy-cli": "^6.0.0",
"esbuild": "^0.25.10",
"esbuild": "^0.27.2",
"esbuild-register": "^3.6.0",
"nx": "^21.6.10",
"prettier": "^3.6.2",
"nx": "^22.3.3",
"prettier": "^3.7.4",
"rimraf": "^6.1.2",
"shelljs": "^0.10.0",
"typescript": "^5.9.2",
"typescript": "^5.9.3",
"versioning": "workspace:*",
"yaml": "^2.8.1"
"yaml": "^2.8.2"
}
}

View File

@ -3,47 +3,48 @@
"version": "0.0.1",
"sideEffects": false,
"dependencies": {
"@prisma/client": "^6.16.2",
"@prisma/adapter-pg": "^7.2.0",
"@prisma/client": "^7.2.0",
"async-mqtt": "^2.6.3",
"db-client": "workspace:*",
"dev-logger": "workspace:*",
"express": "^4.21.2",
"isomorphic-dompurify": "^2.26.0",
"lodash-es": "^4.17.21",
"prisma": "^6.16.2",
"sharp": "^0.34.3",
"express": "^4.22.1",
"isomorphic-dompurify": "^2.34.0",
"lodash-es": "^4.17.22",
"prisma": "^7.2.0",
"sharp": "^0.34.5",
"sourced-assets": "workspace:*",
"uuid": "^11.1.0",
"winston": "^3.17.0",
"uuid": "^13.0.0",
"winston": "^3.19.0",
"winston-daily-rotate-file": "^5.0.0"
},
"devDependencies": {
"@jest/globals": "^30.0.5",
"@nx/devkit": "^21.6.10",
"@types/express": "^4.17.23",
"@jest/globals": "^30.2.0",
"@nx/devkit": "^22.3.3",
"@types/express": "^4.17.25",
"@types/jest": "^30.0.0",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.16.5",
"@types/shelljs": "^0.8.17",
"@yarnpkg/pnpify": "^4.1.5",
"concurrently": "^9.2.0",
"cross-env": "^10.0.0",
"@types/node": "^24.10.4",
"@types/shelljs": "^0.10.0",
"@yarnpkg/pnpify": "^4.1.6",
"concurrently": "^9.2.1",
"cross-env": "^10.1.0",
"dev-services": "workspace:*",
"esbuild": "^0.25.10",
"esbuild": "^0.27.2",
"esbuild-plugin-istanbul": "^0.3.0",
"glob": "^11.1.0",
"jest": "^30.0.5",
"nodemon": "^3.1.10",
"nx": "^21.6.10",
"glob": "^13.0.0",
"jest": "^30.2.0",
"nodemon": "^3.1.11",
"nx": "^22.3.3",
"nyc": "^17.1.0",
"prettier": "^3.6.2",
"prettier": "^3.7.4",
"rimraf": "^6.1.2",
"shelljs": "^0.10.0",
"ts-jest": "^29.4.1",
"ts-jest": "^29.4.6",
"tslib": "^2.8.1",
"tsx": "^4.20.4",
"typescript": "^5.9.2",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"versioning": "workspace:*",
"wait-on": "^8.0.4"
"wait-on": "^9.0.3"
}
}

View File

@ -1,5 +1,5 @@
# Build stage
FROM node:22-alpine3.20 AS builder
FROM node:24-alpine3.20 AS builder
WORKDIR /opt/playnite-web-app
COPY _packaged/package.json ./
@ -10,7 +10,7 @@ RUN npm install --force --omit=dev
# Runtime stage
FROM node:22-alpine3.20
FROM node:24-alpine3.20
LABEL org.opencontainers.image.source=https://github.com/andrew-codes/playnite-web
RUN apk add --no-cache \

View File

@ -35,7 +35,6 @@ const config = defineConfig({
baseUrl: 'http://localhost:3000',
video: process.env.CMD === 'run',
videoCompression: 32,
experimentalStudio: false,
experimentalSourceRewriting: false,
modifyObstructiveCode: false,
setupNodeEvents: async (on, config) => {

View File

@ -24,7 +24,9 @@ describe(`Game details remote control.
})
cy.get('[data-test="GameFigure"] button img').eq(0).click({ force: true })
cy.get('[data-test="Actions"]').children().should('have.length', 0)
cy.get('[data-test="Actions"]', { timeout: 10000 })
.children()
.should('have.length', 0)
})
})
@ -42,7 +44,9 @@ describe(`Game details remote control.
})
cy.get('[data-test="GameFigure"] button img').eq(0).click({ force: true })
cy.get('[data-test="Actions"]').children().should('have.length', 0)
cy.get('[data-test="Actions"]', { timeout: 10000 })
.children()
.should('have.length', 0)
})
describe('With Webhook setting.', () => {
@ -63,6 +67,7 @@ describe(`Game details remote control.
.then((library) => {
cy.signIn('test', 'test')
cy.visit(`/u/test/${library.body.data.syncLibrary.id}`)
cy.waitForImages(40)
})
})
@ -77,7 +82,7 @@ describe(`Game details remote control.
.eq(0)
.click({ force: true })
cy.get('[data-test="Actions"] button')
cy.get('[data-test="Actions"] button', { timeout: 10000 })
.eq(0)
.contains('PC (Windows) via Steam')
cy.get('[data-test="Actions"] button').last().click()
@ -103,9 +108,12 @@ describe(`Game details remote control.
.contains('Sony PlayStation 5 via PlayStation')
.click()
cy.get('[data-test="Actions"] button').eq(0).click()
cy.get('[data-test="Actions"] button', { timeout: 10000 }).eq(0).click()
cy.wait('@api')
// Wait a moment for the webhook to be posted.
cy.wait(5000)
cy.request({
method: 'GET',
url: '/echo',
@ -144,7 +152,7 @@ describe(`Game details remote control.
.find('button img')
.click({ force: true })
cy.get('[data-test="Actions"] button')
cy.get('[data-test="Actions"] button', { timeout: 10000 })
.eq(0)
.contains('PC (Windows) via Steam')
cy.get('[data-test="Actions"] button').last().click()
@ -161,7 +169,7 @@ describe(`Game details remote control.
.contains('Sony PlayStation 5 via PlayStation')
.click()
cy.get('[data-test="Actions"] button').eq(0).click()
cy.get('[data-test="Actions"] button', { timeout: 10000 }).eq(0).click()
cy.get('[data-test="Actions"] li')
.eq(2)
.contains('button', 'Stop game')
@ -169,6 +177,9 @@ describe(`Game details remote control.
cy.get('[data-test="Actions"] li').should('have.length', 1)
cy.wait('@api')
// Wait a moment for the webhook to be posted.
cy.wait(5000)
cy.request({
method: 'GET',
url: '/echo',
@ -202,7 +213,7 @@ describe(`Game details remote control.
.find('button img')
.click({ force: true })
cy.get('[data-test="Actions"] button')
cy.get('[data-test="Actions"] button', { timeout: 10000 })
.eq(0)
.contains('PC (Windows) via Steam')
cy.get('[data-test="Actions"] button').last().click()
@ -219,13 +230,16 @@ describe(`Game details remote control.
.contains('Sony PlayStation 5 via PlayStation')
.click()
cy.get('[data-test="Actions"] button').eq(0).click()
cy.get('[data-test="Actions"] button', { timeout: 10000 }).eq(0).click()
cy.get('[data-test="Actions"] li')
.eq(1)
.contains('button', 'Restart game')
.click()
cy.wait('@api')
// Wait a moment for the webhook to be posted.
cy.wait(5000)
cy.request({
method: 'GET',
url: '/echo',

View File

@ -14,7 +14,7 @@ declare global {
password: string,
libraryData: any,
) => Chainable<Response<any>>
waitForImages: () => Chainable<JQuery<HTMLImageElement>>
waitForImages: (count: number) => Chainable<JQuery<HTMLImageElement>>
lighthouse: (
thresholds?: any,
options?: any,
@ -71,7 +71,6 @@ Cypress.on('window:before:load', (win) => {
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
originalFn(url, options)
cy.get('[data-test=Navigation]', { timeout: 15000 })
cy.waitForImages()
// Wait for MUI to be ready
// cy.wait(2200)
})
@ -143,9 +142,9 @@ Cypress.Commands.add(
},
)
Cypress.Commands.add('waitForImages', () => {
Cypress.Commands.add('waitForImages', (count?: number) => {
return cy.get('img', { timeout: 10000 }).should(($images) => {
$images.each((_, img) => {
$images.slice(0, count ?? $images.length).each((_, img) => {
expect(img.complete).to.equal(true)
})
})

View File

@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@ -1,6 +1,11 @@
//@ts-check
const { composePlugins, withNx } = require('@nx/next')
import { composePlugins, withNx } from '@nx/next'
import pkg from './package.json' with { type: 'json' }
const localPackages = Object.entries(pkg.dependencies || {})
.filter(([dep, v]) => v.startsWith('workspace:'))
.map(([dep]) => dep)
/**
* @type {import('@nx/next/plugins/with-nx').WithNxOptions}
@ -26,7 +31,8 @@ const nextConfig = {
forceSwcTransforms: process.env.INSTRUMENT !== 'true',
ppr: false,
},
transpilePackages: ['db-client', '@prisma/client'],
serverExternalPackages: ['@prisma/client', '@prisma/adapter-pg', 'pg'],
transpilePackages: localPackages,
// Configure webpack for code coverage instrumentation
webpack: (config, { isServer }) => {
@ -34,7 +40,7 @@ const nextConfig = {
// Instrument client-side code (React components, client code)
if (!isServer) {
config.module.rules.push({
test: /\.(tsx?|jsx?)$/,
test: /\\.(tsx?|jsx?)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
@ -46,6 +52,35 @@ const nextConfig = {
})
}
}
// Mark Prisma packages as external to prevent bundling
if (isServer) {
config.externals = config.externals || []
// Handle both array and function externals
const prismaExternals = [
'@prisma/client',
'@prisma/adapter-pg',
'pg',
/^@prisma\/client\/.*/,
]
if (Array.isArray(config.externals)) {
config.externals.push(...prismaExternals)
} else if (typeof config.externals === 'function') {
const originalExternals = config.externals
config.externals = async (context, request, callback) => {
if (
prismaExternals.some((ext) =>
ext instanceof RegExp ? ext.test(request) : ext === request,
)
) {
return callback(null, `commonjs ${request}`)
}
return originalExternals(context, request, callback)
}
}
}
return config
},
@ -56,4 +91,4 @@ const plugins = [withNx]
const config = composePlugins(...plugins)(nextConfig)
module.exports = config
export default config

View File

@ -3,20 +3,21 @@
"version": "4.0.2",
"sideEffects": false,
"dependencies": {
"@apollo/client": "^4.0.5",
"@apollo/client-integration-nextjs": "^0.13.2",
"@apollo/client": "^4.0.11",
"@apollo/client-integration-nextjs": "^0.14.3",
"@emotion/cache": "^11.14.0",
"@emotion/react": "^11.14.0",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.14.1",
"@graphql-yoga/plugin-csrf-prevention": "^3.15.1",
"@graphql-yoga/plugin-jwt": "^3.9.1",
"@mui/icons-material": "^7.3.1",
"@mui/material": "^7.3.1",
"@mui/utils": "^7.3.1",
"@prisma/client": "^6.16.2",
"@reduxjs/toolkit": "^2.8.2",
"@whatwg-node/server": "^0.10.12",
"@graphql-yoga/plugin-csrf-prevention": "^3.18.0",
"@graphql-yoga/plugin-jwt": "^3.12.0",
"@mui/icons-material": "^7.3.6",
"@mui/material": "^7.3.6",
"@mui/utils": "^7.3.6",
"@prisma/adapter-pg": "^7.2.0",
"@prisma/client": "^7.2.0",
"@reduxjs/toolkit": "^2.11.2",
"@whatwg-node/server": "^0.10.17",
"@whatwg-node/server-plugin-cookies": "^1.0.5",
"async-mqtt": "^2.6.3",
"bcrypt": "^6.0.0",
@ -25,130 +26,130 @@
"css-mediaquery": "^0.1.2",
"dataloader": "^2.2.3",
"db-client": "workspace:*",
"dotenv": "^17.2.1",
"express": "^4.21.2",
"framer-motion": "^12.23.12",
"graphql": "^16.11.0",
"graphql-scalars": "^1.24.2",
"dotenv": "^17.2.3",
"express": "^4.22.1",
"framer-motion": "^12.23.26",
"graphql": "^16.12.0",
"graphql-scalars": "^1.25.0",
"graphql-ws": "^6.0.6",
"graphql-yoga": "^5.15.1",
"graphql-yoga": "^5.18.0",
"helmet": "^8.1.0",
"intl-parse-accept-language": "^1.0.0",
"is-ip": "^5.0.1",
"isbot": "^5.1.30",
"isomorphic-dompurify": "^2.26.0",
"isbot": "^5.1.32",
"isomorphic-dompurify": "^2.34.0",
"istanbul-lib-instrument": "^6.0.3",
"jsonwebtoken": "^9.0.2",
"jsonwebtoken": "^9.0.3",
"lodash": "^4.17.21",
"next": "^15.5.9",
"prisma": "^6.16.2",
"next": "^16.1.0",
"prisma": "^7.2.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-redux": "^9.2.0",
"react-window": "^2.2.0",
"react-window": "^2.2.3",
"rxjs": "^7.8.2",
"sourced-assets": "workspace:*",
"ua-parser-js": "^2.0.4",
"uuid": "^11.1.0",
"winston": "^3.17.0",
"ua-parser-js": "^2.0.7",
"uuid": "^13.0.0",
"winston": "^3.19.0",
"winston-daily-rotate-file": "^5.0.0",
"ws": "^8.18.3",
"zod": "^4.0.17"
"zod": "^4.2.1"
},
"devDependencies": {
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@babel/preset-react": "^7.27.1",
"@babel/preset-typescript": "^7.27.1",
"@babel/core": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@babel/preset-react": "^7.28.5",
"@babel/preset-typescript": "^7.28.5",
"@cypress-audit/lighthouse": "^1.4.2",
"@cypress/code-coverage": "^3.14.6",
"@cypress/webpack-preprocessor": "^7.0.1",
"@eddeee888/gcg-typescript-resolver-files": "^0.12.1",
"@eslint/compat": "^1.1.1",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.8.0",
"@graphql-codegen/cli": "^5.0.7",
"@graphql-codegen/graphql-modules-preset": "^4.0.17",
"@graphql-codegen/typescript": "^4.1.6",
"@graphql-codegen/typescript-resolvers": "^4.5.1",
"@jest/globals": "^30.1.2",
"@cypress/code-coverage": "^3.14.7",
"@cypress/webpack-preprocessor": "^7.0.2",
"@eddeee888/gcg-typescript-resolver-files": "^0.14.1",
"@eslint/compat": "^2.0.0",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@graphql-codegen/cli": "^6.1.0",
"@graphql-codegen/graphql-modules-preset": "^5.1.2",
"@graphql-codegen/typescript": "^5.0.7",
"@graphql-codegen/typescript-resolvers": "^5.1.5",
"@jest/globals": "^30.2.0",
"@jspm/core": "^2.1.0",
"@next/eslint-plugin-next": "^15.5.9",
"@nx/cypress": "^21.6.10",
"@nx/devkit": "^21.6.10",
"@nx/eslint-plugin": "^21.6.10",
"@nx/jest": "^21.6.10",
"@nx/js": "^21.6.10",
"@nx/next": "21.6.10",
"@nx/react": "^21.6.10",
"@next/eslint-plugin-next": "^16.1.0",
"@nx/cypress": "^22.3.3",
"@nx/devkit": "^22.3.3",
"@nx/eslint-plugin": "^22.3.3",
"@nx/jest": "^22.3.3",
"@nx/js": "^22.3.3",
"@nx/next": "22.3.3",
"@nx/react": "^22.3.3",
"@swc-node/register": "~1.11.1",
"@swc/cli": "~0.7.9",
"@swc/core": "~1.15.7",
"@swc/helpers": "~0.5.17",
"@swc/plugin-emotion": "^14.1.0",
"@types/crypto-js": "^4.2.2",
"@types/express": "^4.17.23",
"@types/express": "^4.17.25",
"@types/jest": "^30.0.0",
"@types/lodash": "^4.17.12",
"@types/node": "^22.18.3",
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"@types/shelljs": "^0.8.17",
"@types/styled-components": "^5.1.34",
"@typescript-eslint/parser": "^8.43.0",
"@types/lodash": "^4.17.21",
"@types/node": "^24.10.4",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@types/shelljs": "^0.10.0",
"@types/styled-components": "^5.1.36",
"@typescript-eslint/parser": "^8.50.0",
"@vitejs/plugin-react": "^5.1.2",
"@yarnpkg/pnpify": "^4.1.5",
"babel-jest": "^30.1.2",
"@yarnpkg/pnpify": "^4.1.6",
"babel-jest": "^30.2.0",
"babel-loader": "^10.0.0",
"babel-plugin-direct-import": "^1.0.0",
"babel-plugin-istanbul": "^7.0.0",
"babel-plugin-istanbul": "^7.0.1",
"cypress": "^15.8.1",
"cypress-cdp": "^1.6.84",
"cypress-cdp": "^1.6.87",
"cypress-image-diff-html-report": "^2.2.0",
"cypress-image-diff-js": "^2.4.0",
"cypress-split": "^1.24.21",
"cypress-image-diff-js": "^2.5.0",
"cypress-split": "^1.24.25",
"dev-logger": "workspace:*",
"dev-services": "workspace:*",
"esbuild": "^0.25.10",
"esbuild": "^0.27.2",
"esbuild-plugin-istanbul": "^0.3.0",
"eslint": "^9.35.0",
"eslint-config-next": "^15.5.9",
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-cypress": "^3.6.0",
"eslint-plugin-cypress": "^5.2.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"glob": "^11.1.0",
"eslint-plugin-react-hooks": "^7.0.1",
"glob": "^13.0.0",
"graphql-modules": "^3.0.0",
"istanbul-lib-coverage": "^3.2.2",
"jest": "^30.1.3",
"jest-util": "^30.0.5",
"jest": "^30.2.0",
"jest-util": "^30.2.0",
"lodash": "^4.17.21",
"nodemon": "^3.1.10",
"nodemon": "^3.1.11",
"npm-run-all": "^4.1.5",
"nx": "^21.6.10",
"nx": "^22.3.3",
"nyc": "^17.1.0",
"prettier": "^3.6.2",
"prettier": "^3.7.4",
"react-devtools": "^7.0.1",
"rimraf": "^6.1.2",
"shelljs": "^0.10.0",
"sourced-assets": "workspace:*",
"start-server-and-test": "^2.0.13",
"swr": "^2.3.6",
"ts-jest": "^29.4.1",
"ts-loader": "^9.5.2",
"start-server-and-test": "^2.1.3",
"swr": "^2.3.8",
"ts-jest": "^29.4.6",
"ts-loader": "^9.5.4",
"ts-node": "^10.9.2",
"tslib": "^2.8.1",
"tsx": "^4.20.4",
"typescript": "^5.9.2",
"typescript-eslint": "^8.40.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.50.0",
"versioning": "workspace:*",
"vite": "^7.1.5",
"vite-plugin-istanbul": "^7.1.0",
"vite": "^7.3.0",
"vite-plugin-istanbul": "^7.2.1",
"vite-plugin-node-polyfills": "^0.24.0",
"vite-tsconfig-paths": "^5.1.4",
"wait-on": "^8.0.4",
"webpack": "^5.101.3"
"vite-tsconfig-paths": "^6.0.3",
"wait-on": "^9.0.3",
"webpack": "^5.104.1"
}
}

View File

@ -10,7 +10,7 @@ import pkg from '../package.json' with { type: 'json' }
async function run() {
const buildNext = new Promise((resolve, reject) => {
const nextBuild = sh.exec(`yarn next build`, {
const nextBuild = sh.exec(`yarn next build --webpack`, {
async: true,
env: {
...process.env,
@ -80,6 +80,9 @@ async function run() {
external: Object.entries(pkg.dependencies)
.filter(([name, version]) => !version.startsWith('workspace:'))
.map(([name, version]) => name),
logOverride: {
'empty-import-meta': 'silent',
},
bundle: true,
minify: false,
outdir: '_custom-server-build',
@ -103,7 +106,7 @@ async function run() {
serverContents = serverContents
.replace(/var __filename.*$/gm, '')
.replace(/var __dirname.*;$/gm, '')
.replace(/import_meta\.url/g, '__dirname')
.replace(/import_meta\.url/g, 'require("url").pathToFileURL(__dirname).href')
await fs.writeFile('_custom-server-build/server.js', serverContents, 'utf8')

View File

@ -14,6 +14,10 @@ async function run() {
await fs.cp('_custom-server-build', '_packaged', { recursive: true })
await fs.cp('.next', '_packaged/.next', { recursive: true })
await fs.cp(
path.join('../../libs/db-client/src/prisma.config.ts'),
path.join('_packaged/prisma.config.ts'),
)
await fs.cp(
path.join('../../libs/db-client/src/schema.prisma'),
path.join('_packaged/schema.prisma'),
@ -23,6 +27,11 @@ async function run() {
path.join('_packaged/migrations'),
{ recursive: true },
)
await fs.cp(
path.join('../../libs/db-client/.generated'),
path.join('_packaged/.generated'),
{ recursive: true },
)
logger.info('Copying and modifying package.json')
const pkg = JSON.parse(await fs.readFile('package.json', 'utf8'))
@ -39,6 +48,25 @@ async function run() {
'utf8',
)
logger.info('Copying generated Prisma client')
await fs.mkdir(path.join('_packaged/node_modules/db-client'), {
recursive: true,
})
await fs.cp(
path.join('../../libs/db-client/.generated'),
path.join('_packaged/node_modules/db-client/.generated'),
{ recursive: true },
)
await fs.cp(
path.join('../../libs/db-client/src'),
path.join('_packaged/node_modules/db-client/src'),
{ recursive: true },
)
await fs.cp(
path.join('../../libs/db-client/package.json'),
path.join('_packaged/node_modules/db-client/package.json'),
)
logger.info('Copying binaries for Prisma')
await fs.mkdir(path.join('_packaged/.prisma/client'), {
recursive: true,

View File

@ -48,14 +48,12 @@ const GameGrid: FC<{
// })
// }, [gridRef, subscribe])
const Cell = ({ columnIndex, rowIndex, style }) => {
const Cell = ({ ariaAttributes, columnIndex, rowIndex, style }) => {
const game = games[rowIndex * columns + columnIndex]
if (!game) {
return null
}
return (
<div
{...ariaAttributes}
style={{
...style,
left: style.left,
@ -63,34 +61,36 @@ const GameGrid: FC<{
...(style.height && { height: style?.height }),
}}
>
<GameFigure
game={game}
width={`${style.width - horizontalGap}px`}
onSelect={(evt) => {
onSelect?.(evt, game)
}}
priority={true}
>
<Typography
variant="caption"
component="figcaption"
sx={{
fontWeight: 'bold',
textWrap: 'balance',
lineHeight: '1.5',
textOverflow: 'ellipsis',
overflowY: 'hidden',
maxHeight: '4rem',
lineClamp: '2',
fontSize: '15px',
display: '-webkit-box',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical ',
{game && (
<GameFigure
game={game}
width={`${style.width - horizontalGap}px`}
onSelect={(evt) => {
onSelect?.(evt, game)
}}
priority={true}
>
{game.primaryRelease?.title || 'Unknown Game'}
</Typography>
</GameFigure>
<Typography
variant="caption"
component="figcaption"
sx={{
fontWeight: 'bold',
textWrap: 'balance',
lineHeight: '1.5',
textOverflow: 'ellipsis',
overflowY: 'hidden',
maxHeight: '4rem',
lineClamp: '2',
fontSize: '15px',
display: '-webkit-box',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical ',
}}
>
{game.primaryRelease?.title || 'Unknown Game'}
</Typography>
</GameFigure>
)}
</div>
)
}

View File

@ -170,9 +170,4 @@ async function middleware(request: NextRequest) {
return NextResponse.next()
}
const config = {
matcher: ['/((?!_next|api|favicon.ico|sitemap.xml|robots.txt).*)'],
runtime: 'nodejs', // Use Node.js runtime instead of Edge Runtime for custom server compatibility
}
export { config, middleware }
export { middleware }

View File

@ -103,9 +103,10 @@ export const signUp: NonNullable<MutationResolvers['signUp']> = async (
return merge({}, authenticatedUser, { user: omit(newUser, ['password']) })
} catch (error: any) {
if (error?.meta?.target) {
const target = error.meta.target as string
if (target.includes('username')) {
if (error?.meta?.driverAdapterError?.cause?.constraint?.fields) {
const fields = error.meta.driverAdapterError.cause.constraint
.fields as Array<string>
if (fields.includes('username')) {
throw new GraphQLError('Username is already taken.', {
extensions: {
code: 'BAD_USER_INPUT',
@ -113,7 +114,7 @@ export const signUp: NonNullable<MutationResolvers['signUp']> = async (
},
})
}
if (target.includes('email')) {
if (fields.includes('email')) {
throw new GraphQLError('Email is already in use.', {
extensions: {
code: 'BAD_USER_INPUT',

View File

@ -3,14 +3,14 @@
"version": "0.0.1",
"sideEffects": false,
"devDependencies": {
"@types/node": "^22.16.5",
"@types/node": "^24.10.4",
"db-client": "workspace:*",
"dev-logger": "workspace:*",
"nx": "^21.6.10",
"prettier": "^3.6.2",
"nx": "^22.3.3",
"prettier": "^3.7.4",
"shelljs": "^0.10.0",
"tslib": "^2.8.1",
"tsx": "^4.20.4",
"typescript": "^5.9.2"
"tsx": "^4.21.0",
"typescript": "^5.9.3"
}
}

View File

@ -22,25 +22,27 @@
"dev-logger": "workspace:*"
},
"peerDependencies": {
"@prisma/client": "^6.16.2",
"@prisma/adapter-pg": "^7.2.0",
"@prisma/client": "^7.2.0",
"isomorphic-dompurify": "^2.26.0",
"prisma": "^6.16.2"
"prisma": "^7.2.0"
},
"devDependencies": {
"@prisma/client": "^6.16.2",
"@types/node": "^22.16.5",
"@yarnpkg/pnpify": "^4.1.5",
"glob": "^11.1.0",
"isomorphic-dompurify": "^2.26.0",
"jest": "^30.0.5",
"nx": "^21.6.10",
"prettier": "^3.6.2",
"prisma": "^6.16.2",
"@prisma/adapter-pg": "^7.2.0",
"@prisma/client": "^7.2.0",
"@types/node": "^24.10.4",
"@yarnpkg/pnpify": "^4.1.6",
"glob": "^13.0.0",
"isomorphic-dompurify": "^2.34.0",
"jest": "^30.2.0",
"nx": "^22.3.3",
"prettier": "^3.7.4",
"prisma": "^7.2.0",
"rimraf": "^6.1.2",
"shelljs": "^0.10.0",
"ts-jest": "^29.4.1",
"ts-jest": "^29.4.6",
"tslib": "^2.8.1",
"tsx": "^4.20.4",
"typescript": "^5.9.2"
"tsx": "^4.21.0",
"typescript": "^5.9.3"
}
}

View File

@ -0,0 +1,9 @@
import path from 'path'
import { defineConfig } from 'prisma/config'
export default defineConfig({
schema: path.join(__dirname, 'schema.prisma'),
migrations: {
path: path.join(__dirname, 'migrations'),
},
})

View File

@ -20,10 +20,10 @@
},
"prepare": {
"executor": "nx:run-commands",
"outputs": ["{projectRoot}/.generated"],
"outputs": ["{projectRoot}/src/generated"],
"options": {
"parallel": false,
"commands": ["yarn pnpify prisma generate --schema=src/schema.prisma"],
"commands": ["npx prisma generate --schema=src/schema.prisma"],
"cwd": "{projectRoot}",
"env": {
"DATABASE_URL": "postgresql://local:dev@localhost:5432/games?schema=public"
@ -33,7 +33,7 @@
"reset-db": {
"executor": "nx:run-commands",
"options": {
"command": "yarn pnpify prisma migrate reset --force --schema=src/schema.prisma",
"command": "yarn prisma migrate reset --force --schema=src/schema.prisma",
"cwd": "{projectRoot}",
"env": {
"DATABASE_URL": "postgresql://local:dev@localhost:5432/games?schema=public"
@ -44,7 +44,7 @@
"executor": "nx:run-commands",
"dependsOn": ["build"],
"options": {
"command": "yarn pnpify prisma migrate dev --create-only --name migration --schema=src/schema.prisma",
"command": "yarn prisma migrate dev --create-only --name migration --schema=src/schema.prisma",
"cwd": "{projectRoot}",
"env": {
"DATABASE_URL": "postgresql://local:dev@localhost:5432/games?schema=public"

View File

@ -1,22 +1,21 @@
import { PrismaClient } from '@prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import logger from 'dev-logger'
import { PrismaClient } from '../.generated/client'
import { htmlSanitizationExtension } from './extensions/htmlSanitization'
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL })
declare global {
var __prisma__: PrismaClient | undefined
}
export const prisma = global.__prisma__ ?? new PrismaClient()
export const prisma = global.__prisma__ ?? new PrismaClient({ adapter })
prisma.$extends(htmlSanitizationExtension)
if (process.env.NODE_ENV !== 'production') {
global.__prisma__ = prisma
}
// Re-export generated types if you like
export * from '@prisma/client'
export type { PrismaClient }
const gracefulShutdown = async (signal: string) => {
logger.info(`Received ${signal}. Shutting down gracefully...`)
try {
@ -34,5 +33,6 @@ process.on('SIGTERM', () => gracefulShutdown('SIGTERM'))
process.on('SIGINT', () => gracefulShutdown('SIGINT'))
// export default client
export * from '@prisma/client'
export * from '../.generated/client'
export type { PrismaClient }
export default prisma

View File

@ -1,5 +1,5 @@
import { Prisma } from '@prisma/client'
import DOMPurify from 'isomorphic-dompurify'
import { Prisma } from '../../.generated/client'
const SANITIZE_CONFIG = {
FORBID_TAGS: ['script', 'link', 'style', 'meta', 'title', 'base'],

View File

@ -2,11 +2,11 @@ import { spawnSync } from 'child_process'
import path from 'path'
const migrate = async () => {
const schemaPath = path.join(__dirname, 'schema.prisma')
const schemaPath = path.join(__dirname, 'prisma.config.ts')
const migrate = spawnSync(
'npx',
['prisma', 'migrate', 'deploy', '--schema', schemaPath],
['prisma', 'migrate', 'deploy', '--config', schemaPath],
{
stdio: 'inherit',
env: process.env,

View File

@ -0,0 +1,12 @@
import path from 'path'
import { defineConfig, env } from 'prisma/config'
export default defineConfig({
schema: path.join(__dirname, 'schema.prisma'),
migrations: {
path: path.join(__dirname, 'migrations'),
},
datasource: {
url: env('DATABASE_URL'),
},
})

View File

@ -5,14 +5,14 @@
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
moduleFormat = "cjs"
provider = "prisma-client"
output = "../.generated"
engineType = "binary"
binaryTargets = ["native", "linux-musl-arm64-openssl-3.0.x", "linux-musl-openssl-3.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model SiteSettings {

View File

@ -6,7 +6,7 @@
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"noEmit": false,
"noEmit": true,
"allowJs": true,
"module": "ESNext",
"types": ["node"]

View File

@ -11,15 +11,15 @@
}
},
"dependencies": {
"winston": "^3.17.0",
"winston": "^3.19.0",
"winston-daily-rotate-file": "^5.0.0"
},
"devDependencies": {
"@types/node": "^22.16.5",
"glob": "^11.1.0",
"nx": "^21.6.10",
"@types/node": "^24.10.4",
"glob": "^13.0.0",
"nx": "^22.3.3",
"rimraf": "^6.1.2",
"tsx": "^4.20.4",
"typescript": "^5.9.2"
"tsx": "^4.21.0",
"typescript": "^5.9.3"
}
}

View File

@ -6,19 +6,19 @@
"description": "Semantic-release plugin to generate an installer manifest for Playnite plugins.",
"main": "./.dist/src/index.js",
"dependencies": {
"conventional-changelog-angular": "^8.0.0",
"conventional-changelog-angular": "^8.1.0",
"conventional-commits-filter": "^5.0.0",
"conventional-commits-parser": "^6.2.0",
"debug": "^4.4.1",
"conventional-commits-parser": "^6.2.1",
"debug": "^4.4.3",
"dev-logger": "workspace:*",
"get-stream": "^9.0.1",
"import-from-esm": "^2.0.0",
"into-stream": "^8.0.1",
"lodash-es": "^4.17.21",
"read-package-up": "^11.0.0",
"yaml": "^2.8.1"
"into-stream": "^9.0.0",
"lodash-es": "^4.17.22",
"read-package-up": "^12.0.0",
"yaml": "^2.8.2"
},
"devDependencies": {
"esbuild": "^0.25.10"
"esbuild": "^0.27.2"
}
}

View File

@ -26,16 +26,16 @@
"dev-logger": "workspace:*"
},
"devDependencies": {
"@types/node": "^22.16.5",
"glob": "^11.1.0",
"jest": "^30.0.5",
"nx": "^21.6.10",
"prettier": "^3.6.2",
"@types/node": "^24.10.4",
"glob": "^13.0.0",
"jest": "^30.2.0",
"nx": "^22.3.3",
"prettier": "^3.7.4",
"rimraf": "^6.1.2",
"shelljs": "^0.10.0",
"ts-jest": "^29.4.1",
"ts-jest": "^29.4.6",
"tslib": "^2.8.1",
"tsx": "^4.20.4",
"typescript": "^5.9.2"
"tsx": "^4.21.0",
"typescript": "^5.9.3"
}
}

View File

@ -1,3 +1,3 @@
import { slug } from './slug.js'
import { slug } from './slug'
export { slug }

View File

@ -4,16 +4,16 @@
"private": true,
"main": "src/index.ts",
"dependencies": {
"debug": "^4.4.1",
"lodash-es": "^4.17.21",
"semver": "^7.7.2",
"debug": "^4.4.3",
"lodash-es": "^4.17.22",
"semver": "^7.7.3",
"shelljs": "^0.10.0"
},
"devDependencies": {
"@types/semver": "^7.7.0",
"@types/shelljs": "^0.8.17",
"@types/semver": "^7.7.1",
"@types/shelljs": "^0.10.0",
"dev-logger": "workspace:*",
"nx": "^21.6.10",
"nx": "^22.3.3",
"rimraf": "^6.1.2"
}
}

View File

@ -3,7 +3,7 @@
"version": "3.1.4",
"private": true,
"engines": {
"node": "22.17.0"
"node": "24.12.0"
},
"workspaces": [
"apps/*",
@ -13,62 +13,62 @@
],
"devDependencies": {
"@andrew-codes/playnite-plugin-installer-manifest": "workspace:*",
"@emotion/babel-plugin": "11.11.0",
"@eslint/js": "^9.8.0",
"@nx/cypress": "^21.6.10",
"@nx/eslint": "^21.6.10",
"@nx/eslint-plugin": "^21.6.10",
"@nx/jest": "^21.6.10",
"@nx/js": "^21.6.10",
"@nx/next": "21.6.10",
"@nx/react": "^21.6.10",
"@emotion/babel-plugin": "11.13.5",
"@eslint/js": "^9.39.2",
"@nx/cypress": "^22.3.3",
"@nx/eslint": "^22.3.3",
"@nx/eslint-plugin": "^22.3.3",
"@nx/jest": "^22.3.3",
"@nx/js": "^22.3.3",
"@nx/next": "22.3.3",
"@nx/react": "^22.3.3",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/exec": "^7.1.0",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^11.0.4",
"@semantic-release/release-notes-generator": "^14.0.3",
"@semantic-release/github": "^12.0.2",
"@semantic-release/release-notes-generator": "^14.1.0",
"@swc-node/register": "~1.11.1",
"@swc/cli": "~0.7.9",
"@swc/core": "~1.15.7",
"@swc/helpers": "~0.5.17",
"@swc/plugin-emotion": "^14.1.0",
"@types/jest": "^30.0.0",
"@types/node": "^22.18.3",
"@types/react": "^19.0.0",
"@types/react-dom": "19.0.0",
"@typescript-eslint/parser": "^8.44.0",
"cross-env": "^10.0.0",
"@types/node": "^24.10.4",
"@types/react": "^19.2.7",
"@types/react-dom": "19.2.3",
"@typescript-eslint/parser": "^8.50.0",
"cross-env": "^10.1.0",
"cypress": "^15.8.1",
"cz-conventional-changelog": "^3.3.0",
"dotenv": "^17.2.1",
"esbuild": "^0.25.10",
"dotenv": "^17.2.3",
"esbuild": "^0.27.2",
"esbuild-register": "^3.6.0",
"eslint": "^9.35.0",
"eslint-config-next": "^15.5.9",
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-cypress": "^3.6.0",
"eslint-plugin-cypress": "^5.2.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"glob": "^11.1.0",
"eslint-plugin-react-hooks": "^7.0.1",
"glob": "^13.0.0",
"husky": "^9.1.7",
"jest": "^30.1.3",
"jest-config": "^30.0.5",
"next": "^15.5.9",
"nx": "21.6.10",
"prettier": "^3.6.2",
"jest": "^30.2.0",
"jest-config": "^30.2.0",
"next": "^16.1.0",
"nx": "^22.3.3",
"prettier": "^3.7.4",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"semantic-release": "^24.2.7",
"ts-jest": "^29.4.1",
"semantic-release": "^25.0.2",
"ts-jest": "^29.4.6",
"ts-node": "^10.9.2",
"tslib": "^2.8.1",
"tsx": "^4.20.4",
"typescript": "^5.9.2",
"typescript-eslint": "^8.40.0",
"vite": "^7.1.5"
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.50.0",
"vite": "^7.3.0"
},
"resolutions": {
"braces@^3.0.2": "^3.0.3",
@ -76,6 +76,7 @@
"cross-spawn@^6.0.5": "^6.0.6",
"graphql": "16.10.0",
"ip@^2.0.0": "2.0.1",
"jws@^3.2.2": "^3.2.3",
"micromatch@^4.0.0": "^4.0.8",
"micromatch@^4.0.2": "^4.0.8",
"micromatch@^4.0.4": "^4.0.8",
@ -94,7 +95,7 @@
"ws@^7.5.5": "^7.5.10",
"ws@8.133.0": "^8.18.0"
},
"packageManager": "yarn@4.10.3",
"packageManager": "yarn@4.12.0",
"scripts": {
"prepare": "husky",
"release": "nx build playnite-plugin-installer-manifest && semantic-release"

10033
yarn.lock

File diff suppressed because it is too large Load Diff