feat(api): 建立 assets 的 Server Actions 防腐层与 Zod 校验
This commit is contained in:
parent
c35e2f54b5
commit
7bc234b9f6
8
package-lock.json
generated
8
package-lock.json
generated
@ -18,6 +18,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/big.js": "^6.2.2",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
@ -2151,6 +2152,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/big.js": {
|
||||||
|
"version": "6.2.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/big.js/-/big.js-6.2.2.tgz",
|
||||||
|
"integrity": "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name": "temp-next",
|
"name": "temp-next",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
@ -22,6 +22,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/big.js": "^6.2.2",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
|||||||
37
src/actions/asset.ts
Normal file
37
src/actions/asset.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
'use server';
|
||||||
|
|
||||||
|
import { db } from '@/db';
|
||||||
|
import { assets, assetTypeEnum } from '@/db/schema';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
const createAssetSchema = z.object({
|
||||||
|
symbol: z.string().min(1, 'Symbol is required'),
|
||||||
|
type: z.enum(['STOCK', 'CRYPTO', 'CASH']),
|
||||||
|
baseCurrency: z.string().min(2).max(10),
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function createAsset(params: z.infer<typeof createAssetSchema>) {
|
||||||
|
const validation = createAssetSchema.safeParse(params);
|
||||||
|
if (!validation.success) {
|
||||||
|
return { success: false, error: validation.error.issues[0].message };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [asset] = await db.insert(assets).values(params).returning();
|
||||||
|
return { success: true, data: asset };
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (
|
||||||
|
error &&
|
||||||
|
typeof error === 'object' &&
|
||||||
|
'code' in error &&
|
||||||
|
(error as { code: string }).code === '23505'
|
||||||
|
) {
|
||||||
|
return { success: false, error: 'Asset with this symbol already exists' };
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAssets() {
|
||||||
|
return db.select().from(assets);
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user