@igstack/app-catalog-backend-core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +239 -1235
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +441 -2367
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
- package/prisma.config.ts +13 -0
- package/src/index.ts +0 -30
- package/src/middleware/featureRegistry.ts +0 -38
- package/src/server/controller.ts +0 -16
- package/src/modules/appCatalogAdmin/appCatalogAdminRouter.ts +0 -187
- package/src/modules/appCatalogAdmin/catalogBackupController.ts +0 -213
- package/src/modules/approvalMethod/approvalMethodRouter.ts +0 -169
- package/src/modules/approvalMethod/slugUtils.ts +0 -17
- package/src/modules/approvalMethod/syncApprovalMethods.ts +0 -38
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
import { Prisma } from '../../db/prisma'
|
|
3
|
-
import { getDbClient } from '../../db'
|
|
4
|
-
import { adminProcedure, publicProcedure, router } from '../../server/trpcSetup'
|
|
5
|
-
import type {
|
|
6
|
-
ApprovalMethod,
|
|
7
|
-
ApprovalMethodConfig,
|
|
8
|
-
CustomConfig,
|
|
9
|
-
PersonTeamConfig,
|
|
10
|
-
ServiceConfig,
|
|
11
|
-
} from '../../types'
|
|
12
|
-
import { generateSlugFromDisplayName } from './slugUtils'
|
|
13
|
-
|
|
14
|
-
// Zod schemas
|
|
15
|
-
const ReachOutContactSchema = z.object({
|
|
16
|
-
displayName: z.string(),
|
|
17
|
-
contact: z.string(),
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
const ServiceConfigSchema = z.object({
|
|
21
|
-
url: z.url().optional(),
|
|
22
|
-
icon: z.string().optional(),
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const PersonTeamConfigSchema = z.object({
|
|
26
|
-
reachOutContacts: z.array(ReachOutContactSchema).optional(),
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const CustomConfigSchema = z.object({})
|
|
30
|
-
|
|
31
|
-
const ApprovalMethodConfigSchema = z.union([
|
|
32
|
-
ServiceConfigSchema,
|
|
33
|
-
PersonTeamConfigSchema,
|
|
34
|
-
CustomConfigSchema,
|
|
35
|
-
])
|
|
36
|
-
|
|
37
|
-
const CreateApprovalMethodSchema = z.object({
|
|
38
|
-
type: z.enum(['service', 'personTeam', 'custom']),
|
|
39
|
-
displayName: z.string().min(1),
|
|
40
|
-
config: ApprovalMethodConfigSchema.optional(),
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
const UpdateApprovalMethodSchema = z.object({
|
|
44
|
-
slug: z.string(),
|
|
45
|
-
type: z.enum(['service', 'personTeam', 'custom']).optional(),
|
|
46
|
-
displayName: z.string().min(1).optional(),
|
|
47
|
-
config: ApprovalMethodConfigSchema.optional(),
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Convert Prisma DbApprovalMethod to our ApprovalMethod type.
|
|
52
|
-
* This ensures tRPC infers proper types for frontend consumers.
|
|
53
|
-
*/
|
|
54
|
-
function toApprovalMethod(db: {
|
|
55
|
-
slug: string
|
|
56
|
-
type: ApprovalMethod['type']
|
|
57
|
-
displayName: string
|
|
58
|
-
config: ApprovalMethodConfig | null
|
|
59
|
-
createdAt: Date
|
|
60
|
-
updatedAt: Date
|
|
61
|
-
}): ApprovalMethod {
|
|
62
|
-
// Handle discriminated union by explicitly narrowing based on type
|
|
63
|
-
const baseFields = {
|
|
64
|
-
slug: db.slug,
|
|
65
|
-
displayName: db.displayName,
|
|
66
|
-
createdAt: db.createdAt,
|
|
67
|
-
updatedAt: db.updatedAt,
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Provide default empty config if null, as ApprovalMethod discriminated union requires config
|
|
71
|
-
const config = db.config ?? {}
|
|
72
|
-
|
|
73
|
-
switch (db.type) {
|
|
74
|
-
case 'service':
|
|
75
|
-
return { ...baseFields, type: 'service', config: config as ServiceConfig }
|
|
76
|
-
case 'personTeam':
|
|
77
|
-
return {
|
|
78
|
-
...baseFields,
|
|
79
|
-
type: 'personTeam',
|
|
80
|
-
config: config as PersonTeamConfig,
|
|
81
|
-
}
|
|
82
|
-
case 'custom':
|
|
83
|
-
return { ...baseFields, type: 'custom', config: config as CustomConfig }
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function createApprovalMethodRouter() {
|
|
88
|
-
return router({
|
|
89
|
-
// Public: list for selection in app admin
|
|
90
|
-
list: publicProcedure.query(async (): Promise<Array<ApprovalMethod>> => {
|
|
91
|
-
const prisma = getDbClient()
|
|
92
|
-
const results = await prisma.dbApprovalMethod.findMany({
|
|
93
|
-
orderBy: { displayName: 'asc' },
|
|
94
|
-
})
|
|
95
|
-
return results.map(toApprovalMethod)
|
|
96
|
-
}),
|
|
97
|
-
|
|
98
|
-
// Public: get by ID
|
|
99
|
-
getById: publicProcedure
|
|
100
|
-
.input(z.object({ slug: z.string() }))
|
|
101
|
-
.query(async ({ input }): Promise<ApprovalMethod | null> => {
|
|
102
|
-
const prisma = getDbClient()
|
|
103
|
-
const result = await prisma.dbApprovalMethod.findUnique({
|
|
104
|
-
where: { slug: input.slug },
|
|
105
|
-
})
|
|
106
|
-
return result ? toApprovalMethod(result) : null
|
|
107
|
-
}),
|
|
108
|
-
|
|
109
|
-
// Admin: create
|
|
110
|
-
create: adminProcedure
|
|
111
|
-
.input(CreateApprovalMethodSchema)
|
|
112
|
-
.mutation(async ({ input }): Promise<ApprovalMethod> => {
|
|
113
|
-
const prisma = getDbClient()
|
|
114
|
-
const result = await prisma.dbApprovalMethod.create({
|
|
115
|
-
data: {
|
|
116
|
-
slug: generateSlugFromDisplayName(input.displayName),
|
|
117
|
-
type: input.type,
|
|
118
|
-
displayName: input.displayName,
|
|
119
|
-
config: input.config ?? Prisma.JsonNull,
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
return toApprovalMethod(result)
|
|
123
|
-
}),
|
|
124
|
-
|
|
125
|
-
// Admin: update
|
|
126
|
-
update: adminProcedure
|
|
127
|
-
.input(UpdateApprovalMethodSchema)
|
|
128
|
-
.mutation(async ({ input }): Promise<ApprovalMethod> => {
|
|
129
|
-
const prisma = getDbClient()
|
|
130
|
-
const { slug, ...updateData } = input
|
|
131
|
-
const result = await prisma.dbApprovalMethod.update({
|
|
132
|
-
where: { slug },
|
|
133
|
-
data: {
|
|
134
|
-
...(updateData.type !== undefined && { type: updateData.type }),
|
|
135
|
-
...(updateData.displayName !== undefined && {
|
|
136
|
-
displayName: updateData.displayName,
|
|
137
|
-
}),
|
|
138
|
-
...(updateData.config !== undefined && {
|
|
139
|
-
config: updateData.config ?? Prisma.JsonNull,
|
|
140
|
-
}),
|
|
141
|
-
},
|
|
142
|
-
})
|
|
143
|
-
return toApprovalMethod(result)
|
|
144
|
-
}),
|
|
145
|
-
|
|
146
|
-
// Admin: delete
|
|
147
|
-
delete: adminProcedure
|
|
148
|
-
.input(z.object({ slug: z.string() }))
|
|
149
|
-
.mutation(async ({ input }): Promise<ApprovalMethod> => {
|
|
150
|
-
const prisma = getDbClient()
|
|
151
|
-
const result = await prisma.dbApprovalMethod.delete({
|
|
152
|
-
where: { slug: input.slug },
|
|
153
|
-
})
|
|
154
|
-
return toApprovalMethod(result)
|
|
155
|
-
}),
|
|
156
|
-
|
|
157
|
-
// Admin: search by type
|
|
158
|
-
listByType: publicProcedure
|
|
159
|
-
.input(z.object({ type: z.enum(['service', 'personTeam', 'custom']) }))
|
|
160
|
-
.query(async ({ input }): Promise<Array<ApprovalMethod>> => {
|
|
161
|
-
const prisma = getDbClient()
|
|
162
|
-
const results = await prisma.dbApprovalMethod.findMany({
|
|
163
|
-
where: { type: input.type },
|
|
164
|
-
orderBy: { displayName: 'asc' },
|
|
165
|
-
})
|
|
166
|
-
return results.map(toApprovalMethod)
|
|
167
|
-
}),
|
|
168
|
-
})
|
|
169
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates a URL-friendly slug from a display name.
|
|
3
|
-
* Converts to lowercase and replaces non-alphanumeric characters with hyphens.
|
|
4
|
-
*
|
|
5
|
-
* @param displayName - The display name to convert
|
|
6
|
-
* @returns A slug suitable for use as a primary key
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* generateSlugFromDisplayName("My Service") // "my-service"
|
|
10
|
-
* generateSlugFromDisplayName("John's Team") // "john-s-team"
|
|
11
|
-
*/
|
|
12
|
-
export function generateSlugFromDisplayName(displayName: string): string {
|
|
13
|
-
return displayName
|
|
14
|
-
.toLowerCase()
|
|
15
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
16
|
-
.replace(/^-+|-+$/g, '')
|
|
17
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { PrismaClient as CorePrismaClient } from '../../db/prisma'
|
|
2
|
-
|
|
3
|
-
export interface ApprovalMethodSyncInput {
|
|
4
|
-
slug: string
|
|
5
|
-
type: 'service' | 'personTeam' | 'custom'
|
|
6
|
-
displayName: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Syncs approval methods to the database using upsert logic based on type + displayName.
|
|
11
|
-
*
|
|
12
|
-
* @param prisma - The PrismaClient instance from the backend-core database
|
|
13
|
-
* @param methods - Array of approval methods to sync
|
|
14
|
-
*/
|
|
15
|
-
export async function syncApprovalMethods(
|
|
16
|
-
prisma: CorePrismaClient,
|
|
17
|
-
methods: Array<ApprovalMethodSyncInput>,
|
|
18
|
-
): Promise<void> {
|
|
19
|
-
// Use transaction for atomicity
|
|
20
|
-
await prisma.$transaction(
|
|
21
|
-
methods.map((method) =>
|
|
22
|
-
prisma.dbApprovalMethod.upsert({
|
|
23
|
-
where: {
|
|
24
|
-
slug: method.slug,
|
|
25
|
-
},
|
|
26
|
-
update: {
|
|
27
|
-
displayName: method.displayName,
|
|
28
|
-
type: method.type,
|
|
29
|
-
},
|
|
30
|
-
create: {
|
|
31
|
-
slug: method.slug,
|
|
32
|
-
type: method.type,
|
|
33
|
-
displayName: method.displayName,
|
|
34
|
-
},
|
|
35
|
-
}),
|
|
36
|
-
),
|
|
37
|
-
)
|
|
38
|
-
}
|