feat: 后端初始化2
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
# Pooled Neon connection string for Netlify Functions runtime.
|
||||
DATABASE_URL="postgresql://USER:PASSWORD@HOST-pooler.REGION.aws.neon.tech/DB?sslmode=require"
|
||||
|
||||
# Direct Neon connection string for Prisma CLI commands such as migrate.
|
||||
DIRECT_URL="postgresql://USER:PASSWORD@HOST.REGION.aws.neon.tech/DB?sslmode=require"
|
||||
# MySQL connection string for Netlify Functions runtime and Prisma CLI.
|
||||
DATABASE_URL="mysql://supper:Supper%40123456@localhost:10086/supplier_db"
|
||||
|
||||
# Optional app settings.
|
||||
JWT_SECRET="replace-me"
|
||||
UPLOAD_TOKEN="replace-me"
|
||||
|
||||
# Main points mall bridge API, for example http://localhost/open.
|
||||
POINTS_MALL_OPEN_API_BASE="http://localhost/open"
|
||||
|
||||
@@ -25,10 +25,12 @@ prisma/
|
||||
|
||||
Copy `.env.example` to `.env` and set:
|
||||
|
||||
- `DATABASE_URL`: pooled Neon connection string for Netlify Functions runtime
|
||||
- `DIRECT_URL`: direct Neon connection string for Prisma CLI and migrations
|
||||
- `DATABASE_URL`: Neon Postgres connection string for Netlify Functions runtime and Prisma CLI
|
||||
- `JWT_SECRET`: auth signing secret
|
||||
- `UPLOAD_TOKEN`: upload guard token
|
||||
- `POINTS_MALL_OPEN_API_BASE`: main platform bridge base URL, for example `http://localhost/open`
|
||||
|
||||
Supplier H5 uses `VUE_APP_SUPPLIER_IDENTIFICATION` to request supplier config from this service. The supplier `clientSecret` stays in the database and is only used by the Netlify Function when requesting the platform bridge token.
|
||||
|
||||
## Scripts
|
||||
|
||||
@@ -55,3 +57,5 @@ Current placeholders:
|
||||
- `order-pay`
|
||||
- `user-info`
|
||||
- `upload`
|
||||
- `supplier-info`
|
||||
- `supplier-token`
|
||||
|
||||
Generated
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"version": "5",
|
||||
"remote": {
|
||||
"https://edge.netlify.com/": "fd941d61d88673d5f28aab283fb86fcc50f08a3bc80ee5470498fcfa88c65cfb",
|
||||
"https://edge.netlify.com/bootstrap/config.ts": "6a2ce0e544e15e8f8883a5c18da5948e37fd0f2619f68cb31f3af53c51817025",
|
||||
"https://edge.netlify.com/bootstrap/context.ts": "e97240232121e2f369f6546ce961490f34d961ea1ea54be3ff09633e3f08373f",
|
||||
"https://edge.netlify.com/bootstrap/cookie.ts": "8b0baae708989ca183c6f3b4ab3d029e6abcbc2e43f93edeb0ff447b3bbc3a05",
|
||||
"https://edge.netlify.com/bootstrap/edge_function.ts": "b8253e86aa83c67341f5cfedeba5049d77fbf84dcab7eceff7566b7728ae9b39",
|
||||
"https://edge.netlify.com/bootstrap/globals/types.ts": "eaa6148ded3121d8dee62dd91c86e7fe76601df0f3ca8d7962243a30f4c8935f"
|
||||
},
|
||||
"workspace": {
|
||||
"packageJson": {
|
||||
"dependencies": [
|
||||
"npm:@neondatabase/serverless@^1.0.1",
|
||||
"npm:@netlify/functions@^4.2.5",
|
||||
"npm:@prisma/adapter-neon@^6.16.0",
|
||||
"npm:@prisma/client@^6.16.0",
|
||||
"npm:@types/crypto-js@^4.2.2",
|
||||
"npm:@types/node@^24.10.1",
|
||||
"npm:@types/ws@^8.18.1",
|
||||
"npm:crypto-js@^4.2.0",
|
||||
"npm:dotenv@^17.2.3",
|
||||
"npm:netlify-cli@^23.13.3",
|
||||
"npm:prisma@^6.19.3",
|
||||
"npm:typescript@^5.9.3",
|
||||
"npm:ws@^8.18.3"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'cart-add endpoint placeholder' })
|
||||
return ok({ message: '加入购物车接口待实现' })
|
||||
})
|
||||
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'login endpoint placeholder' })
|
||||
return ok({ message: '登录接口待实现' })
|
||||
})
|
||||
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'order-create endpoint placeholder' })
|
||||
return ok({ message: '创建订单接口待实现' })
|
||||
})
|
||||
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'order-pay endpoint placeholder' })
|
||||
return ok({ message: '订单支付接口待实现' })
|
||||
})
|
||||
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['GET'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'product-detail endpoint placeholder' })
|
||||
return ok({ message: '商品详情接口待实现' })
|
||||
})
|
||||
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['GET'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'product-list endpoint placeholder' })
|
||||
return ok({ message: '商品列表接口待实现' })
|
||||
})
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { Context } from '@netlify/functions'
|
||||
import { guardMethod } from '../utils/method.js'
|
||||
import { fail, ok } from '../utils/http.js'
|
||||
import { readJson } from '../utils/request.js'
|
||||
import { prisma } from '../utils/prisma.js'
|
||||
import { withErrorBoundary } from '../utils/handler.js'
|
||||
|
||||
type SupplierInfoRequest = {
|
||||
supplierIdentification?: string
|
||||
}
|
||||
|
||||
export default withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
const body = await readJson<SupplierInfoRequest>(request)
|
||||
const supplierIdentification = String(body.supplierIdentification || '').trim().toLowerCase()
|
||||
|
||||
if (!supplierIdentification) {
|
||||
return fail('供应商唯一标识不能为空')
|
||||
}
|
||||
|
||||
const supplier = await prisma.supplierInfo.findUnique({
|
||||
where: { supplierIdentification }
|
||||
})
|
||||
|
||||
if (!supplier || supplier.deleted === 1) {
|
||||
return fail('供应商信息未配置或已停用', 404, 'SUPPLIER_NOT_CONFIGURED')
|
||||
}
|
||||
|
||||
return ok({
|
||||
id: supplier.id,
|
||||
supplierIdentification: supplier.supplierIdentification,
|
||||
supplierId: supplier.supplierId,
|
||||
supplierName: supplier.supplierName,
|
||||
clientId: supplier.clientId
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,86 @@
|
||||
import type { Context } from '@netlify/functions'
|
||||
import { guardMethod } from '../utils/method.js'
|
||||
import { fail, ok } from '../utils/http.js'
|
||||
import { readJson } from '../utils/request.js'
|
||||
import { prisma } from '../utils/prisma.js'
|
||||
import { createBridgeSignature } from '../utils/crypto.js'
|
||||
import { withErrorBoundary } from '../utils/handler.js'
|
||||
|
||||
type SupplierTokenRequest = {
|
||||
userId?: string
|
||||
supplierIdentification?: string
|
||||
}
|
||||
|
||||
type BridgeTokenResponse = {
|
||||
resultCode?: number
|
||||
message?: string
|
||||
accessToken?: string
|
||||
refreshToken?: string
|
||||
expire?: number
|
||||
refreshExpire?: number
|
||||
time?: string
|
||||
}
|
||||
|
||||
const normalizeBase = (base: string) => base.replace(/\/$/, '')
|
||||
|
||||
export default withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
const body = await readJson<SupplierTokenRequest>(request)
|
||||
const userId = String(body.userId || '').trim()
|
||||
const supplierIdentification = String(body.supplierIdentification || '').trim().toLowerCase()
|
||||
|
||||
if (!userId || !supplierIdentification) {
|
||||
return fail('用户信息和供应商唯一标识不能为空')
|
||||
}
|
||||
|
||||
const supplier = await prisma.supplierInfo.findUnique({
|
||||
where: { supplierIdentification }
|
||||
})
|
||||
|
||||
if (!supplier || supplier.deleted === 1) {
|
||||
return fail('供应商信息未配置或已停用', 404, 'SUPPLIER_NOT_CONFIGURED')
|
||||
}
|
||||
|
||||
const timestamp = String(Date.now())
|
||||
const signature = createBridgeSignature(supplier.clientId, supplier.clientSecret, timestamp)
|
||||
const apiBase = normalizeBase(process.env.POINTS_MALL_OPEN_API_BASE || '')
|
||||
|
||||
if (!apiBase) {
|
||||
return fail('平台积分商城接口地址未配置', 500, 'OPEN_API_BASE_MISSING')
|
||||
}
|
||||
|
||||
const response = await fetch(`${apiBase}/connect/token`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
supplierId: supplier.supplierId,
|
||||
clientId: supplier.clientId,
|
||||
clientSecret: signature,
|
||||
code: '',
|
||||
timestamp
|
||||
})
|
||||
})
|
||||
|
||||
const tokenPayload = (await response.json().catch(() => ({}))) as BridgeTokenResponse
|
||||
|
||||
if (!response.ok || tokenPayload.resultCode !== 0) {
|
||||
return fail(tokenPayload.message || '获取平台授权令牌失败', 502, 'BRIDGE_TOKEN_FAILED')
|
||||
}
|
||||
|
||||
return ok({
|
||||
supplierIdentification,
|
||||
supplierId: supplier.supplierId,
|
||||
supplierName: supplier.supplierName,
|
||||
userId,
|
||||
token: tokenPayload.accessToken,
|
||||
accessToken: tokenPayload.accessToken,
|
||||
refreshToken: tokenPayload.refreshToken,
|
||||
expiresIn: tokenPayload.expire,
|
||||
refreshExpiresIn: tokenPayload.refreshExpire,
|
||||
issuedAt: tokenPayload.time
|
||||
})
|
||||
})
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'upload endpoint placeholder' })
|
||||
return ok({ message: '上传接口待实现' })
|
||||
})
|
||||
|
||||
@@ -7,5 +7,5 @@ export default withErrorBoundary(async (request: Request, _context: Context) =>
|
||||
const methodResponse = guardMethod(request, ['GET'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return ok({ message: 'user-info endpoint placeholder' })
|
||||
return ok({ message: '用户信息接口待实现' })
|
||||
})
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
export const sha256 = (value: string) => {
|
||||
return CryptoJS.SHA256(value).toString(CryptoJS.enc.Hex)
|
||||
}
|
||||
|
||||
export const createBridgeSignature = (clientId: string, clientSecret: string, timestamp: string) => {
|
||||
return sha256(`${clientId}${clientSecret}${timestamp}${clientSecret}`)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ export const withErrorBoundary = (handler: FunctionHandler): FunctionHandler =>
|
||||
return await handler(request, context)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return fail('Internal server error', 500, 'INTERNAL_SERVER_ERROR')
|
||||
return fail('服务异常,请稍后再试', 500, 'INTERNAL_SERVER_ERROR')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
export type JsonBody = Record<string, unknown> | unknown[]
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS'
|
||||
}
|
||||
|
||||
export const json = (body: JsonBody, init: ResponseInit = {}) =>
|
||||
Response.json(body, {
|
||||
...init,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...corsHeaders,
|
||||
...(init.headers || {})
|
||||
}
|
||||
})
|
||||
@@ -16,10 +23,11 @@ export const fail = (message: string, status = 400, code = 'BAD_REQUEST') =>
|
||||
|
||||
export const methodNotAllowed = (allowedMethods: string[]) =>
|
||||
json(
|
||||
{ success: false, error: { code: 'METHOD_NOT_ALLOWED', message: 'Method not allowed' } },
|
||||
{ success: false, error: { code: 'METHOD_NOT_ALLOWED', message: '请求方式不支持' } },
|
||||
{
|
||||
status: 405,
|
||||
headers: {
|
||||
...corsHeaders,
|
||||
Allow: allowedMethods.join(', ')
|
||||
}
|
||||
}
|
||||
@@ -28,9 +36,5 @@ export const methodNotAllowed = (allowedMethods: string[]) =>
|
||||
export const handleOptions = () =>
|
||||
new Response(null, {
|
||||
status: 204,
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS'
|
||||
}
|
||||
headers: corsHeaders
|
||||
})
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
import { neonConfig } from '@neondatabase/serverless'
|
||||
import { PrismaNeon } from '@prisma/adapter-neon'
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import ws from 'ws'
|
||||
|
||||
neonConfig.webSocketConstructor = ws
|
||||
|
||||
const connectionString = process.env.DATABASE_URL
|
||||
|
||||
if (!connectionString) {
|
||||
throw new Error('DATABASE_URL is required')
|
||||
throw new Error('缺少数据库连接配置 DATABASE_URL')
|
||||
}
|
||||
|
||||
const globalForPrisma = globalThis as typeof globalThis & {
|
||||
prisma?: PrismaClient
|
||||
}
|
||||
|
||||
const adapter = new PrismaNeon({ connectionString })
|
||||
|
||||
export const prisma = globalForPrisma.prisma || new PrismaClient({ adapter })
|
||||
export const prisma = globalForPrisma.prisma || new PrismaClient()
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
globalForPrisma.prisma = prisma
|
||||
|
||||
Generated
+334
-1
@@ -12,14 +12,16 @@
|
||||
"@netlify/functions": "^4.2.5",
|
||||
"@prisma/adapter-neon": "^6.16.0",
|
||||
"@prisma/client": "^6.16.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/ws": "^8.18.1",
|
||||
"netlify-cli": "^23.13.3",
|
||||
"prisma": "^6.16.0",
|
||||
"prisma": "^6.19.3",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
},
|
||||
@@ -967,6 +969,13 @@
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/crypto-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
|
||||
"integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
|
||||
@@ -2116,6 +2125,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/crypto-js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||
@@ -9260,6 +9275,270 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz",
|
||||
"integrity": "sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.2.tgz",
|
||||
"integrity": "sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.2.tgz",
|
||||
"integrity": "sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.2.tgz",
|
||||
"integrity": "sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.2.tgz",
|
||||
"integrity": "sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.2.tgz",
|
||||
"integrity": "sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.2.tgz",
|
||||
"integrity": "sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.2.tgz",
|
||||
"integrity": "sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.2.tgz",
|
||||
"integrity": "sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.2.tgz",
|
||||
"integrity": "sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.2.tgz",
|
||||
"integrity": "sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.2.tgz",
|
||||
"integrity": "sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.2.tgz",
|
||||
"integrity": "sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.2.tgz",
|
||||
"integrity": "sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.2.tgz",
|
||||
"integrity": "sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.2.tgz",
|
||||
"integrity": "sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"extraneous": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/@sec-ant/readable-stream": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
|
||||
@@ -13324,6 +13603,19 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"extraneous": true,
|
||||
"hasInstallScript": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@@ -17381,6 +17673,47 @@
|
||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/rollup": {
|
||||
"version": "4.52.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz",
|
||||
"integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==",
|
||||
"extraneous": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.52.2",
|
||||
"@rollup/rollup-android-arm64": "4.52.2",
|
||||
"@rollup/rollup-darwin-arm64": "4.52.2",
|
||||
"@rollup/rollup-darwin-x64": "4.52.2",
|
||||
"@rollup/rollup-freebsd-arm64": "4.52.2",
|
||||
"@rollup/rollup-freebsd-x64": "4.52.2",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.52.2",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.52.2",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.52.2",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.52.2",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.52.2",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.52.2",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.52.2",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.52.2",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.52.2",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.52.2",
|
||||
"@rollup/rollup-linux-x64-musl": "4.52.2",
|
||||
"@rollup/rollup-openharmony-arm64": "4.52.2",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.52.2",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.52.2",
|
||||
"@rollup/rollup-win32-x64-gnu": "4.52.2",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.52.2",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/netlify-cli/node_modules/router": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
"@netlify/functions": "^4.2.5",
|
||||
"@prisma/adapter-neon": "^6.16.0",
|
||||
"@prisma/client": "^6.16.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/ws": "^8.18.1",
|
||||
"netlify-cli": "^23.13.3",
|
||||
"prisma": "^6.16.0",
|
||||
"prisma": "^6.19.3",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ import { defineConfig, env } from 'prisma/config'
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
datasource: {
|
||||
url: env('DIRECT_URL')
|
||||
url: env('DATABASE_URL')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -3,7 +3,8 @@ generator client {
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
provider = "mysql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
@@ -37,6 +38,23 @@ model Product {
|
||||
orderItems OrderItem[]
|
||||
}
|
||||
|
||||
model SupplierInfo {
|
||||
id Int @id @default(autoincrement())
|
||||
supplierIdentification String @unique
|
||||
supplierId String @unique
|
||||
supplierName String
|
||||
clientId String
|
||||
clientSecret String
|
||||
createTime DateTime @default(now())
|
||||
updateTime DateTime @updatedAt
|
||||
creator String?
|
||||
updator String?
|
||||
version Int @default(0)
|
||||
deleted Int @default(0)
|
||||
|
||||
@@map("supplier_info")
|
||||
}
|
||||
|
||||
model CartItem {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
|
||||
Reference in New Issue
Block a user