@payloadcms/plugin-mcp 0.0.1-alpha.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/LICENSE.md +22 -0
- package/README.md +7 -0
- package/dist/collections/createApiKeysCollection.d.ts +7 -0
- package/dist/collections/createApiKeysCollection.d.ts.map +1 -0
- package/dist/collections/createApiKeysCollection.js +315 -0
- package/dist/collections/createApiKeysCollection.js.map +1 -0
- package/dist/endpoints/mcp.d.ts +4 -0
- package/dist/endpoints/mcp.d.ts.map +1 -0
- package/dist/endpoints/mcp.js +44 -0
- package/dist/endpoints/mcp.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/createRequest.d.ts +3 -0
- package/dist/mcp/createRequest.d.ts.map +1 -0
- package/dist/mcp/createRequest.js +14 -0
- package/dist/mcp/createRequest.js.map +1 -0
- package/dist/mcp/getMcpHandler.d.ts +4 -0
- package/dist/mcp/getMcpHandler.d.ts.map +1 -0
- package/dist/mcp/getMcpHandler.js +179 -0
- package/dist/mcp/getMcpHandler.js.map +1 -0
- package/dist/mcp/helpers/config.d.ts +30 -0
- package/dist/mcp/helpers/config.d.ts.map +1 -0
- package/dist/mcp/helpers/config.js +217 -0
- package/dist/mcp/helpers/config.js.map +1 -0
- package/dist/mcp/helpers/conversion.d.ts +2 -0
- package/dist/mcp/helpers/conversion.d.ts.map +1 -0
- package/dist/mcp/helpers/conversion.js +5 -0
- package/dist/mcp/helpers/conversion.js.map +1 -0
- package/dist/mcp/helpers/fields.d.ts +38 -0
- package/dist/mcp/helpers/fields.d.ts.map +1 -0
- package/dist/mcp/helpers/fields.js +96 -0
- package/dist/mcp/helpers/fields.js.map +1 -0
- package/dist/mcp/helpers/fileValidation.d.ts +69 -0
- package/dist/mcp/helpers/fileValidation.d.ts.map +1 -0
- package/dist/mcp/helpers/fileValidation.js +305 -0
- package/dist/mcp/helpers/fileValidation.js.map +1 -0
- package/dist/mcp/helpers/validation.d.ts +9 -0
- package/dist/mcp/helpers/validation.d.ts.map +1 -0
- package/dist/mcp/helpers/validation.js +22 -0
- package/dist/mcp/helpers/validation.js.map +1 -0
- package/dist/mcp/registerTool.d.ts +6 -0
- package/dist/mcp/registerTool.d.ts.map +1 -0
- package/dist/mcp/registerTool.js +18 -0
- package/dist/mcp/registerTool.js.map +1 -0
- package/dist/mcp/tools/auth/auth.d.ts +4 -0
- package/dist/mcp/tools/auth/auth.d.ts.map +1 -0
- package/dist/mcp/tools/auth/auth.js +54 -0
- package/dist/mcp/tools/auth/auth.js.map +1 -0
- package/dist/mcp/tools/auth/forgotPassword.d.ts +4 -0
- package/dist/mcp/tools/auth/forgotPassword.d.ts.map +1 -0
- package/dist/mcp/tools/auth/forgotPassword.js +45 -0
- package/dist/mcp/tools/auth/forgotPassword.js.map +1 -0
- package/dist/mcp/tools/auth/login.d.ts +4 -0
- package/dist/mcp/tools/auth/login.d.ts.map +1 -0
- package/dist/mcp/tools/auth/login.js +48 -0
- package/dist/mcp/tools/auth/login.js.map +1 -0
- package/dist/mcp/tools/auth/resetPassword.d.ts +4 -0
- package/dist/mcp/tools/auth/resetPassword.d.ts.map +1 -0
- package/dist/mcp/tools/auth/resetPassword.js +46 -0
- package/dist/mcp/tools/auth/resetPassword.js.map +1 -0
- package/dist/mcp/tools/auth/unlock.d.ts +4 -0
- package/dist/mcp/tools/auth/unlock.d.ts.map +1 -0
- package/dist/mcp/tools/auth/unlock.js +45 -0
- package/dist/mcp/tools/auth/unlock.js.map +1 -0
- package/dist/mcp/tools/auth/verify.d.ts +4 -0
- package/dist/mcp/tools/auth/verify.d.ts.map +1 -0
- package/dist/mcp/tools/auth/verify.js +42 -0
- package/dist/mcp/tools/auth/verify.js.map +1 -0
- package/dist/mcp/tools/collection/create.d.ts +10 -0
- package/dist/mcp/tools/collection/create.d.ts.map +1 -0
- package/dist/mcp/tools/collection/create.js +159 -0
- package/dist/mcp/tools/collection/create.js.map +1 -0
- package/dist/mcp/tools/collection/delete.d.ts +10 -0
- package/dist/mcp/tools/collection/delete.d.ts.map +1 -0
- package/dist/mcp/tools/collection/delete.js +162 -0
- package/dist/mcp/tools/collection/delete.js.map +1 -0
- package/dist/mcp/tools/collection/find.d.ts +10 -0
- package/dist/mcp/tools/collection/find.d.ts.map +1 -0
- package/dist/mcp/tools/collection/find.js +162 -0
- package/dist/mcp/tools/collection/find.js.map +1 -0
- package/dist/mcp/tools/collection/update.d.ts +10 -0
- package/dist/mcp/tools/collection/update.d.ts.map +1 -0
- package/dist/mcp/tools/collection/update.js +206 -0
- package/dist/mcp/tools/collection/update.js.map +1 -0
- package/dist/mcp/tools/config/find.d.ts +10 -0
- package/dist/mcp/tools/config/find.d.ts.map +1 -0
- package/dist/mcp/tools/config/find.js +94 -0
- package/dist/mcp/tools/config/find.js.map +1 -0
- package/dist/mcp/tools/config/update.d.ts +10 -0
- package/dist/mcp/tools/config/update.d.ts.map +1 -0
- package/dist/mcp/tools/config/update.js +212 -0
- package/dist/mcp/tools/config/update.js.map +1 -0
- package/dist/mcp/tools/job/create.d.ts +10 -0
- package/dist/mcp/tools/job/create.d.ts.map +1 -0
- package/dist/mcp/tools/job/create.js +293 -0
- package/dist/mcp/tools/job/create.js.map +1 -0
- package/dist/mcp/tools/job/run.d.ts +10 -0
- package/dist/mcp/tools/job/run.d.ts.map +1 -0
- package/dist/mcp/tools/job/run.js +147 -0
- package/dist/mcp/tools/job/run.js.map +1 -0
- package/dist/mcp/tools/job/update.d.ts +11 -0
- package/dist/mcp/tools/job/update.d.ts.map +1 -0
- package/dist/mcp/tools/job/update.js +211 -0
- package/dist/mcp/tools/job/update.js.map +1 -0
- package/dist/mcp/tools/resource/create.d.ts +6 -0
- package/dist/mcp/tools/resource/create.d.ts.map +1 -0
- package/dist/mcp/tools/resource/create.js +75 -0
- package/dist/mcp/tools/resource/create.js.map +1 -0
- package/dist/mcp/tools/resource/delete.d.ts +5 -0
- package/dist/mcp/tools/resource/delete.d.ts.map +1 -0
- package/dist/mcp/tools/resource/delete.js +140 -0
- package/dist/mcp/tools/resource/delete.js.map +1 -0
- package/dist/mcp/tools/resource/find.d.ts +5 -0
- package/dist/mcp/tools/resource/find.d.ts.map +1 -0
- package/dist/mcp/tools/resource/find.js +119 -0
- package/dist/mcp/tools/resource/find.js.map +1 -0
- package/dist/mcp/tools/resource/update.d.ts +6 -0
- package/dist/mcp/tools/resource/update.d.ts.map +1 -0
- package/dist/mcp/tools/resource/update.js +201 -0
- package/dist/mcp/tools/resource/update.js.map +1 -0
- package/dist/mcp/tools/schemas.d.ts +374 -0
- package/dist/mcp/tools/schemas.d.ts.map +1 -0
- package/dist/mcp/tools/schemas.js +201 -0
- package/dist/mcp/tools/schemas.js.map +1 -0
- package/dist/types.d.ts +379 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/camelCase.d.ts +9 -0
- package/dist/utils/camelCase.d.ts.map +1 -0
- package/dist/utils/camelCase.js +11 -0
- package/dist/utils/camelCase.js.map +1 -0
- package/dist/utils/convertCollectionSchemaToZod.d.ts +3 -0
- package/dist/utils/convertCollectionSchemaToZod.d.ts.map +1 -0
- package/dist/utils/convertCollectionSchemaToZod.js +30 -0
- package/dist/utils/convertCollectionSchemaToZod.js.map +1 -0
- package/package.json +64 -0
- package/src/collections/createApiKeysCollection.ts +393 -0
- package/src/endpoints/mcp.ts +60 -0
- package/src/index.ts +86 -0
- package/src/mcp/createRequest.ts +13 -0
- package/src/mcp/getMcpHandler.ts +433 -0
- package/src/mcp/helpers/config.ts +326 -0
- package/src/mcp/helpers/conversion.ts +3 -0
- package/src/mcp/helpers/fields.ts +158 -0
- package/src/mcp/helpers/fileValidation.ts +417 -0
- package/src/mcp/helpers/validation.ts +32 -0
- package/src/mcp/registerTool.ts +22 -0
- package/src/mcp/tools/auth/auth.ts +69 -0
- package/src/mcp/tools/auth/forgotPassword.ts +68 -0
- package/src/mcp/tools/auth/login.ts +70 -0
- package/src/mcp/tools/auth/resetPassword.ts +59 -0
- package/src/mcp/tools/auth/unlock.ts +62 -0
- package/src/mcp/tools/auth/verify.ts +55 -0
- package/src/mcp/tools/collection/create.ts +236 -0
- package/src/mcp/tools/collection/delete.ts +227 -0
- package/src/mcp/tools/collection/find.ts +222 -0
- package/src/mcp/tools/collection/update.ts +288 -0
- package/src/mcp/tools/config/find.ts +126 -0
- package/src/mcp/tools/config/update.ts +282 -0
- package/src/mcp/tools/job/create.ts +420 -0
- package/src/mcp/tools/job/run.ts +189 -0
- package/src/mcp/tools/job/update.ts +319 -0
- package/src/mcp/tools/resource/create.ts +121 -0
- package/src/mcp/tools/resource/delete.ts +210 -0
- package/src/mcp/tools/resource/find.ts +194 -0
- package/src/mcp/tools/resource/update.ts +314 -0
- package/src/mcp/tools/schemas.ts +373 -0
- package/src/types.ts +405 -0
- package/src/utils/camelCase.ts +12 -0
- package/src/utils/convertCollectionSchemaToZod.ts +35 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AdminConfig,
|
|
3
|
+
CollectionConfigUpdates,
|
|
4
|
+
DatabaseConfig,
|
|
5
|
+
GeneralConfig,
|
|
6
|
+
PluginUpdates,
|
|
7
|
+
} from '../../types.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adds a collection to the payload.config.ts file
|
|
11
|
+
*/
|
|
12
|
+
export function addCollectionToConfig(content: string, collectionName: string): string {
|
|
13
|
+
const capitalizedName = collectionName.charAt(0).toUpperCase() + collectionName.slice(1)
|
|
14
|
+
|
|
15
|
+
// Add import statement
|
|
16
|
+
const importRegex = /import.*from\s*['"]\.\/collections\/.*['"]/g
|
|
17
|
+
const importMatches = content.match(importRegex)
|
|
18
|
+
|
|
19
|
+
if (importMatches && importMatches.length > 0) {
|
|
20
|
+
const lastImport = importMatches[importMatches.length - 1]
|
|
21
|
+
const newImport = `import { ${capitalizedName} } from './collections/${capitalizedName}'`
|
|
22
|
+
|
|
23
|
+
// Check if import already exists
|
|
24
|
+
if (lastImport && !content.includes(newImport)) {
|
|
25
|
+
content = content.replace(lastImport, `${lastImport}\n${newImport}`)
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
// Add import after existing imports
|
|
29
|
+
const importInsertPoint = content.indexOf("import sharp from 'sharp'")
|
|
30
|
+
if (importInsertPoint !== -1) {
|
|
31
|
+
const lineEnd = content.indexOf('\n', importInsertPoint)
|
|
32
|
+
const newImport = `import { ${capitalizedName} } from './collections/${capitalizedName}'`
|
|
33
|
+
content = content.slice(0, lineEnd + 1) + newImport + '\n' + content.slice(lineEnd + 1)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Add to collections array
|
|
38
|
+
const collectionsRegex = /collections:\s*\[([\s\S]*?)\]/
|
|
39
|
+
const collectionsMatch = content.match(collectionsRegex)
|
|
40
|
+
|
|
41
|
+
if (collectionsMatch && collectionsMatch[1]) {
|
|
42
|
+
const collectionsContent = collectionsMatch[1].trim()
|
|
43
|
+
if (!collectionsContent.includes(capitalizedName)) {
|
|
44
|
+
const newCollections = collectionsContent
|
|
45
|
+
? `${collectionsContent}, ${capitalizedName}`
|
|
46
|
+
: capitalizedName
|
|
47
|
+
content = content.replace(collectionsRegex, `collections: [${newCollections}]`)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return content
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Removes a collection from the payload.config.ts file
|
|
56
|
+
*/
|
|
57
|
+
export function removeCollectionFromConfig(content: string, collectionName: string): string {
|
|
58
|
+
const capitalizedName = collectionName.charAt(0).toUpperCase() + collectionName.slice(1)
|
|
59
|
+
|
|
60
|
+
// Remove import statement
|
|
61
|
+
const importRegex = new RegExp(
|
|
62
|
+
`import\\s*{\\s*${capitalizedName}\\s*}\\s*from\\s*['"]\\./collections/${capitalizedName}['"]\\s*\\n?`,
|
|
63
|
+
'g',
|
|
64
|
+
)
|
|
65
|
+
content = content.replace(importRegex, '')
|
|
66
|
+
|
|
67
|
+
// Remove from collections array
|
|
68
|
+
const collectionsRegex = /collections:\s*\[([\s\S]*?)\]/
|
|
69
|
+
const collectionsMatch = content.match(collectionsRegex)
|
|
70
|
+
|
|
71
|
+
if (collectionsMatch && collectionsMatch[1]) {
|
|
72
|
+
let collectionsContent = collectionsMatch[1]
|
|
73
|
+
|
|
74
|
+
// Remove the collection name and clean up commas
|
|
75
|
+
collectionsContent = collectionsContent.replace(
|
|
76
|
+
new RegExp(`\\s*,?\\s*${capitalizedName}\\s*,?`, 'g'),
|
|
77
|
+
'',
|
|
78
|
+
)
|
|
79
|
+
collectionsContent = collectionsContent.replace(/,\s*,/g, ',') // Remove double commas
|
|
80
|
+
collectionsContent = collectionsContent.replace(/^\s*,|,\s*$/g, '') // Remove leading/trailing commas
|
|
81
|
+
|
|
82
|
+
content = content.replace(collectionsRegex, `collections: [${collectionsContent}]`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Clean up any double newlines from removed imports
|
|
86
|
+
content = content.replace(/\n{3,}/g, '\n\n')
|
|
87
|
+
|
|
88
|
+
return content
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Updates admin configuration in payload.config.ts
|
|
93
|
+
*/
|
|
94
|
+
export function updateAdminConfig(content: string, adminConfig: AdminConfig): string {
|
|
95
|
+
const adminRegex = /admin:\s*\{([^}]*)\}/
|
|
96
|
+
const adminMatch = content.match(adminRegex)
|
|
97
|
+
|
|
98
|
+
if (adminMatch && adminMatch[1]) {
|
|
99
|
+
let adminContent = adminMatch[1]
|
|
100
|
+
|
|
101
|
+
// Update specific admin properties
|
|
102
|
+
if (adminConfig.user) {
|
|
103
|
+
if (adminContent.includes('user:')) {
|
|
104
|
+
adminContent = adminContent.replace(/user:[^,}]*/, `user: ${adminConfig.user}.slug`)
|
|
105
|
+
} else {
|
|
106
|
+
adminContent = `\n user: ${adminConfig.user}.slug,${adminContent}`
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (adminConfig.meta) {
|
|
111
|
+
const metaConfig = Object.entries(adminConfig.meta)
|
|
112
|
+
.map(([key, value]) => ` ${key}: '${value}'`)
|
|
113
|
+
.join(',\n')
|
|
114
|
+
|
|
115
|
+
if (adminContent.includes('meta:')) {
|
|
116
|
+
adminContent = adminContent.replace(/meta:\s*\{[^}]*\}/, `meta: {\n${metaConfig}\n }`)
|
|
117
|
+
} else {
|
|
118
|
+
adminContent = `${adminContent}\n meta: {\n${metaConfig}\n },`
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
content = content.replace(adminRegex, `admin: {${adminContent}\n }`)
|
|
123
|
+
} else {
|
|
124
|
+
// Add admin config if it doesn't exist
|
|
125
|
+
const adminConfigEntries = []
|
|
126
|
+
|
|
127
|
+
if (adminConfig.user) {
|
|
128
|
+
adminConfigEntries.push(` user: ${adminConfig.user}.slug`)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (adminConfig.meta) {
|
|
132
|
+
const metaConfig = Object.entries(adminConfig.meta)
|
|
133
|
+
.map(([key, value]) => ` ${key}: '${value}'`)
|
|
134
|
+
.join(',\n')
|
|
135
|
+
adminConfigEntries.push(` meta: {\n${metaConfig}\n }`)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const adminConfigString = `admin: {\n${adminConfigEntries.join(',\n')}\n },`
|
|
139
|
+
content = content.replace(
|
|
140
|
+
/export default buildConfig\(\{/,
|
|
141
|
+
`export default buildConfig({\n ${adminConfigString}`,
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return content
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Updates database configuration in payload.config.ts
|
|
150
|
+
*/
|
|
151
|
+
export function updateDatabaseConfig(content: string, databaseConfig: DatabaseConfig): string {
|
|
152
|
+
if (databaseConfig.type === 'mongodb') {
|
|
153
|
+
// Update to MongoDB adapter
|
|
154
|
+
const dbRegex = /db:[^,}]*(?:,|\})/
|
|
155
|
+
const mongoImportRegex = /import.*mongooseAdapter.*from.*@payloadcms\/db-mongodb.*/
|
|
156
|
+
|
|
157
|
+
if (!content.match(mongoImportRegex)) {
|
|
158
|
+
content = content.replace(
|
|
159
|
+
/(import.*from.*payload.*\n)/,
|
|
160
|
+
`$1import { mongooseAdapter } from '@payloadcms/db-mongodb'\n`,
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const dbConfig = `db: mongooseAdapter({\n url: process.env.DATABASE_URI || '${databaseConfig.url || ''}',\n })`
|
|
165
|
+
content = content.replace(dbRegex, `${dbConfig},`)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return content
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Updates plugins configuration in payload.config.ts
|
|
173
|
+
*/
|
|
174
|
+
export function updatePluginsConfig(content: string, pluginUpdates: PluginUpdates): string {
|
|
175
|
+
// Add plugin imports
|
|
176
|
+
if (pluginUpdates.add) {
|
|
177
|
+
pluginUpdates.add.forEach((pluginImport: string) => {
|
|
178
|
+
if (!content.includes(pluginImport)) {
|
|
179
|
+
content = content.replace(/(import.*from.*payload.*\n)/, `$1${pluginImport}\n`)
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Handle plugins array
|
|
185
|
+
const pluginsRegex = /plugins:\s*\[([\s\S]*?)\]/
|
|
186
|
+
const pluginsMatch = content.match(pluginsRegex)
|
|
187
|
+
|
|
188
|
+
if (pluginsMatch && pluginsMatch[1]) {
|
|
189
|
+
let pluginsContent = pluginsMatch[1]
|
|
190
|
+
|
|
191
|
+
// Remove plugins
|
|
192
|
+
if (pluginUpdates.remove) {
|
|
193
|
+
pluginUpdates.remove.forEach((pluginName: string) => {
|
|
194
|
+
const pluginRegex = new RegExp(`\\s*${pluginName}\\(\\)\\s*,?`, 'g')
|
|
195
|
+
pluginsContent = pluginsContent.replace(pluginRegex, '')
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Add plugins
|
|
200
|
+
if (pluginUpdates.add) {
|
|
201
|
+
pluginUpdates.add.forEach((pluginImport: string) => {
|
|
202
|
+
// This will match: import { PluginName } from '...';
|
|
203
|
+
const match = pluginImport.match(/import\s*\{\s*(\w+)\s*\}/)
|
|
204
|
+
if (match && match[1]) {
|
|
205
|
+
const pluginName = match[1]
|
|
206
|
+
if (!pluginsContent.includes(`${pluginName}(`)) {
|
|
207
|
+
pluginsContent = pluginsContent.trim()
|
|
208
|
+
? `${pluginsContent}\n ${pluginName}(),`
|
|
209
|
+
: `\n ${pluginName}(),`
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
content = content.replace(pluginsRegex, `plugins: [${pluginsContent}\n ]`)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return content
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Updates general configuration options in payload.config.ts
|
|
223
|
+
*/
|
|
224
|
+
export function updateGeneralConfig(content: string, generalConfig: GeneralConfig): string {
|
|
225
|
+
// Update various general configuration options
|
|
226
|
+
Object.entries(generalConfig).forEach(([key, value]) => {
|
|
227
|
+
if (value !== undefined && value !== null) {
|
|
228
|
+
const configRegex = new RegExp(`${key}:\\s*[^,}]*`, 'g')
|
|
229
|
+
|
|
230
|
+
if (content.match(configRegex)) {
|
|
231
|
+
if (typeof value === 'string') {
|
|
232
|
+
content = content.replace(configRegex, `${key}: '${value}'`)
|
|
233
|
+
} else if (typeof value === 'boolean') {
|
|
234
|
+
content = content.replace(configRegex, `${key}: ${value}`)
|
|
235
|
+
} else if (typeof value === 'object') {
|
|
236
|
+
content = content.replace(configRegex, `${key}: ${JSON.stringify(value, null, 2)}`)
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
// Add new config option
|
|
240
|
+
const configValue =
|
|
241
|
+
typeof value === 'string'
|
|
242
|
+
? `'${value}'`
|
|
243
|
+
: typeof value === 'object'
|
|
244
|
+
? JSON.stringify(value, null, 2)
|
|
245
|
+
: value
|
|
246
|
+
content = content.replace(
|
|
247
|
+
/export default buildConfig\(\{/,
|
|
248
|
+
`export default buildConfig({\n ${key}: ${configValue},`,
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
return content
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Updates collection-level configuration in a collection file
|
|
259
|
+
*/
|
|
260
|
+
export function updateCollectionConfig(
|
|
261
|
+
content: string,
|
|
262
|
+
updates: CollectionConfigUpdates,
|
|
263
|
+
collectionName: string,
|
|
264
|
+
): string {
|
|
265
|
+
let updatedContent = content
|
|
266
|
+
|
|
267
|
+
if (updates.slug) {
|
|
268
|
+
updatedContent = updatedContent.replace(/slug:\s*'[^']*'/, `slug: '${updates.slug}'`)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (updates.access) {
|
|
272
|
+
const accessRegex = /access:\s*\{[^}]*\}/
|
|
273
|
+
if (updatedContent.match(accessRegex)) {
|
|
274
|
+
// Update existing access config
|
|
275
|
+
Object.entries(updates.access).forEach(([key, value]) => {
|
|
276
|
+
if (value !== undefined) {
|
|
277
|
+
updatedContent = updatedContent.replace(
|
|
278
|
+
new RegExp(`${key}:\\s*[^,}]*`),
|
|
279
|
+
`${key}: ${value}`,
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
} else {
|
|
284
|
+
// Add access config
|
|
285
|
+
const accessConfig = Object.entries(updates.access)
|
|
286
|
+
.filter(([, value]) => value !== undefined)
|
|
287
|
+
.map(([key, value]) => ` ${key}: ${value}`)
|
|
288
|
+
.join(',\n')
|
|
289
|
+
|
|
290
|
+
updatedContent = updatedContent.replace(
|
|
291
|
+
/slug:\s*'[^']*',/,
|
|
292
|
+
`slug: '${collectionName}',\n access: {\n${accessConfig}\n },`,
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (updates.timestamps !== undefined) {
|
|
298
|
+
if (updatedContent.includes('timestamps:')) {
|
|
299
|
+
updatedContent = updatedContent.replace(
|
|
300
|
+
/timestamps:[^,}]*/,
|
|
301
|
+
`timestamps: ${updates.timestamps}`,
|
|
302
|
+
)
|
|
303
|
+
} else {
|
|
304
|
+
updatedContent = updatedContent.replace(
|
|
305
|
+
/fields:\s*\[/,
|
|
306
|
+
`timestamps: ${updates.timestamps},\n fields: [`,
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (updates.versioning !== undefined) {
|
|
312
|
+
if (updatedContent.includes('versioning:')) {
|
|
313
|
+
updatedContent = updatedContent.replace(
|
|
314
|
+
/versioning:[^,}]*/,
|
|
315
|
+
`versioning: ${updates.versioning}`,
|
|
316
|
+
)
|
|
317
|
+
} else {
|
|
318
|
+
updatedContent = updatedContent.replace(
|
|
319
|
+
/fields:\s*\[/,
|
|
320
|
+
`versioning: ${updates.versioning},\n fields: [`,
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return updatedContent
|
|
326
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
type FieldDefinition = {
|
|
2
|
+
description?: string
|
|
3
|
+
name: string
|
|
4
|
+
options?: { label: string; value: string }[]
|
|
5
|
+
position?: 'main' | 'sidebar'
|
|
6
|
+
required?: boolean
|
|
7
|
+
type: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type FieldModification = {
|
|
11
|
+
changes: {
|
|
12
|
+
description?: string
|
|
13
|
+
options?: { label: string; value: string }[]
|
|
14
|
+
position?: 'main' | 'sidebar'
|
|
15
|
+
required?: boolean
|
|
16
|
+
type?: string
|
|
17
|
+
}
|
|
18
|
+
fieldName: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Adds new fields to a collection file content
|
|
23
|
+
*/
|
|
24
|
+
export function addFieldsToCollection(content: string, newFields: FieldDefinition[]): string {
|
|
25
|
+
// Find the fields array closing bracket
|
|
26
|
+
const fieldsRegex = /fields:\s*\[([\s\S]*?)\]\s*(?:,\s*)?\}/
|
|
27
|
+
const match = content.match(fieldsRegex)
|
|
28
|
+
|
|
29
|
+
if (!match) {
|
|
30
|
+
throw new Error('Could not find fields array in collection file')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Generate new field definitions
|
|
34
|
+
const newFieldDefinitions = newFields
|
|
35
|
+
.map((field) => {
|
|
36
|
+
const fieldConfig = []
|
|
37
|
+
fieldConfig.push(` {`)
|
|
38
|
+
fieldConfig.push(` name: '${field.name}',`)
|
|
39
|
+
fieldConfig.push(` type: '${field.type}',`)
|
|
40
|
+
|
|
41
|
+
if (field.required) {
|
|
42
|
+
fieldConfig.push(` required: true,`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (field.description || field.position) {
|
|
46
|
+
fieldConfig.push(` admin: {`)
|
|
47
|
+
if (field.description) {
|
|
48
|
+
fieldConfig.push(` description: '${field.description}',`)
|
|
49
|
+
}
|
|
50
|
+
if (field.position) {
|
|
51
|
+
fieldConfig.push(` position: '${field.position}',`)
|
|
52
|
+
}
|
|
53
|
+
fieldConfig.push(` },`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (field.options && field.type === 'select') {
|
|
57
|
+
fieldConfig.push(` options: [`)
|
|
58
|
+
field.options.forEach((option: { label: string; value: string }) => {
|
|
59
|
+
fieldConfig.push(` { label: '${option.label}', value: '${option.value}' },`)
|
|
60
|
+
})
|
|
61
|
+
fieldConfig.push(` ],`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fieldConfig.push(` },`)
|
|
65
|
+
return fieldConfig.join('\n')
|
|
66
|
+
})
|
|
67
|
+
.join('\n')
|
|
68
|
+
|
|
69
|
+
// Add new fields before the closing bracket
|
|
70
|
+
const existingFields = match[1] || ''
|
|
71
|
+
const hasTrailingComma = existingFields.trim().endsWith(',')
|
|
72
|
+
const separator = hasTrailingComma ? '\n' : ',\n'
|
|
73
|
+
|
|
74
|
+
return content.replace(
|
|
75
|
+
fieldsRegex,
|
|
76
|
+
`fields: [${existingFields}${separator}${newFieldDefinitions}\n ],
|
|
77
|
+
}`,
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Removes fields from a collection file content
|
|
83
|
+
*/
|
|
84
|
+
export function removeFieldsFromCollection(content: string, fieldNames: string[]): string {
|
|
85
|
+
let updatedContent = content
|
|
86
|
+
|
|
87
|
+
fieldNames.forEach((fieldName) => {
|
|
88
|
+
// Create regex to match the field definition
|
|
89
|
+
const fieldRegex = new RegExp(
|
|
90
|
+
`\\s*{[^}]*name:\\s*['"]${fieldName}['"][^}]*}[^}]*(?:},?|,?\\s*})`,
|
|
91
|
+
'gs',
|
|
92
|
+
)
|
|
93
|
+
updatedContent = updatedContent.replace(fieldRegex, '')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// Clean up any double commas or trailing commas
|
|
97
|
+
updatedContent = updatedContent.replace(/,\s*,/g, ',')
|
|
98
|
+
updatedContent = updatedContent.replace(/,\s*\]/g, '\n ]')
|
|
99
|
+
|
|
100
|
+
return updatedContent
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Modifies existing fields in a collection file content
|
|
105
|
+
*/
|
|
106
|
+
export function modifyFieldsInCollection(
|
|
107
|
+
content: string,
|
|
108
|
+
modifications: FieldModification[],
|
|
109
|
+
): string {
|
|
110
|
+
let updatedContent = content
|
|
111
|
+
|
|
112
|
+
modifications.forEach((mod) => {
|
|
113
|
+
const { changes, fieldName } = mod
|
|
114
|
+
|
|
115
|
+
// Find the field definition
|
|
116
|
+
const fieldRegex = new RegExp(`({[^}]*name:\\s*['"]${fieldName}['"][^}]*})`, 'gs')
|
|
117
|
+
const fieldMatch = updatedContent.match(fieldRegex)
|
|
118
|
+
|
|
119
|
+
if (fieldMatch) {
|
|
120
|
+
let fieldDef = fieldMatch[0]
|
|
121
|
+
|
|
122
|
+
// Apply changes
|
|
123
|
+
if (changes.type) {
|
|
124
|
+
fieldDef = fieldDef.replace(/type:\s*'[^']*'/, `type: '${changes.type}'`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (changes.required !== undefined) {
|
|
128
|
+
if (fieldDef.includes('required:')) {
|
|
129
|
+
fieldDef = fieldDef.replace(/required:[^,]*/, `required: ${changes.required}`)
|
|
130
|
+
} else {
|
|
131
|
+
fieldDef = fieldDef.replace(
|
|
132
|
+
/type:\s*'[^']*',/,
|
|
133
|
+
`type: '${changes.type}',\n required: ${changes.required},`,
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (changes.description) {
|
|
139
|
+
const adminRegex = /admin:\s*\{[^}]*\}/
|
|
140
|
+
if (fieldDef.match(adminRegex)) {
|
|
141
|
+
fieldDef = fieldDef.replace(
|
|
142
|
+
/description:\s*'[^']*'/,
|
|
143
|
+
`description: '${changes.description}'`,
|
|
144
|
+
)
|
|
145
|
+
} else {
|
|
146
|
+
fieldDef = fieldDef.replace(
|
|
147
|
+
/\},?\s*$/,
|
|
148
|
+
`,\n admin: {\n description: '${changes.description}',\n },\n }`,
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
updatedContent = updatedContent.replace(fieldRegex, fieldDef)
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
return updatedContent
|
|
158
|
+
}
|