create-payload-app 3.67.0-internal.8383bda → 3.67.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.
Files changed (51) hide show
  1. package/dist/ast-integration.spec.js +131 -0
  2. package/dist/ast-integration.spec.js.map +1 -0
  3. package/dist/lib/ast/adapter-config.d.ts +40 -0
  4. package/dist/lib/ast/adapter-config.d.ts.map +1 -0
  5. package/dist/lib/ast/adapter-config.js +145 -0
  6. package/dist/lib/ast/adapter-config.js.map +1 -0
  7. package/dist/lib/ast/package-json.d.ts +13 -0
  8. package/dist/lib/ast/package-json.d.ts.map +1 -0
  9. package/dist/lib/ast/package-json.js +103 -0
  10. package/dist/lib/ast/package-json.js.map +1 -0
  11. package/dist/lib/ast/package-json.spec.js +66 -0
  12. package/dist/lib/ast/package-json.spec.js.map +1 -0
  13. package/dist/lib/ast/payload-config.d.ts +23 -0
  14. package/dist/lib/ast/payload-config.d.ts.map +1 -0
  15. package/dist/lib/ast/payload-config.js +655 -0
  16. package/dist/lib/ast/payload-config.js.map +1 -0
  17. package/dist/lib/ast/payload-config.spec.js +364 -0
  18. package/dist/lib/ast/payload-config.spec.js.map +1 -0
  19. package/dist/lib/ast/types.d.ts +126 -0
  20. package/dist/lib/ast/types.d.ts.map +1 -0
  21. package/dist/lib/ast/types.js +18 -0
  22. package/dist/lib/ast/types.js.map +1 -0
  23. package/dist/lib/ast/utils.d.ts +48 -0
  24. package/dist/lib/ast/utils.d.ts.map +1 -0
  25. package/dist/lib/ast/utils.js +189 -0
  26. package/dist/lib/ast/utils.js.map +1 -0
  27. package/dist/lib/ast/utils.spec.js +225 -0
  28. package/dist/lib/ast/utils.spec.js.map +1 -0
  29. package/dist/lib/configure-payload-config.d.ts.map +1 -1
  30. package/dist/lib/configure-payload-config.js +30 -86
  31. package/dist/lib/configure-payload-config.js.map +1 -1
  32. package/dist/lib/create-project.spec.js +9 -5
  33. package/dist/lib/create-project.spec.js.map +1 -1
  34. package/dist/lib/init-next.d.ts.map +1 -1
  35. package/dist/lib/init-next.js +2 -1
  36. package/dist/lib/init-next.js.map +1 -1
  37. package/dist/main.d.ts.map +1 -1
  38. package/dist/main.js +4 -0
  39. package/dist/main.js.map +1 -1
  40. package/dist/template/src/payload.config.ts +2 -7
  41. package/dist/types.d.ts +3 -2
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/dist/utils/log.d.ts.map +1 -1
  45. package/dist/utils/log.js +3 -1
  46. package/dist/utils/log.js.map +1 -1
  47. package/package.json +4 -2
  48. package/dist/lib/replacements.d.ts +0 -27
  49. package/dist/lib/replacements.d.ts.map +0 -1
  50. package/dist/lib/replacements.js +0 -104
  51. package/dist/lib/replacements.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/ast/payload-config.ts"],"sourcesContent":["import { execSync } from 'child_process'\nimport path from 'path'\nimport { Project, QuoteKind, type SourceFile, SyntaxKind } from 'ts-morph'\n\nimport type {\n ConfigureOptions,\n DatabaseAdapter,\n DetectionResult,\n Modification,\n StorageAdapter,\n TransformationResult,\n WriteOptions,\n WriteResult,\n} from './types.js'\n\nimport { debug } from '../../utils/log.js'\nimport { DB_ADAPTER_CONFIG, STORAGE_ADAPTER_CONFIG } from './adapter-config.js'\nimport {\n addImportDeclaration,\n cleanupOrphanedImports,\n formatError,\n removeImportDeclaration,\n} from './utils.js'\n\nexport function detectPayloadConfigStructure(sourceFile: SourceFile): DetectionResult {\n debug(`[AST] Detecting payload config structure in ${sourceFile.getFilePath()}`)\n\n // First find the actual name being used (might be aliased)\n const payloadImport = sourceFile\n .getImportDeclarations()\n .find((imp) => imp.getModuleSpecifierValue() === 'payload')\n\n const buildConfigImportSpec = payloadImport\n ?.getNamedImports()\n .find((spec) => spec.getName() === 'buildConfig')\n\n const aliasNode = buildConfigImportSpec?.getAliasNode()\n const buildConfigName = aliasNode ? aliasNode.getText() : 'buildConfig'\n\n debug(`[AST] Looking for function call: ${buildConfigName}`)\n\n // Find buildConfig call expression (using actual name in code)\n const buildConfigCall = sourceFile\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .find((call) => {\n const expression = call.getExpression()\n return expression.getText() === buildConfigName\n })\n\n if (!buildConfigCall) {\n debug(`[AST] ✗ ${buildConfigName} call not found`)\n return {\n error: formatError({\n actual: `No ${buildConfigName} call found in file`,\n context: 'buildConfig call',\n expected: `export default ${buildConfigName}({ ... })`,\n technicalDetails: `Could not find CallExpression with identifier \"${buildConfigName}\"`,\n }),\n success: false,\n }\n }\n\n debug(`[AST] ✓ ${buildConfigName} call found`)\n\n // Get import statements\n const importStatements = sourceFile.getImportDeclarations()\n debug(`[AST] Found ${importStatements.length} import statements`)\n\n // Find db property if it exists\n const configObject = buildConfigCall.getArguments()[0]\n let dbProperty\n if (configObject && configObject.getKind() === SyntaxKind.ObjectLiteralExpression) {\n dbProperty = configObject\n .asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n .getProperty('db')\n ?.asKind(SyntaxKind.PropertyAssignment)\n }\n\n debug(`[AST] db property: ${dbProperty ? '✓ found' : '✗ not found'}`)\n\n // Find plugins array if it exists\n let pluginsArray\n if (configObject && configObject.getKind() === SyntaxKind.ObjectLiteralExpression) {\n const objLiteral = configObject.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n const pluginsProperty = objLiteral.getProperty('plugins')\n\n // Handle PropertyAssignment (e.g., plugins: [...])\n const propertyAssignment = pluginsProperty?.asKind(SyntaxKind.PropertyAssignment)\n if (propertyAssignment) {\n const initializer = propertyAssignment.getInitializer()\n if (initializer?.getKind() === SyntaxKind.ArrayLiteralExpression) {\n pluginsArray = initializer.asKind(SyntaxKind.ArrayLiteralExpression)\n }\n }\n // For ShorthandPropertyAssignment (e.g., plugins), we can't get the array directly\n // but we'll detect it in addStorageAdapter\n }\n\n debug(`[AST] plugins array: ${pluginsArray ? '✓ found' : '✗ not found'}`)\n\n // Find all buildConfig calls for edge case detection (using actual name)\n const allBuildConfigCalls = sourceFile\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .filter((call) => {\n const expression = call.getExpression()\n return expression.getText() === buildConfigName\n })\n\n const hasImportAlias = !!aliasNode\n\n // Check for other Payload imports\n const payloadImports = payloadImport?.getNamedImports() || []\n const hasOtherPayloadImports =\n payloadImports.length > 1 || payloadImports.some((imp) => imp.getName() !== 'buildConfig')\n\n // Track database adapter imports\n let dbAdapterImportInfo\n for (const [, config] of Object.entries(DB_ADAPTER_CONFIG)) {\n const importDecl = sourceFile\n .getImportDeclarations()\n .find((imp) => imp.getModuleSpecifierValue() === config.packageName)\n\n if (importDecl) {\n const namedImports = importDecl.getNamedImports()\n dbAdapterImportInfo = {\n hasOtherImports: namedImports.length > 1,\n importDeclaration: importDecl,\n packageName: config.packageName,\n }\n break\n }\n }\n\n // Track storage adapter imports\n const storageAdapterImports = []\n for (const [, config] of Object.entries(STORAGE_ADAPTER_CONFIG)) {\n if (!config.packageName || !config.adapterName) {\n continue\n }\n\n const importDecl = sourceFile\n .getImportDeclarations()\n .find((imp) => imp.getModuleSpecifierValue() === config.packageName)\n\n if (importDecl) {\n const namedImports = importDecl.getNamedImports()\n storageAdapterImports.push({\n hasOtherImports: namedImports.length > 1,\n importDeclaration: importDecl,\n packageName: config.packageName,\n })\n }\n }\n\n const needsManualIntervention = hasImportAlias || allBuildConfigCalls.length > 2\n\n debug(\n `[AST] Edge cases: alias=${hasImportAlias}, multiple=${allBuildConfigCalls.length > 1}, otherImports=${hasOtherPayloadImports}, manual=${needsManualIntervention}`,\n )\n\n return {\n edgeCases: {\n hasImportAlias,\n hasOtherPayloadImports,\n multipleBuildConfigCalls: allBuildConfigCalls.length > 1,\n needsManualIntervention,\n },\n importSources: {\n dbAdapter: dbAdapterImportInfo,\n storageAdapters: storageAdapterImports.length > 0 ? storageAdapterImports : undefined,\n },\n sourceFile,\n structures: {\n buildConfigCall,\n dbProperty,\n importStatements,\n pluginsArray,\n },\n success: true,\n }\n}\n\nexport function addDatabaseAdapter({\n adapter,\n envVarName = 'DATABASE_URI',\n sourceFile,\n}: {\n adapter: DatabaseAdapter\n envVarName?: string\n sourceFile: SourceFile\n}): TransformationResult {\n debug(`[AST] Adding database adapter: ${adapter} (envVar: ${envVarName})`)\n\n const modifications: Modification[] = []\n\n const detection = detectPayloadConfigStructure(sourceFile)\n\n if (!detection.success || !detection.structures) {\n return {\n error: detection.error,\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const { buildConfigCall, dbProperty } = detection.structures\n const config = DB_ADAPTER_CONFIG[adapter]\n\n // Remove old db adapter imports and track position for replacement\n const oldAdapters = Object.values(DB_ADAPTER_CONFIG)\n const removedAdapters: string[] = []\n let importInsertIndex: number | undefined\n oldAdapters.forEach((oldConfig) => {\n if (oldConfig.packageName !== config.packageName) {\n const { removedIndex } = removeImportDeclaration({\n moduleSpecifier: oldConfig.packageName,\n sourceFile,\n })\n if (removedIndex !== undefined) {\n // Use the first removed adapter's position\n if (importInsertIndex === undefined) {\n importInsertIndex = removedIndex\n }\n removedAdapters.push(oldConfig.packageName)\n modifications.push({\n type: 'import-removed',\n description: `Removed import from '${oldConfig.packageName}'`,\n })\n }\n }\n })\n\n if (removedAdapters.length > 0) {\n debug(`[AST] Removed old adapter imports: ${removedAdapters.join(', ')}`)\n }\n\n // Add new import at the position of the removed one (or default position)\n addImportDeclaration({\n insertIndex: importInsertIndex,\n moduleSpecifier: config.packageName,\n namedImports: [config.adapterName],\n sourceFile,\n })\n modifications.push({\n type: 'import-added',\n description: `Added import: { ${config.adapterName} } from '${config.packageName}'`,\n })\n\n // Add special imports for specific adapters\n if (adapter === 'd1-sqlite') {\n debug('[AST] Adding special import: ./db/migrations')\n addImportDeclaration({\n defaultImport: 'migrations',\n moduleSpecifier: './db/migrations',\n sourceFile,\n })\n modifications.push({\n type: 'import-added',\n description: `Added import: migrations from './db/migrations'`,\n })\n }\n\n // Get config object\n const configObject = buildConfigCall.getArguments()[0]\n if (!configObject || configObject.getKind() !== SyntaxKind.ObjectLiteralExpression) {\n return {\n error: formatError({\n actual: 'buildConfig has no object literal argument',\n context: 'database adapter configuration',\n expected: 'buildConfig({ ... })',\n technicalDetails: 'buildConfig call must have an object literal as first argument',\n }),\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const objLiteral = configObject.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\n const newDbCode = `db: ${config.configTemplate(envVarName)}`\n\n if (dbProperty) {\n // Replace existing db property\n // NOTE: Using replaceWithText() instead of remove() + insertPropertyAssignment()\n // to avoid double comma issues. When remove() is called, ts-morph doesn't always\n // clean up trailing commas correctly, which can result in syntax like \"},,\" when\n // inserting a new property at that position. replaceWithText() preserves the\n // surrounding punctuation correctly.\n debug(`[AST] Replacing existing db property`)\n dbProperty.replaceWithText(newDbCode)\n modifications.push({\n type: 'property-added',\n description: `Replaced db property with ${adapter} adapter`,\n })\n } else {\n // No existing db property - insert at end\n const insertIndex = objLiteral.getProperties().length\n debug(`[AST] Adding db property at index ${insertIndex}`)\n objLiteral.insertPropertyAssignment(insertIndex, {\n name: 'db',\n initializer: config.configTemplate(envVarName),\n })\n modifications.push({\n type: 'property-added',\n description: `Added db property with ${adapter} adapter`,\n })\n }\n\n debug(`[AST] ✓ Database adapter ${adapter} added successfully`)\n\n return {\n modifications,\n modified: true,\n success: true,\n }\n}\n\nexport function addStorageAdapter({\n adapter,\n sourceFile,\n}: {\n adapter: StorageAdapter\n sourceFile: SourceFile\n}): TransformationResult {\n debug(`[AST] Adding storage adapter: ${adapter}`)\n\n const modifications: Modification[] = []\n\n const detection = detectPayloadConfigStructure(sourceFile)\n\n if (!detection.success || !detection.structures) {\n return {\n error: detection.error,\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const config = STORAGE_ADAPTER_CONFIG[adapter]\n\n // Local disk doesn't need any imports or plugins\n if (adapter === 'localDisk') {\n debug('[AST] localDisk storage adapter - no imports or plugins needed')\n return {\n modifications: [],\n modified: false,\n success: true,\n }\n }\n\n // Add import\n if (config.packageName && config.adapterName) {\n addImportDeclaration({\n moduleSpecifier: config.packageName,\n namedImports: [config.adapterName],\n sourceFile,\n })\n modifications.push({\n type: 'import-added',\n description: `Added import: { ${config.adapterName} } from '${config.packageName}'`,\n })\n }\n\n const { buildConfigCall } = detection.structures\n const configObject = buildConfigCall.getArguments()[0]\n\n if (!configObject || configObject.getKind() !== SyntaxKind.ObjectLiteralExpression) {\n return {\n error: formatError({\n actual: 'buildConfig has no object literal argument',\n context: 'storage adapter configuration',\n expected: 'buildConfig({ ... })',\n technicalDetails: 'buildConfig call must have an object literal as first argument',\n }),\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const objLiteral = configObject.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\n // Find or create plugins array\n const pluginsPropertyRaw = objLiteral.getProperty('plugins')\n let pluginsProperty = pluginsPropertyRaw?.asKind(SyntaxKind.PropertyAssignment)\n\n // Check if it's a shorthand property (e.g., `plugins` referencing an imported variable)\n const shorthandProperty = pluginsPropertyRaw?.asKind(SyntaxKind.ShorthandPropertyAssignment)\n\n if (shorthandProperty) {\n debug('[AST] Found shorthand plugins property, converting to long form with spread')\n // Get the identifier name (usually 'plugins')\n const identifierName = shorthandProperty.getName()\n\n // Find insert position before removing\n const allProperties = objLiteral.getProperties()\n const insertIndex = allProperties.indexOf(shorthandProperty)\n\n // Remove the shorthand property\n shorthandProperty.remove()\n\n // Create new property with spread operator: plugins: [...plugins, newAdapter]\n objLiteral.insertPropertyAssignment(insertIndex, {\n name: 'plugins',\n initializer: `[...${identifierName}]`,\n })\n\n pluginsProperty = objLiteral.getProperty('plugins')?.asKind(SyntaxKind.PropertyAssignment)\n modifications.push({\n type: 'property-added',\n description: `Converted shorthand plugins property to array with spread syntax`,\n })\n } else if (!pluginsProperty) {\n debug('[AST] Creating new plugins array')\n // Create plugins array\n objLiteral.addPropertyAssignment({\n name: 'plugins',\n initializer: '[]',\n })\n pluginsProperty = objLiteral.getProperty('plugins')?.asKind(SyntaxKind.PropertyAssignment)\n modifications.push({\n type: 'property-added',\n description: `Created plugins array`,\n })\n } else {\n debug('[AST] Reusing existing plugins array')\n }\n\n if (!pluginsProperty) {\n return {\n error: formatError({\n actual: 'Failed to create or find plugins property',\n context: 'storage adapter configuration',\n expected: 'plugins array property',\n technicalDetails: 'Could not create or access plugins property',\n }),\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const initializer = pluginsProperty.getInitializer()\n if (!initializer || initializer.getKind() !== SyntaxKind.ArrayLiteralExpression) {\n return {\n error: formatError({\n actual: 'plugins property is not an array',\n context: 'storage adapter configuration',\n expected: 'plugins: [...]',\n technicalDetails: 'plugins property must be an array literal expression',\n }),\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const pluginsArray = initializer.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n // Add storage adapter call\n const configText = config.configTemplate()\n if (configText) {\n pluginsArray.addElement(configText)\n modifications.push({\n type: 'property-added',\n description: `Added ${adapter} to plugins array`,\n })\n }\n\n debug(`[AST] ✓ Storage adapter ${adapter} added successfully`)\n\n return {\n modifications,\n modified: true,\n success: true,\n }\n}\n\nexport function removeSharp(sourceFile: SourceFile): TransformationResult {\n debug('[AST] Removing sharp import and property')\n\n const modifications: Modification[] = []\n\n // Remove import\n const { removedIndex } = removeImportDeclaration({ moduleSpecifier: 'sharp', sourceFile })\n if (removedIndex !== undefined) {\n modifications.push({\n type: 'import-removed',\n description: `Removed import from 'sharp'`,\n })\n }\n\n // Find and remove sharp property from buildConfig\n const detection = detectPayloadConfigStructure(sourceFile)\n\n if (!detection.success || !detection.structures) {\n // If detection failed but we removed import, still count as partial success\n if (modifications.length > 0) {\n return {\n modifications,\n modified: true,\n success: true,\n warnings: ['Could not detect config structure to remove sharp property'],\n }\n }\n return {\n error: detection.error,\n modifications: [],\n modified: false,\n success: false,\n }\n }\n\n const { buildConfigCall } = detection.structures\n const configObject = buildConfigCall.getArguments()[0]\n\n if (!configObject || configObject.getKind() !== SyntaxKind.ObjectLiteralExpression) {\n return {\n modifications,\n modified: modifications.length > 0,\n success: true,\n warnings: ['buildConfig has no object literal argument - could not remove sharp property'],\n }\n }\n\n const objLiteral = configObject.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n const sharpProperty = objLiteral.getProperty('sharp')\n\n if (sharpProperty) {\n sharpProperty.remove()\n modifications.push({\n type: 'property-removed',\n description: `Removed sharp property from config`,\n })\n debug('[AST] ✓ Sharp property removed from config')\n } else {\n debug('[AST] Sharp property not found (already absent)')\n }\n\n return {\n modifications,\n modified: modifications.length > 0,\n success: true,\n }\n}\n\n/** This shouldn't be necessary once the templates are updated. Can't hurt to keep in, though */\nexport function removeCommentMarkers(sourceFile: SourceFile): SourceFile {\n // Get the full text and replace comment markers\n let text = sourceFile.getFullText()\n\n // Remove inline comment markers from imports\n text = text.replace(/\\s*\\/\\/\\s*database-adapter-import\\s*$/gm, '')\n text = text.replace(/\\s*\\/\\/\\s*storage-adapter-import-placeholder\\s*$/gm, '')\n\n // Remove standalone comment lines\n text = text.replace(/^\\s*\\/\\/\\s*database-adapter-config-start\\s*\\n/gm, '')\n text = text.replace(/^\\s*\\/\\/\\s*database-adapter-config-end\\s*\\n/gm, '')\n text = text.replace(/^\\s*\\/\\/\\s*storage-adapter-placeholder\\s*\\n/gm, '')\n\n // Also remove the placeholder line from template (storage-adapter-import-placeholder at top)\n text = text.replace(/^\\/\\/\\s*storage-adapter-import-placeholder\\s*\\n/gm, '')\n\n // Replace the entire source file content\n sourceFile.replaceWithText(text)\n\n return sourceFile\n}\n\n/**\n * Validates payload config structure has required elements after transformation.\n * Checks that buildConfig() call exists and has a db property configured.\n */\nexport function validateStructure(sourceFile: SourceFile): WriteResult {\n debug('[AST] Validating payload config structure')\n\n const detection = detectPayloadConfigStructure(sourceFile)\n\n if (!detection.success) {\n debug('[AST] ✗ Validation failed: detection unsuccessful')\n return {\n error: detection.error,\n success: false,\n }\n }\n\n const { structures } = detection\n\n // Validate db property exists\n if (!structures?.dbProperty) {\n debug('[AST] ✗ Validation failed: db property missing')\n return {\n error: formatError({\n actual: 'No db property found',\n context: 'database configuration',\n expected: 'buildConfig must have a db property',\n technicalDetails: 'PropertyAssignment with name \"db\" not found in buildConfig object',\n }),\n success: false,\n }\n }\n\n debug('[AST] ✓ Validation passed')\n return { success: true }\n}\n\nexport async function writeTransformedFile(\n sourceFile: SourceFile,\n options: WriteOptions = {},\n): Promise<WriteResult> {\n const { formatWithPrettier = true, validateStructure: shouldValidate = true } = options\n\n debug(`[AST] Writing transformed file: ${sourceFile.getFilePath()}`)\n\n // Validate if requested\n if (shouldValidate) {\n const validation = validateStructure(sourceFile)\n if (!validation.success) {\n return validation\n }\n }\n\n // Get file path and save to disk\n const filePath = sourceFile.getFilePath()\n\n // Format with ts-morph before saving (fixes trailing commas, indentation)\n debug('[AST] Formatting with ts-morph')\n sourceFile.formatText()\n\n // Write file\n debug('[AST] Writing file to disk')\n await sourceFile.save()\n\n // Format with prettier if requested\n if (formatWithPrettier) {\n debug('[AST] Running prettier formatting via CLI')\n try {\n // Detect project directory (go up from file until we find package.json or use dirname)\n const projectDir = path.dirname(filePath)\n\n // Run prettier via CLI (avoids Jest/ESM compatibility issues)\n const prettierCmd = `npx prettier --write \"${filePath}\"`\n\n debug(`[AST] Executing: ${prettierCmd}`)\n execSync(prettierCmd, {\n cwd: projectDir,\n stdio: 'pipe', // Suppress output\n })\n debug('[AST] ✓ Prettier formatting successful')\n } catch (error) {\n // Log but don't fail if prettier fails (might not be installed)\n debug(\n `[AST] ⚠ Prettier formatting failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n debug('[AST] Continuing with unformatted output')\n }\n } else {\n debug('[AST] Skipping prettier formatting (disabled)')\n }\n\n debug('[AST] ✓ File written successfully')\n\n return { success: true }\n}\n\nexport async function configurePayloadConfig(\n filePath: string,\n options: ConfigureOptions = {},\n): Promise<WriteResult> {\n debug(`[AST] Configuring payload config: ${filePath}`)\n debug(\n `[AST] Options: db=${options.db?.type}, storage=${options.storage}, removeSharp=${options.removeSharp}`,\n )\n\n const allModifications: Modification[] = []\n const allWarnings: string[] = []\n\n try {\n // Create Project and load source file with proper settings\n const project = new Project({\n manipulationSettings: {\n quoteKind: QuoteKind.Single,\n },\n })\n let sourceFile = project.addSourceFileAtPath(filePath)\n\n // Run detection\n const detection = detectPayloadConfigStructure(sourceFile)\n if (!detection.success) {\n return detection\n }\n\n // Apply transformations based on options\n if (options.db) {\n debug('[AST] Applying database adapter transformation')\n const result = addDatabaseAdapter({\n adapter: options.db.type,\n envVarName: options.db.envVarName,\n sourceFile,\n })\n\n if (!result.success) {\n return {\n error: result.error,\n success: false,\n }\n }\n\n allModifications.push(...result.modifications)\n if (result.warnings) {\n allWarnings.push(...result.warnings)\n }\n }\n\n if (options.storage) {\n debug('[AST] Applying storage adapter transformation')\n const result = addStorageAdapter({ adapter: options.storage, sourceFile })\n\n if (!result.success) {\n return {\n error: result.error,\n success: false,\n }\n }\n\n allModifications.push(...result.modifications)\n if (result.warnings) {\n allWarnings.push(...result.warnings)\n }\n }\n\n if (options.removeSharp) {\n debug('[AST] Applying sharp removal')\n const result = removeSharp(sourceFile)\n\n if (!result.success) {\n return {\n error: result.error,\n success: false,\n }\n }\n\n allModifications.push(...result.modifications)\n if (result.warnings) {\n allWarnings.push(...result.warnings)\n }\n }\n\n // Remove comment markers from template\n sourceFile = removeCommentMarkers(sourceFile)\n\n // Cleanup orphaned imports after all transformations\n debug('[AST] Cleaning up orphaned imports')\n\n // Cleanup database adapter imports if db was removed\n for (const [, config] of Object.entries(DB_ADAPTER_CONFIG)) {\n if (options.db && config.packageName !== DB_ADAPTER_CONFIG[options.db.type].packageName) {\n const cleanup = cleanupOrphanedImports({\n importNames: [config.adapterName],\n moduleSpecifier: config.packageName,\n sourceFile,\n })\n if (cleanup.removed.length > 0) {\n cleanup.removed.forEach((importName) => {\n allModifications.push({\n type: 'import-removed',\n description: `Cleaned up unused import '${importName}' from '${config.packageName}'`,\n })\n })\n }\n }\n }\n\n // Log summary of modifications\n if (allModifications.length > 0) {\n debug(`[AST] Applied ${allModifications.length} modification(s):`)\n allModifications.forEach((mod) => {\n debug(`[AST] - ${mod.type}: ${mod.description}`)\n })\n }\n\n if (allWarnings.length > 0) {\n debug(`[AST] ${allWarnings.length} warning(s):`)\n allWarnings.forEach((warning) => {\n debug(`[AST] - ${warning}`)\n })\n }\n\n // Write transformed file with validation and formatting\n return await writeTransformedFile(sourceFile, {\n formatWithPrettier: options.formatWithPrettier,\n validateStructure: options.validateStructure ?? true,\n })\n } catch (error) {\n debug(`[AST] ✗ Configuration failed: ${error instanceof Error ? error.message : String(error)}`)\n return {\n error: formatError({\n actual: error instanceof Error ? error.message : String(error),\n context: 'configurePayloadConfig',\n expected: 'Successful file transformation',\n technicalDetails: error instanceof Error ? error.stack || error.message : String(error),\n }),\n success: false,\n }\n }\n}\n"],"names":["execSync","path","Project","QuoteKind","SyntaxKind","debug","DB_ADAPTER_CONFIG","STORAGE_ADAPTER_CONFIG","addImportDeclaration","cleanupOrphanedImports","formatError","removeImportDeclaration","detectPayloadConfigStructure","sourceFile","getFilePath","payloadImport","getImportDeclarations","find","imp","getModuleSpecifierValue","buildConfigImportSpec","getNamedImports","spec","getName","aliasNode","getAliasNode","buildConfigName","getText","buildConfigCall","getDescendantsOfKind","CallExpression","call","expression","getExpression","error","actual","context","expected","technicalDetails","success","importStatements","length","configObject","getArguments","dbProperty","getKind","ObjectLiteralExpression","asKindOrThrow","getProperty","asKind","PropertyAssignment","pluginsArray","objLiteral","pluginsProperty","propertyAssignment","initializer","getInitializer","ArrayLiteralExpression","allBuildConfigCalls","filter","hasImportAlias","payloadImports","hasOtherPayloadImports","some","dbAdapterImportInfo","config","Object","entries","importDecl","packageName","namedImports","hasOtherImports","importDeclaration","storageAdapterImports","adapterName","push","needsManualIntervention","edgeCases","multipleBuildConfigCalls","importSources","dbAdapter","storageAdapters","undefined","structures","addDatabaseAdapter","adapter","envVarName","modifications","detection","modified","oldAdapters","values","removedAdapters","importInsertIndex","forEach","oldConfig","removedIndex","moduleSpecifier","type","description","join","insertIndex","defaultImport","newDbCode","configTemplate","replaceWithText","getProperties","insertPropertyAssignment","name","addStorageAdapter","pluginsPropertyRaw","shorthandProperty","ShorthandPropertyAssignment","identifierName","allProperties","indexOf","remove","addPropertyAssignment","configText","addElement","removeSharp","warnings","sharpProperty","removeCommentMarkers","text","getFullText","replace","validateStructure","writeTransformedFile","options","formatWithPrettier","shouldValidate","validation","filePath","formatText","save","projectDir","dirname","prettierCmd","cwd","stdio","Error","message","configurePayloadConfig","db","storage","allModifications","allWarnings","project","manipulationSettings","quoteKind","Single","addSourceFileAtPath","result","cleanup","importNames","removed","importName","mod","warning","String","stack"],"mappings":"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"}
@@ -0,0 +1,364 @@
1
+ import { Project } from 'ts-morph';
2
+ import { addDatabaseAdapter, addStorageAdapter, detectPayloadConfigStructure, removeSharp } from './payload-config';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import * as os from 'os';
6
+ describe('detectPayloadConfigStructure', ()=>{
7
+ it('successfully detects buildConfig call', ()=>{
8
+ const project = new Project({
9
+ useInMemoryFileSystem: true
10
+ });
11
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
12
+
13
+ export default buildConfig({
14
+ db: mongooseAdapter({ url: '' }),
15
+ plugins: []
16
+ })`);
17
+ const result = detectPayloadConfigStructure(sourceFile);
18
+ expect(result.success).toBe(true);
19
+ expect(result.structures?.buildConfigCall).toBeDefined();
20
+ });
21
+ it('fails when buildConfig call not found', ()=>{
22
+ const project = new Project({
23
+ useInMemoryFileSystem: true
24
+ });
25
+ const sourceFile = project.createSourceFile('payload.config.ts', `export default {}`);
26
+ const result = detectPayloadConfigStructure(sourceFile);
27
+ expect(result.success).toBe(false);
28
+ expect(result.error?.userMessage).toContain('buildConfig');
29
+ expect(result.error?.technicalDetails).toContain('CallExpression');
30
+ });
31
+ it('detects buildConfig in variable declaration', ()=>{
32
+ const project = new Project({
33
+ useInMemoryFileSystem: true
34
+ });
35
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
36
+
37
+ const config = buildConfig({
38
+ db: mongooseAdapter({ url: '' })
39
+ })
40
+
41
+ export default config`);
42
+ const result = detectPayloadConfigStructure(sourceFile);
43
+ expect(result.success).toBe(true);
44
+ expect(result.structures?.buildConfigCall).toBeDefined();
45
+ });
46
+ it('detects import alias edge case', ()=>{
47
+ const project = new Project({
48
+ useInMemoryFileSystem: true
49
+ });
50
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig as createConfig } from 'payload'
51
+ import { mongooseAdapter } from '@payloadcms/db-mongodb'
52
+
53
+ export default createConfig({
54
+ db: mongooseAdapter({ url: '' }),
55
+ collections: [],
56
+ })`);
57
+ const result = detectPayloadConfigStructure(sourceFile);
58
+ expect(result.success).toBe(true);
59
+ expect(result.edgeCases?.hasImportAlias).toBe(true);
60
+ expect(result.structures?.buildConfigCall).toBeDefined();
61
+ });
62
+ it('detects multiple buildConfig calls', ()=>{
63
+ const project = new Project({
64
+ useInMemoryFileSystem: true
65
+ });
66
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
67
+
68
+ const helper = buildConfig({ collections: [] })
69
+
70
+ export default buildConfig({
71
+ collections: [],
72
+ })`);
73
+ const result = detectPayloadConfigStructure(sourceFile);
74
+ expect(result.success).toBe(true);
75
+ expect(result.edgeCases?.multipleBuildConfigCalls).toBe(true);
76
+ });
77
+ it('detects other Payload imports', ()=>{
78
+ const project = new Project({
79
+ useInMemoryFileSystem: true
80
+ });
81
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig, CollectionConfig } from 'payload'
82
+
83
+ export default buildConfig({
84
+ collections: [],
85
+ })`);
86
+ const result = detectPayloadConfigStructure(sourceFile);
87
+ expect(result.success).toBe(true);
88
+ expect(result.edgeCases?.hasOtherPayloadImports).toBe(true);
89
+ });
90
+ });
91
+ describe('addDatabaseAdapter', ()=>{
92
+ it.each([
93
+ {
94
+ adapter: 'mongodb',
95
+ adapterName: 'mongooseAdapter',
96
+ packageName: '@payloadcms/db-mongodb'
97
+ },
98
+ {
99
+ adapter: 'postgres',
100
+ adapterName: 'postgresAdapter',
101
+ packageName: '@payloadcms/db-postgres'
102
+ }
103
+ ])('adds $adapter adapter with import and config', ({ adapter, adapterName, packageName })=>{
104
+ const project = new Project({
105
+ useInMemoryFileSystem: true
106
+ });
107
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
108
+
109
+ export default buildConfig({
110
+ collections: []
111
+ })`);
112
+ const result = addDatabaseAdapter({
113
+ sourceFile,
114
+ adapter,
115
+ envVarName: 'DATABASE_URI'
116
+ });
117
+ expect(result.success).toBe(true);
118
+ expect(result.modified).toBe(true);
119
+ expect(result.modifications.length).toBeGreaterThan(0);
120
+ const text = sourceFile.getText();
121
+ expect(text).toMatch(new RegExp(`import.*${adapterName}.*from.*${packageName.replace('/', '\\/')}`));
122
+ expect(text).toContain(`db: ${adapterName}`);
123
+ expect(text).toContain('process.env.DATABASE_URI');
124
+ });
125
+ it('replaces existing db adapter', ()=>{
126
+ const project = new Project({
127
+ useInMemoryFileSystem: true
128
+ });
129
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
130
+ import { mongooseAdapter } from '@payloadcms/db-mongodb'
131
+
132
+ export default buildConfig({
133
+ db: mongooseAdapter({ url: '' }),
134
+ collections: []
135
+ })`);
136
+ const result = addDatabaseAdapter({
137
+ sourceFile,
138
+ adapter: 'postgres',
139
+ envVarName: 'DATABASE_URI'
140
+ });
141
+ expect(result.success).toBe(true);
142
+ const text = sourceFile.getText();
143
+ expect(text).toMatch(/import.*postgresAdapter.*from.*@payloadcms\/db-postgres/);
144
+ expect(text).toContain('db: postgresAdapter');
145
+ expect(text).not.toContain('mongooseAdapter');
146
+ expect(text).not.toContain('@payloadcms/db-mongodb');
147
+ });
148
+ });
149
+ describe('addStorageAdapter', ()=>{
150
+ it('adds vercelBlobStorage adapter to plugins array', ()=>{
151
+ const project = new Project({
152
+ useInMemoryFileSystem: true
153
+ });
154
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
155
+
156
+ export default buildConfig({
157
+ plugins: []
158
+ })`);
159
+ const result = addStorageAdapter({
160
+ sourceFile,
161
+ adapter: 'vercelBlobStorage'
162
+ });
163
+ expect(result.success).toBe(true);
164
+ expect(result.modified).toBe(true);
165
+ const text = sourceFile.getText();
166
+ expect(text).toMatch(/import.*vercelBlobStorage.*from.*@payloadcms\/storage-vercel-blob/);
167
+ expect(text).toContain('vercelBlobStorage(');
168
+ });
169
+ it('creates plugins array if missing', ()=>{
170
+ const project = new Project({
171
+ useInMemoryFileSystem: true
172
+ });
173
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
174
+
175
+ export default buildConfig({
176
+ collections: []
177
+ })`);
178
+ const result = addStorageAdapter({
179
+ sourceFile,
180
+ adapter: 'r2Storage'
181
+ });
182
+ expect(result.success).toBe(true);
183
+ const text = sourceFile.getText();
184
+ expect(text).toContain('plugins: [');
185
+ expect(text).toContain('r2Storage(');
186
+ });
187
+ it('adds to existing plugins array', ()=>{
188
+ const project = new Project({
189
+ useInMemoryFileSystem: true
190
+ });
191
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
192
+
193
+ export default buildConfig({
194
+ plugins: [
195
+ someOtherPlugin()
196
+ ]
197
+ })`);
198
+ const result = addStorageAdapter({
199
+ sourceFile,
200
+ adapter: 's3Storage'
201
+ });
202
+ expect(result.success).toBe(true);
203
+ const text = sourceFile.getText();
204
+ expect(text).toContain('someOtherPlugin()');
205
+ expect(text).toContain('s3Storage(');
206
+ });
207
+ });
208
+ describe('removeSharp', ()=>{
209
+ it('removes sharp import and property', ()=>{
210
+ const project = new Project({
211
+ useInMemoryFileSystem: true
212
+ });
213
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
214
+ import sharp from 'sharp'
215
+
216
+ export default buildConfig({
217
+ sharp,
218
+ collections: []
219
+ })`);
220
+ const result = removeSharp(sourceFile);
221
+ expect(result.success).toBe(true);
222
+ expect(result.modified).toBe(true);
223
+ expect(result.modifications.length).toBeGreaterThan(0);
224
+ const text = sourceFile.getText();
225
+ expect(text).not.toContain("import sharp from 'sharp'");
226
+ expect(text).not.toContain('sharp,');
227
+ });
228
+ it('does nothing if sharp not present', ()=>{
229
+ const project = new Project({
230
+ useInMemoryFileSystem: true
231
+ });
232
+ const sourceFile = project.createSourceFile('payload.config.ts', `import { buildConfig } from 'payload'
233
+
234
+ export default buildConfig({
235
+ collections: []
236
+ })`);
237
+ const result = removeSharp(sourceFile);
238
+ expect(result.success).toBe(true);
239
+ expect(result.modified).toBe(false);
240
+ });
241
+ });
242
+ describe('configurePayloadConfig', ()=>{
243
+ let tempDir;
244
+ beforeEach(()=>{
245
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'payload-test-'));
246
+ });
247
+ afterEach(()=>{
248
+ fs.rmSync(tempDir, {
249
+ recursive: true,
250
+ force: true
251
+ });
252
+ });
253
+ it('applies all transformations in one call (db + storage)', async ()=>{
254
+ const filePath = path.join(tempDir, 'payload.config.ts');
255
+ fs.writeFileSync(filePath, `import { buildConfig } from 'payload'
256
+
257
+ export default buildConfig({
258
+ collections: []
259
+ })`);
260
+ const { configurePayloadConfig } = await import('./payload-config');
261
+ const result = await configurePayloadConfig(filePath, {
262
+ db: {
263
+ type: 'postgres',
264
+ envVarName: 'DATABASE_URL'
265
+ },
266
+ storage: 'vercelBlobStorage'
267
+ });
268
+ expect(result.success).toBe(true);
269
+ const content = fs.readFileSync(filePath, 'utf-8');
270
+ expect(content).toContain('postgresAdapter');
271
+ expect(content).toContain('vercelBlobStorage');
272
+ expect(content).toContain('DATABASE_URL');
273
+ });
274
+ it('applies db transformation only', async ()=>{
275
+ const filePath = path.join(tempDir, 'payload.config.ts');
276
+ fs.writeFileSync(filePath, `import { buildConfig } from 'payload'
277
+
278
+ export default buildConfig({
279
+ collections: []
280
+ })`);
281
+ const { configurePayloadConfig } = await import('./payload-config');
282
+ const result = await configurePayloadConfig(filePath, {
283
+ db: {
284
+ type: 'mongodb',
285
+ envVarName: 'MONGO_URL'
286
+ }
287
+ });
288
+ expect(result.success).toBe(true);
289
+ const content = fs.readFileSync(filePath, 'utf-8');
290
+ expect(content).toContain('mongooseAdapter');
291
+ expect(content).toContain('MONGO_URL');
292
+ });
293
+ it('applies removeSharp transformation', async ()=>{
294
+ const filePath = path.join(tempDir, 'payload.config.ts');
295
+ fs.writeFileSync(filePath, `import { buildConfig } from 'payload'
296
+ import sharp from 'sharp'
297
+ import { mongooseAdapter } from '@payloadcms/db-mongodb'
298
+
299
+ export default buildConfig({
300
+ db: mongooseAdapter({ url: '' }),
301
+ sharp,
302
+ collections: []
303
+ })`);
304
+ const { configurePayloadConfig } = await import('./payload-config');
305
+ const result = await configurePayloadConfig(filePath, {
306
+ removeSharp: true
307
+ });
308
+ expect(result.success).toBe(true);
309
+ const content = fs.readFileSync(filePath, 'utf-8');
310
+ expect(content).not.toContain("import sharp from 'sharp'");
311
+ expect(content).not.toContain('sharp,');
312
+ });
313
+ it('handles transformation errors gracefully', async ()=>{
314
+ const filePath = path.join(tempDir, 'payload.config.ts');
315
+ fs.writeFileSync(filePath, `export default {}`);
316
+ const { configurePayloadConfig } = await import('./payload-config');
317
+ const result = await configurePayloadConfig(filePath, {
318
+ db: {
319
+ type: 'postgres',
320
+ envVarName: 'DATABASE_URL'
321
+ }
322
+ });
323
+ expect(result.success).toBe(false);
324
+ expect(result.error?.userMessage).toContain('buildConfig');
325
+ });
326
+ it('handles file not found error', async ()=>{
327
+ const filePath = path.join(tempDir, 'nonexistent.ts');
328
+ const { configurePayloadConfig } = await import('./payload-config');
329
+ const result = await configurePayloadConfig(filePath, {
330
+ db: {
331
+ type: 'postgres',
332
+ envVarName: 'DATABASE_URL'
333
+ }
334
+ });
335
+ expect(result.success).toBe(false);
336
+ expect(result.error).toBeDefined();
337
+ });
338
+ it('replaces adapter in config file', async ()=>{
339
+ const filePath = path.join(tempDir, 'payload.config.ts');
340
+ fs.writeFileSync(filePath, `import { buildConfig } from 'payload'
341
+ import { mongooseAdapter } from '@payloadcms/db-mongodb'
342
+
343
+ export default buildConfig({
344
+ db: mongooseAdapter({ url: process.env.DATABASE_URI || '' }),
345
+ collections: []
346
+ })`);
347
+ const { configurePayloadConfig } = await import('./payload-config');
348
+ const result = await configurePayloadConfig(filePath, {
349
+ db: {
350
+ type: 'postgres',
351
+ envVarName: 'DATABASE_URL'
352
+ }
353
+ });
354
+ expect(result.success).toBe(true);
355
+ // Verify config was updated
356
+ const content = fs.readFileSync(filePath, 'utf-8');
357
+ expect(content).toContain('postgresAdapter');
358
+ expect(content).toContain('@payloadcms/db-postgres');
359
+ expect(content).not.toContain('mongooseAdapter');
360
+ expect(content).not.toContain('@payloadcms/db-mongodb');
361
+ });
362
+ });
363
+
364
+ //# sourceMappingURL=payload-config.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/ast/payload-config.spec.ts"],"sourcesContent":["import { Project } from 'ts-morph'\nimport {\n addDatabaseAdapter,\n addStorageAdapter,\n detectPayloadConfigStructure,\n removeSharp,\n} from './payload-config'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport * as os from 'os'\n\ndescribe('detectPayloadConfigStructure', () => {\n it('successfully detects buildConfig call', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n db: mongooseAdapter({ url: '' }),\n plugins: []\n})`,\n )\n\n const result = detectPayloadConfigStructure(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.structures?.buildConfigCall).toBeDefined()\n })\n\n it('fails when buildConfig call not found', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile('payload.config.ts', `export default {}`)\n\n const result = detectPayloadConfigStructure(sourceFile)\n\n expect(result.success).toBe(false)\n expect(result.error?.userMessage).toContain('buildConfig')\n expect(result.error?.technicalDetails).toContain('CallExpression')\n })\n\n it('detects buildConfig in variable declaration', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nconst config = buildConfig({\n db: mongooseAdapter({ url: '' })\n})\n\nexport default config`,\n )\n\n const result = detectPayloadConfigStructure(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.structures?.buildConfigCall).toBeDefined()\n })\n\n it('detects import alias edge case', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig as createConfig } from 'payload'\nimport { mongooseAdapter } from '@payloadcms/db-mongodb'\n\nexport default createConfig({\n db: mongooseAdapter({ url: '' }),\n collections: [],\n})`,\n )\n\n const result = detectPayloadConfigStructure(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.edgeCases?.hasImportAlias).toBe(true)\n expect(result.structures?.buildConfigCall).toBeDefined()\n })\n\n it('detects multiple buildConfig calls', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nconst helper = buildConfig({ collections: [] })\n\nexport default buildConfig({\n collections: [],\n})`,\n )\n\n const result = detectPayloadConfigStructure(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.edgeCases?.multipleBuildConfigCalls).toBe(true)\n })\n\n it('detects other Payload imports', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig, CollectionConfig } from 'payload'\n\nexport default buildConfig({\n collections: [],\n})`,\n )\n\n const result = detectPayloadConfigStructure(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.edgeCases?.hasOtherPayloadImports).toBe(true)\n })\n})\n\ndescribe('addDatabaseAdapter', () => {\n it.each([\n {\n adapter: 'mongodb' as const,\n adapterName: 'mongooseAdapter',\n packageName: '@payloadcms/db-mongodb',\n },\n {\n adapter: 'postgres' as const,\n adapterName: 'postgresAdapter',\n packageName: '@payloadcms/db-postgres',\n },\n ])('adds $adapter adapter with import and config', ({ adapter, adapterName, packageName }) => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n collections: []\n})`,\n )\n\n const result = addDatabaseAdapter({\n sourceFile,\n adapter,\n envVarName: 'DATABASE_URI',\n })\n\n expect(result.success).toBe(true)\n expect(result.modified).toBe(true)\n expect(result.modifications.length).toBeGreaterThan(0)\n\n const text = sourceFile.getText()\n expect(text).toMatch(\n new RegExp(`import.*${adapterName}.*from.*${packageName.replace('/', '\\\\/')}`),\n )\n expect(text).toContain(`db: ${adapterName}`)\n expect(text).toContain('process.env.DATABASE_URI')\n })\n\n it('replaces existing db adapter', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\nimport { mongooseAdapter } from '@payloadcms/db-mongodb'\n\nexport default buildConfig({\n db: mongooseAdapter({ url: '' }),\n collections: []\n})`,\n )\n\n const result = addDatabaseAdapter({\n sourceFile,\n adapter: 'postgres',\n envVarName: 'DATABASE_URI',\n })\n\n expect(result.success).toBe(true)\n const text = sourceFile.getText()\n expect(text).toMatch(/import.*postgresAdapter.*from.*@payloadcms\\/db-postgres/)\n expect(text).toContain('db: postgresAdapter')\n expect(text).not.toContain('mongooseAdapter')\n expect(text).not.toContain('@payloadcms/db-mongodb')\n })\n})\n\ndescribe('addStorageAdapter', () => {\n it('adds vercelBlobStorage adapter to plugins array', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n plugins: []\n})`,\n )\n\n const result = addStorageAdapter({ sourceFile, adapter: 'vercelBlobStorage' })\n\n expect(result.success).toBe(true)\n expect(result.modified).toBe(true)\n const text = sourceFile.getText()\n expect(text).toMatch(/import.*vercelBlobStorage.*from.*@payloadcms\\/storage-vercel-blob/)\n expect(text).toContain('vercelBlobStorage(')\n })\n\n it('creates plugins array if missing', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n collections: []\n})`,\n )\n\n const result = addStorageAdapter({ sourceFile, adapter: 'r2Storage' })\n\n expect(result.success).toBe(true)\n const text = sourceFile.getText()\n expect(text).toContain('plugins: [')\n expect(text).toContain('r2Storage(')\n })\n\n it('adds to existing plugins array', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n plugins: [\n someOtherPlugin()\n ]\n})`,\n )\n\n const result = addStorageAdapter({ sourceFile, adapter: 's3Storage' })\n\n expect(result.success).toBe(true)\n const text = sourceFile.getText()\n expect(text).toContain('someOtherPlugin()')\n expect(text).toContain('s3Storage(')\n })\n})\n\ndescribe('removeSharp', () => {\n it('removes sharp import and property', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\nimport sharp from 'sharp'\n\nexport default buildConfig({\n sharp,\n collections: []\n})`,\n )\n\n const result = removeSharp(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.modified).toBe(true)\n expect(result.modifications.length).toBeGreaterThan(0)\n const text = sourceFile.getText()\n expect(text).not.toContain(\"import sharp from 'sharp'\")\n expect(text).not.toContain('sharp,')\n })\n\n it('does nothing if sharp not present', () => {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile(\n 'payload.config.ts',\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n collections: []\n})`,\n )\n\n const result = removeSharp(sourceFile)\n\n expect(result.success).toBe(true)\n expect(result.modified).toBe(false)\n })\n})\n\ndescribe('configurePayloadConfig', () => {\n let tempDir: string\n\n beforeEach(() => {\n tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'payload-test-'))\n })\n\n afterEach(() => {\n fs.rmSync(tempDir, { recursive: true, force: true })\n })\n\n it('applies all transformations in one call (db + storage)', async () => {\n const filePath = path.join(tempDir, 'payload.config.ts')\n fs.writeFileSync(\n filePath,\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n collections: []\n})`,\n )\n\n const { configurePayloadConfig } = await import('./payload-config')\n const result = await configurePayloadConfig(filePath, {\n db: { type: 'postgres', envVarName: 'DATABASE_URL' },\n storage: 'vercelBlobStorage',\n })\n\n expect(result.success).toBe(true)\n\n const content = fs.readFileSync(filePath, 'utf-8')\n expect(content).toContain('postgresAdapter')\n expect(content).toContain('vercelBlobStorage')\n expect(content).toContain('DATABASE_URL')\n })\n\n it('applies db transformation only', async () => {\n const filePath = path.join(tempDir, 'payload.config.ts')\n fs.writeFileSync(\n filePath,\n `import { buildConfig } from 'payload'\n\nexport default buildConfig({\n collections: []\n})`,\n )\n\n const { configurePayloadConfig } = await import('./payload-config')\n const result = await configurePayloadConfig(filePath, {\n db: { type: 'mongodb', envVarName: 'MONGO_URL' },\n })\n\n expect(result.success).toBe(true)\n\n const content = fs.readFileSync(filePath, 'utf-8')\n expect(content).toContain('mongooseAdapter')\n expect(content).toContain('MONGO_URL')\n })\n\n it('applies removeSharp transformation', async () => {\n const filePath = path.join(tempDir, 'payload.config.ts')\n fs.writeFileSync(\n filePath,\n `import { buildConfig } from 'payload'\nimport sharp from 'sharp'\nimport { mongooseAdapter } from '@payloadcms/db-mongodb'\n\nexport default buildConfig({\n db: mongooseAdapter({ url: '' }),\n sharp,\n collections: []\n})`,\n )\n\n const { configurePayloadConfig } = await import('./payload-config')\n const result = await configurePayloadConfig(filePath, {\n removeSharp: true,\n })\n\n expect(result.success).toBe(true)\n\n const content = fs.readFileSync(filePath, 'utf-8')\n expect(content).not.toContain(\"import sharp from 'sharp'\")\n expect(content).not.toContain('sharp,')\n })\n\n it('handles transformation errors gracefully', async () => {\n const filePath = path.join(tempDir, 'payload.config.ts')\n fs.writeFileSync(\n filePath,\n `export default {}`, // Invalid structure\n )\n\n const { configurePayloadConfig } = await import('./payload-config')\n const result = await configurePayloadConfig(filePath, {\n db: { type: 'postgres', envVarName: 'DATABASE_URL' },\n })\n\n expect(result.success).toBe(false)\n expect(result.error?.userMessage).toContain('buildConfig')\n })\n\n it('handles file not found error', async () => {\n const filePath = path.join(tempDir, 'nonexistent.ts')\n\n const { configurePayloadConfig } = await import('./payload-config')\n const result = await configurePayloadConfig(filePath, {\n db: { type: 'postgres', envVarName: 'DATABASE_URL' },\n })\n\n expect(result.success).toBe(false)\n expect(result.error).toBeDefined()\n })\n\n it('replaces adapter in config file', async () => {\n const filePath = path.join(tempDir, 'payload.config.ts')\n fs.writeFileSync(\n filePath,\n `import { buildConfig } from 'payload'\nimport { mongooseAdapter } from '@payloadcms/db-mongodb'\n\nexport default buildConfig({\n db: mongooseAdapter({ url: process.env.DATABASE_URI || '' }),\n collections: []\n})`,\n )\n\n const { configurePayloadConfig } = await import('./payload-config')\n const result = await configurePayloadConfig(filePath, {\n db: { type: 'postgres', envVarName: 'DATABASE_URL' },\n })\n\n expect(result.success).toBe(true)\n\n // Verify config was updated\n const content = fs.readFileSync(filePath, 'utf-8')\n expect(content).toContain('postgresAdapter')\n expect(content).toContain('@payloadcms/db-postgres')\n expect(content).not.toContain('mongooseAdapter')\n expect(content).not.toContain('@payloadcms/db-mongodb')\n })\n})\n"],"names":["Project","addDatabaseAdapter","addStorageAdapter","detectPayloadConfigStructure","removeSharp","fs","path","os","describe","it","project","useInMemoryFileSystem","sourceFile","createSourceFile","result","expect","success","toBe","structures","buildConfigCall","toBeDefined","error","userMessage","toContain","technicalDetails","edgeCases","hasImportAlias","multipleBuildConfigCalls","hasOtherPayloadImports","each","adapter","adapterName","packageName","envVarName","modified","modifications","length","toBeGreaterThan","text","getText","toMatch","RegExp","replace","not","tempDir","beforeEach","mkdtempSync","join","tmpdir","afterEach","rmSync","recursive","force","filePath","writeFileSync","configurePayloadConfig","db","type","storage","content","readFileSync"],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import type { ArrayLiteralExpression, CallExpression, ImportDeclaration, PropertyAssignment, SourceFile } from 'ts-morph';
2
+ export type ImportRemovalResult = {
3
+ removedIndex?: number;
4
+ sourceFile: SourceFile;
5
+ };
6
+ export type NamedImportRemovalResult = {
7
+ fullyRemoved: boolean;
8
+ index?: number;
9
+ sourceFile: SourceFile;
10
+ };
11
+ export type ImportCleanupResult = {
12
+ kept: string[];
13
+ removed: string[];
14
+ sourceFile: SourceFile;
15
+ };
16
+ export type DetectionError = {
17
+ debugInfo?: Record<string, unknown>;
18
+ technicalDetails: string;
19
+ userMessage: string;
20
+ };
21
+ export type PayloadConfigStructures = {
22
+ buildConfigCall: CallExpression;
23
+ dbProperty?: PropertyAssignment;
24
+ importStatements: ImportDeclaration[];
25
+ pluginsArray?: ArrayLiteralExpression;
26
+ };
27
+ /**
28
+ * Detection result with edge case tracking and import source information
29
+ */
30
+ export type DetectionResult = {
31
+ /** Edge case flags */
32
+ edgeCases?: {
33
+ /** Import uses an alias (e.g., import { buildConfig as bc }) */
34
+ hasImportAlias: boolean;
35
+ /** Other Payload imports exist (e.g., CollectionConfig) */
36
+ hasOtherPayloadImports: boolean;
37
+ /** Multiple buildConfig calls found in file */
38
+ multipleBuildConfigCalls: boolean;
39
+ /** Needs manual intervention (can't be automatically handled) */
40
+ needsManualIntervention: boolean;
41
+ };
42
+ error?: DetectionError;
43
+ /** Import source tracking */
44
+ importSources?: {
45
+ /** Current database adapter import info */
46
+ dbAdapter?: {
47
+ hasOtherImports: boolean;
48
+ importDeclaration: ImportDeclaration;
49
+ packageName: string;
50
+ };
51
+ /** Current storage adapter import info */
52
+ storageAdapters?: Array<{
53
+ hasOtherImports: boolean;
54
+ importDeclaration: ImportDeclaration;
55
+ packageName: string;
56
+ }>;
57
+ };
58
+ /** Source file reference */
59
+ sourceFile?: SourceFile;
60
+ /** Detected structures */
61
+ structures?: PayloadConfigStructures;
62
+ success: boolean;
63
+ };
64
+ /**
65
+ * Tracks a single modification made to the AST
66
+ */
67
+ export type Modification = {
68
+ description: string;
69
+ location?: {
70
+ column: number;
71
+ line: number;
72
+ };
73
+ type: 'function-renamed' | 'import-added' | 'import-modified' | 'import-removed' | 'property-added' | 'property-removed';
74
+ };
75
+ /**
76
+ * Result of transformation operations
77
+ */
78
+ export type TransformationResult = {
79
+ error?: DetectionError;
80
+ modifications: Modification[];
81
+ modified: boolean;
82
+ success: boolean;
83
+ warnings?: string[];
84
+ };
85
+ /**
86
+ * Final result after writing to disk
87
+ */
88
+ export type ModificationResult = {
89
+ error?: DetectionError;
90
+ filePath: string;
91
+ formatted?: boolean;
92
+ modifications: Modification[];
93
+ success: boolean;
94
+ warnings?: string[];
95
+ };
96
+ export type DatabaseAdapter = (typeof ALL_DATABASE_ADAPTERS)[number];
97
+ export declare const ALL_DATABASE_ADAPTERS: readonly ["mongodb", "postgres", "sqlite", "vercel-postgres", "d1-sqlite"];
98
+ export declare const ALL_STORAGE_ADAPTERS: readonly ["azureStorage", "gcsStorage", "localDisk", "r2Storage", "s3Storage", "uploadthingStorage", "vercelBlobStorage"];
99
+ export type StorageAdapter = (typeof ALL_STORAGE_ADAPTERS)[number];
100
+ export type TransformOptions = {
101
+ databaseAdapter?: {
102
+ envVarName?: string;
103
+ type: DatabaseAdapter;
104
+ };
105
+ removeSharp?: boolean;
106
+ storageAdapter?: {
107
+ type: StorageAdapter;
108
+ };
109
+ };
110
+ export type WriteOptions = {
111
+ formatWithPrettier?: boolean;
112
+ validateStructure?: boolean;
113
+ };
114
+ export type WriteResult = {
115
+ error?: DetectionError;
116
+ success: boolean;
117
+ };
118
+ export type ConfigureOptions = {
119
+ db?: {
120
+ envVarName?: string;
121
+ type: DatabaseAdapter;
122
+ };
123
+ removeSharp?: boolean;
124
+ storage?: StorageAdapter;
125
+ } & WriteOptions;
126
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/ast/types.ts"],"names":[],"mappings":"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"}