fix(ST-507): split server-only code helpers into lib/code-server to keep client bundle clean
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b71eb53fa8
commit
f994219957
4 changed files with 41 additions and 37 deletions
|
|
@ -7,7 +7,8 @@ import { z } from 'zod'
|
|||
import { prisma } from '@/lib/prisma'
|
||||
import { SessionData, sessionOptions } from '@/lib/session'
|
||||
import { getAccessibleProduct } from '@/lib/product-access'
|
||||
import { generateNextPbiCode, isValidCode, MAX_CODE_LENGTH, normalizeCode } from '@/lib/code'
|
||||
import { isValidCode, MAX_CODE_LENGTH, normalizeCode } from '@/lib/code'
|
||||
import { generateNextPbiCode } from '@/lib/code-server'
|
||||
|
||||
async function getSession() {
|
||||
return getIronSession<SessionData>(await cookies(), sessionOptions)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import { prisma } from '@/lib/prisma'
|
|||
import { SessionData, sessionOptions } from '@/lib/session'
|
||||
import { getAccessibleProduct, productAccessFilter } from '@/lib/product-access'
|
||||
import { requireProductWriter } from '@/lib/auth'
|
||||
import { generateNextStoryCode, isValidCode, MAX_CODE_LENGTH, normalizeCode } from '@/lib/code'
|
||||
import { isValidCode, MAX_CODE_LENGTH, normalizeCode } from '@/lib/code'
|
||||
import { generateNextStoryCode } from '@/lib/code-server'
|
||||
|
||||
async function getSession() {
|
||||
return getIronSession<SessionData>(await cookies(), sessionOptions)
|
||||
|
|
|
|||
35
lib/code-server.ts
Normal file
35
lib/code-server.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
const STORY_AUTO_RE = /^ST-(\d+)$/
|
||||
const PBI_AUTO_RE = /^PBI-(\d+)$/
|
||||
|
||||
function nextSequential(existing: (string | null)[], pattern: RegExp): number {
|
||||
let max = 0
|
||||
for (const c of existing) {
|
||||
if (!c) continue
|
||||
const m = c.match(pattern)
|
||||
if (m) {
|
||||
const n = Number.parseInt(m[1], 10)
|
||||
if (!Number.isNaN(n) && n > max) max = n
|
||||
}
|
||||
}
|
||||
return max + 1
|
||||
}
|
||||
|
||||
export async function generateNextStoryCode(productId: string): Promise<string> {
|
||||
const stories = await prisma.story.findMany({
|
||||
where: { product_id: productId },
|
||||
select: { code: true },
|
||||
})
|
||||
const next = nextSequential(stories.map((s) => s.code), STORY_AUTO_RE)
|
||||
return `ST-${String(next).padStart(3, '0')}`
|
||||
}
|
||||
|
||||
export async function generateNextPbiCode(productId: string): Promise<string> {
|
||||
const pbis = await prisma.pbi.findMany({
|
||||
where: { product_id: productId },
|
||||
select: { code: true },
|
||||
})
|
||||
const next = nextSequential(pbis.map((p) => p.code), PBI_AUTO_RE)
|
||||
return `PBI-${next}`
|
||||
}
|
||||
37
lib/code.ts
37
lib/code.ts
|
|
@ -1,7 +1,5 @@
|
|||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
const STORY_AUTO_RE = /^ST-(\d+)$/
|
||||
const PBI_AUTO_RE = /^PBI-(\d+)$/
|
||||
// Pure helpers — safe to import from client components.
|
||||
// DB-backed helpers (generateNextStoryCode/PbiCode) live in lib/code-server.ts.
|
||||
|
||||
const VALID_CODE_RE = /^[A-Za-z0-9._-]+$/
|
||||
|
||||
|
|
@ -17,37 +15,6 @@ export function normalizeCode(input: string | null | undefined): string | null {
|
|||
return trimmed === '' ? null : trimmed
|
||||
}
|
||||
|
||||
function nextSequential(existing: (string | null)[], pattern: RegExp): number {
|
||||
let max = 0
|
||||
for (const c of existing) {
|
||||
if (!c) continue
|
||||
const m = c.match(pattern)
|
||||
if (m) {
|
||||
const n = Number.parseInt(m[1], 10)
|
||||
if (!Number.isNaN(n) && n > max) max = n
|
||||
}
|
||||
}
|
||||
return max + 1
|
||||
}
|
||||
|
||||
export async function generateNextStoryCode(productId: string): Promise<string> {
|
||||
const stories = await prisma.story.findMany({
|
||||
where: { product_id: productId },
|
||||
select: { code: true },
|
||||
})
|
||||
const next = nextSequential(stories.map((s) => s.code), STORY_AUTO_RE)
|
||||
return `ST-${String(next).padStart(3, '0')}`
|
||||
}
|
||||
|
||||
export async function generateNextPbiCode(productId: string): Promise<string> {
|
||||
const pbis = await prisma.pbi.findMany({
|
||||
where: { product_id: productId },
|
||||
select: { code: true },
|
||||
})
|
||||
const next = nextSequential(pbis.map((p) => p.code), PBI_AUTO_RE)
|
||||
return `PBI-${next}`
|
||||
}
|
||||
|
||||
export function deriveTaskCode(storyCode: string | null, indexOneBased: number): string | null {
|
||||
if (!storyCode) return null
|
||||
return `${storyCode}.${indexOneBased}`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue