diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index 263801b0..99a55494 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -21,7 +21,8 @@ ENV DATABASE_PATH=/tmp/build.db ENV DATABASE_URL=file:/tmp/build.db COPY --from=deps /app/node_modules ./node_modules COPY . . -RUN npx prisma generate +# Build the application (includes prisma generate as per Prisma best practices) +# Real Prisma client will be regenerated at runtime to ensure engine availability RUN npx prisma db push --skip-generate RUN npm run build && rm -f /tmp/build.db @@ -30,8 +31,11 @@ ENV NODE_ENV=production ENV PORT=3000 WORKDIR /app -# Install gosu for privilege dropping -RUN apt-get update && apt-get install -y --no-install-recommends gosu && rm -rf /var/lib/apt/lists/* +# Install gosu for privilege dropping and openssl for Prisma +RUN apt-get update && apt-get install -y --no-install-recommends \ + gosu \ + openssl \ + && rm -rf /var/lib/apt/lists/* RUN groupadd -g 1001 nodejs && useradd -r -u 1001 -g nodejs nextjs diff --git a/docker/web/entrypoint.sh b/docker/web/entrypoint.sh index 9d788d75..b53e752e 100755 --- a/docker/web/entrypoint.sh +++ b/docker/web/entrypoint.sh @@ -18,6 +18,16 @@ gosu nextjs sh -c ' # Set npm cache to writable directory export NPM_CONFIG_CACHE=/tmp/.npm + # Generate real Prisma client at runtime (replaces build-time stub) + echo "Generating Prisma client..." + npx prisma generate || { + echo "Warning: Prisma generate failed, attempting with checksum ignore..." + PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1 npx prisma generate || { + echo "Error: Failed to generate Prisma client" + exit 1 + } + } + if [ ! -f "$DB_PATH" ]; then echo "Database not found, initializing..." npx prisma db push --skip-generate diff --git a/package.json b/package.json index 262d0ca7..85a89092 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,11 @@ "private": true, "scripts": { "dev": "next dev", - "build": "node scripts/generate-prisma-stub.js && next build", + "build": "prisma generate && next build", "start": "next start", "lint": "next lint", "typecheck": "tsc --noEmit", - "postinstall": "node scripts/generate-prisma-stub.js || prisma generate || echo 'Prisma generate failed, using stub'" + "postinstall": "prisma generate || echo 'Prisma generate skipped'" }, "dependencies": { "@emotion/react": "^11.14.0", diff --git a/scripts/generate-prisma-stub.js b/scripts/generate-prisma-stub.js deleted file mode 100755 index 1aacd0c3..00000000 --- a/scripts/generate-prisma-stub.js +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env node - -/** - * This script generates a minimal Prisma Client stub to allow building - * when the Prisma engines cannot be downloaded (e.g., network restrictions). - * - * The actual Prisma engines must be available at runtime. - */ - -const fs = require('fs'); -const path = require('path'); - -const clientDir = path.join(__dirname, '..', 'node_modules', '.prisma', 'client'); - -// Ensure directory exists -fs.mkdirSync(clientDir, { recursive: true }); - -// Generate minimal client files -const indexContent = ` -// Auto-generated stub for build-time type checking -// Real Prisma Client will be generated at runtime - -class PrismaClient { - constructor(options = {}) { - this.user = createModelProxy('User'); - this.session = createModelProxy('Session'); - this.oAuthState = createModelProxy('OAuthState'); - this.setting = createModelProxy('Setting'); - this.accessList = createModelProxy('AccessList'); - this.accessListEntry = createModelProxy('AccessListEntry'); - this.certificate = createModelProxy('Certificate'); - this.proxyHost = createModelProxy('ProxyHost'); - this.redirectHost = createModelProxy('RedirectHost'); - this.deadHost = createModelProxy('DeadHost'); - this.apiToken = createModelProxy('ApiToken'); - this.auditEvent = createModelProxy('AuditEvent'); - } - - async $connect() { - throw new Error('Prisma Client stub - engines not available at build time'); - } - - async $disconnect() { - return Promise.resolve(); - } - - async $executeRaw() { - throw new Error('Prisma Client stub - engines not available at build time'); - } - - async $queryRaw() { - throw new Error('Prisma Client stub - engines not available at build time'); - } - - async $transaction() { - throw new Error('Prisma Client stub - engines not available at build time'); - } -} - -function createModelProxy(modelName) { - return new Proxy({}, { - get() { - throw new Error(\`Prisma Client stub - \${modelName} operations not available at build time\`); - } - }); -} - -exports.PrismaClient = PrismaClient; -exports.Prisma = { - ModelName: { - User: 'User', - Session: 'Session', - OAuthState: 'OAuthState', - Setting: 'Setting', - AccessList: 'AccessList', - AccessListEntry: 'AccessListEntry', - Certificate: 'Certificate', - ProxyHost: 'ProxyHost', - RedirectHost: 'RedirectHost', - DeadHost: 'DeadHost', - ApiToken: 'ApiToken', - AuditEvent: 'AuditEvent' - } -}; -`; - -const indexDtsContent = ` -// Auto-generated stub for build-time type checking - -export class PrismaClient { - constructor(options?: any); - user: any; - session: any; - oAuthState: any; - setting: any; - accessList: any; - accessListEntry: any; - certificate: any; - proxyHost: any; - redirectHost: any; - deadHost: any; - apiToken: any; - auditEvent: any; - $connect(): Promise; - $disconnect(): Promise; - $executeRaw(query: any, ...values: any[]): Promise; - $queryRaw(query: any, ...values: any[]): Promise; - $transaction(fn: any): Promise; -} - -export namespace Prisma { - export const ModelName: { - User: 'User'; - Session: 'Session'; - OAuthState: 'OAuthState'; - Setting: 'Setting'; - AccessList: 'AccessList'; - AccessListEntry: 'AccessListEntry'; - Certificate: 'Certificate'; - ProxyHost: 'ProxyHost'; - RedirectHost: 'RedirectHost'; - DeadHost: 'DeadHost'; - ApiToken: 'ApiToken'; - AuditEvent: 'AuditEvent'; - }; -} -`; - -const defaultJsContent = indexContent; -const defaultDtsContent = indexDtsContent; - -// Write files -fs.writeFileSync(path.join(clientDir, 'index.js'), indexContent); -fs.writeFileSync(path.join(clientDir, 'index.d.ts'), indexDtsContent); -fs.writeFileSync(path.join(clientDir, 'default.js'), defaultJsContent); -fs.writeFileSync(path.join(clientDir, 'default.d.ts'), defaultDtsContent); -fs.writeFileSync(path.join(clientDir, 'edge.js'), defaultJsContent); -fs.writeFileSync(path.join(clientDir, 'edge.d.ts'), defaultDtsContent); -fs.writeFileSync(path.join(clientDir, 'wasm.js'), defaultJsContent); -fs.writeFileSync(path.join(clientDir, 'wasm.d.ts'), defaultDtsContent); -fs.writeFileSync(path.join(clientDir, 'index-browser.js'), defaultJsContent); - -console.log('✓ Generated Prisma Client stub for build'); -console.log('⚠️ Note: Actual Prisma engines must be available at runtime');