pocketbase-zod-schema 0.1.2

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 (94) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +167 -0
  4. package/dist/cli/index.cjs +3383 -0
  5. package/dist/cli/index.cjs.map +1 -0
  6. package/dist/cli/index.d.cts +30 -0
  7. package/dist/cli/index.d.ts +30 -0
  8. package/dist/cli/index.js +3331 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/cli/migrate.cjs +3380 -0
  11. package/dist/cli/migrate.cjs.map +1 -0
  12. package/dist/cli/migrate.d.cts +1 -0
  13. package/dist/cli/migrate.d.ts +1 -0
  14. package/dist/cli/migrate.js +3353 -0
  15. package/dist/cli/migrate.js.map +1 -0
  16. package/dist/cli/utils/index.cjs +540 -0
  17. package/dist/cli/utils/index.cjs.map +1 -0
  18. package/dist/cli/utils/index.d.cts +232 -0
  19. package/dist/cli/utils/index.d.ts +232 -0
  20. package/dist/cli/utils/index.js +487 -0
  21. package/dist/cli/utils/index.js.map +1 -0
  22. package/dist/enums.cjs +19 -0
  23. package/dist/enums.cjs.map +1 -0
  24. package/dist/enums.d.cts +6 -0
  25. package/dist/enums.d.ts +6 -0
  26. package/dist/enums.js +17 -0
  27. package/dist/enums.js.map +1 -0
  28. package/dist/index.cjs +4900 -0
  29. package/dist/index.cjs.map +1 -0
  30. package/dist/index.d.cts +18 -0
  31. package/dist/index.d.ts +18 -0
  32. package/dist/index.js +4726 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/migration/analyzer.cjs +1267 -0
  35. package/dist/migration/analyzer.cjs.map +1 -0
  36. package/dist/migration/analyzer.d.cts +186 -0
  37. package/dist/migration/analyzer.d.ts +186 -0
  38. package/dist/migration/analyzer.js +1232 -0
  39. package/dist/migration/analyzer.js.map +1 -0
  40. package/dist/migration/diff.cjs +557 -0
  41. package/dist/migration/diff.cjs.map +1 -0
  42. package/dist/migration/diff.d.cts +291 -0
  43. package/dist/migration/diff.d.ts +291 -0
  44. package/dist/migration/diff.js +534 -0
  45. package/dist/migration/diff.js.map +1 -0
  46. package/dist/migration/generator.cjs +778 -0
  47. package/dist/migration/generator.cjs.map +1 -0
  48. package/dist/migration/generator.d.cts +225 -0
  49. package/dist/migration/generator.d.ts +225 -0
  50. package/dist/migration/generator.js +737 -0
  51. package/dist/migration/generator.js.map +1 -0
  52. package/dist/migration/index.cjs +3390 -0
  53. package/dist/migration/index.cjs.map +1 -0
  54. package/dist/migration/index.d.cts +103 -0
  55. package/dist/migration/index.d.ts +103 -0
  56. package/dist/migration/index.js +3265 -0
  57. package/dist/migration/index.js.map +1 -0
  58. package/dist/migration/snapshot.cjs +609 -0
  59. package/dist/migration/snapshot.cjs.map +1 -0
  60. package/dist/migration/snapshot.d.cts +167 -0
  61. package/dist/migration/snapshot.d.ts +167 -0
  62. package/dist/migration/snapshot.js +575 -0
  63. package/dist/migration/snapshot.js.map +1 -0
  64. package/dist/migration/utils/index.cjs +672 -0
  65. package/dist/migration/utils/index.cjs.map +1 -0
  66. package/dist/migration/utils/index.d.cts +207 -0
  67. package/dist/migration/utils/index.d.ts +207 -0
  68. package/dist/migration/utils/index.js +641 -0
  69. package/dist/migration/utils/index.js.map +1 -0
  70. package/dist/mutator.cjs +427 -0
  71. package/dist/mutator.cjs.map +1 -0
  72. package/dist/mutator.d.cts +190 -0
  73. package/dist/mutator.d.ts +190 -0
  74. package/dist/mutator.js +425 -0
  75. package/dist/mutator.js.map +1 -0
  76. package/dist/permissions-ZHafVSIx.d.cts +71 -0
  77. package/dist/permissions-ZHafVSIx.d.ts +71 -0
  78. package/dist/schema.cjs +430 -0
  79. package/dist/schema.cjs.map +1 -0
  80. package/dist/schema.d.cts +316 -0
  81. package/dist/schema.d.ts +316 -0
  82. package/dist/schema.js +396 -0
  83. package/dist/schema.js.map +1 -0
  84. package/dist/types-BbTgmg6H.d.cts +91 -0
  85. package/dist/types-z1Dkjg8m.d.ts +91 -0
  86. package/dist/types.cjs +4 -0
  87. package/dist/types.cjs.map +1 -0
  88. package/dist/types.d.cts +14 -0
  89. package/dist/types.d.ts +14 -0
  90. package/dist/types.js +3 -0
  91. package/dist/types.js.map +1 -0
  92. package/dist/user-jS1aYoeD.d.cts +123 -0
  93. package/dist/user-jS1aYoeD.d.ts +123 -0
  94. package/package.json +165 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/migration/errors.ts","../../src/schema/permission-templates.ts","../../src/migration/rule-validator.ts","../../src/migration/permission-analyzer.ts","../../src/migration/utils/pluralize.ts","../../src/migration/utils/relation-detector.ts","../../src/migration/utils/type-mapper.ts","../../src/migration/analyzer.ts"],"names":["path","isAuthCollection","z","ext"],"mappings":"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","file":"analyzer.js","sourcesContent":["/**\n * Custom error classes for migration tool\n * Provides specific error types for better error handling and user feedback\n */\n\n/**\n * Base error class for all migration-related errors\n */\nexport class MigrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"MigrationError\";\n Object.setPrototypeOf(this, MigrationError.prototype);\n }\n}\n\n/**\n * Error thrown when schema parsing fails\n * Used when Zod schemas cannot be parsed or are invalid\n */\nexport class SchemaParsingError extends MigrationError {\n public readonly filePath?: string;\n public readonly originalError?: Error;\n\n constructor(message: string, filePath?: string, originalError?: Error) {\n super(message);\n this.name = \"SchemaParsingError\";\n this.filePath = filePath;\n this.originalError = originalError;\n Object.setPrototypeOf(this, SchemaParsingError.prototype);\n }\n\n /**\n * Creates a formatted error message with file path and original error details\n */\n public getDetailedMessage(): string {\n const parts: string[] = [this.message];\n\n if (this.filePath) {\n parts.push(`\\nFile: ${this.filePath}`);\n }\n\n if (this.originalError) {\n parts.push(`\\nCause: ${this.originalError.message}`);\n }\n\n return parts.join(\"\");\n }\n}\n\n/**\n * Error thrown when snapshot operations fail\n * Used for snapshot file read/write/parse errors\n */\nexport class SnapshotError extends MigrationError {\n public readonly snapshotPath?: string;\n public readonly operation?: \"read\" | \"write\" | \"parse\" | \"validate\";\n public readonly originalError?: Error;\n\n constructor(\n message: string,\n snapshotPath?: string,\n operation?: \"read\" | \"write\" | \"parse\" | \"validate\",\n originalError?: Error\n ) {\n super(message);\n this.name = \"SnapshotError\";\n this.snapshotPath = snapshotPath;\n this.operation = operation;\n this.originalError = originalError;\n Object.setPrototypeOf(this, SnapshotError.prototype);\n }\n\n /**\n * Creates a formatted error message with snapshot path and operation details\n */\n public getDetailedMessage(): string {\n const parts: string[] = [this.message];\n\n if (this.operation) {\n parts.push(`\\nOperation: ${this.operation}`);\n }\n\n if (this.snapshotPath) {\n parts.push(`\\nSnapshot: ${this.snapshotPath}`);\n }\n\n if (this.originalError) {\n parts.push(`\\nCause: ${this.originalError.message}`);\n }\n\n return parts.join(\"\");\n }\n}\n\n/**\n * Error thrown when migration file generation fails\n * Used when migration files cannot be created or written\n */\nexport class MigrationGenerationError extends MigrationError {\n public readonly migrationPath?: string;\n public readonly originalError?: Error;\n\n constructor(message: string, migrationPath?: string, originalError?: Error) {\n super(message);\n this.name = \"MigrationGenerationError\";\n this.migrationPath = migrationPath;\n this.originalError = originalError;\n Object.setPrototypeOf(this, MigrationGenerationError.prototype);\n }\n\n /**\n * Creates a formatted error message with migration path and original error details\n */\n public getDetailedMessage(): string {\n const parts: string[] = [this.message];\n\n if (this.migrationPath) {\n parts.push(`\\nMigration: ${this.migrationPath}`);\n }\n\n if (this.originalError) {\n parts.push(`\\nCause: ${this.originalError.message}`);\n }\n\n return parts.join(\"\");\n }\n}\n\n/**\n * Error thrown when file system operations fail\n * Used for directory creation, file permissions, disk space issues\n */\nexport class FileSystemError extends MigrationError {\n public readonly path?: string;\n public readonly operation?: \"read\" | \"write\" | \"create\" | \"delete\" | \"access\";\n public readonly code?: string;\n public readonly originalError?: Error;\n\n constructor(\n message: string,\n path?: string,\n operation?: \"read\" | \"write\" | \"create\" | \"delete\" | \"access\",\n code?: string,\n originalError?: Error\n ) {\n super(message);\n this.name = \"FileSystemError\";\n this.path = path;\n this.operation = operation;\n this.code = code;\n this.originalError = originalError;\n Object.setPrototypeOf(this, FileSystemError.prototype);\n }\n\n /**\n * Creates a formatted error message with path, operation, and error code details\n */\n public getDetailedMessage(): string {\n const parts: string[] = [this.message];\n\n if (this.operation) {\n parts.push(`\\nOperation: ${this.operation}`);\n }\n\n if (this.path) {\n parts.push(`\\nPath: ${this.path}`);\n }\n\n if (this.code) {\n parts.push(`\\nError Code: ${this.code}`);\n }\n\n if (this.originalError) {\n parts.push(`\\nCause: ${this.originalError.message}`);\n }\n\n return parts.join(\"\");\n }\n}\n\n/**\n * Error thrown when configuration is invalid\n * Used for configuration file parsing, validation, and path resolution errors\n */\nexport class ConfigurationError extends MigrationError {\n public readonly configPath?: string;\n public readonly invalidFields?: string[];\n public readonly originalError?: Error;\n\n constructor(message: string, configPath?: string, invalidFields?: string[], originalError?: Error) {\n super(message);\n this.name = \"ConfigurationError\";\n this.configPath = configPath;\n this.invalidFields = invalidFields;\n this.originalError = originalError;\n Object.setPrototypeOf(this, ConfigurationError.prototype);\n }\n\n /**\n * Creates a formatted error message with configuration details\n */\n public getDetailedMessage(): string {\n const parts: string[] = [this.message];\n\n if (this.configPath) {\n parts.push(`\\nConfiguration File: ${this.configPath}`);\n }\n\n if (this.invalidFields && this.invalidFields.length > 0) {\n parts.push(`\\nInvalid Fields: ${this.invalidFields.join(\", \")}`);\n }\n\n if (this.originalError) {\n parts.push(`\\nCause: ${this.originalError.message}`);\n }\n\n return parts.join(\"\");\n }\n}\n\n/**\n * Error thrown when CLI command usage is incorrect\n * Used for invalid arguments, missing required options, etc.\n */\nexport class CLIUsageError extends MigrationError {\n public readonly command?: string;\n public readonly suggestion?: string;\n\n constructor(message: string, command?: string, suggestion?: string) {\n super(message);\n this.name = \"CLIUsageError\";\n this.command = command;\n this.suggestion = suggestion;\n Object.setPrototypeOf(this, CLIUsageError.prototype);\n }\n\n /**\n * Creates a formatted error message with usage suggestions\n */\n public getDetailedMessage(): string {\n const parts: string[] = [this.message];\n\n if (this.command) {\n parts.push(`\\nCommand: ${this.command}`);\n }\n\n if (this.suggestion) {\n parts.push(`\\nSuggestion: ${this.suggestion}`);\n }\n\n return parts.join(\"\");\n }\n}\n","import type { PermissionSchema, PermissionTemplateConfig, RuleExpression } from \"./permissions\";\n\n/**\n * Predefined permission templates for common access control patterns\n */\nexport const PermissionTemplates = {\n /**\n * Public access - anyone can perform all operations\n */\n public: (): PermissionSchema => ({\n listRule: \"\",\n viewRule: \"\",\n createRule: \"\",\n updateRule: \"\",\n deleteRule: \"\",\n }),\n\n /**\n * Authenticated users only - requires valid authentication for all operations\n */\n authenticated: (): PermissionSchema => ({\n listRule: '@request.auth.id != \"\"',\n viewRule: '@request.auth.id != \"\"',\n createRule: '@request.auth.id != \"\"',\n updateRule: '@request.auth.id != \"\"',\n deleteRule: '@request.auth.id != \"\"',\n }),\n\n /**\n * Owner-only access - users can only manage their own records\n * @param ownerField - Name of the relation field pointing to user (default: 'User')\n */\n ownerOnly: (ownerField: string = \"User\"): PermissionSchema => ({\n listRule: `@request.auth.id != \"\" && ${ownerField} = @request.auth.id`,\n viewRule: `@request.auth.id != \"\" && ${ownerField} = @request.auth.id`,\n createRule: '@request.auth.id != \"\"',\n updateRule: `@request.auth.id != \"\" && ${ownerField} = @request.auth.id`,\n deleteRule: `@request.auth.id != \"\" && ${ownerField} = @request.auth.id`,\n }),\n\n /**\n * Admin/superuser only access\n * Assumes a 'role' field exists with 'admin' value\n * @param roleField - Name of the role field (default: 'role')\n */\n adminOnly: (roleField: string = \"role\"): PermissionSchema => ({\n listRule: `@request.auth.id != \"\" && @request.auth.${roleField} = \"admin\"`,\n viewRule: `@request.auth.id != \"\" && @request.auth.${roleField} = \"admin\"`,\n createRule: `@request.auth.id != \"\" && @request.auth.${roleField} = \"admin\"`,\n updateRule: `@request.auth.id != \"\" && @request.auth.${roleField} = \"admin\"`,\n deleteRule: `@request.auth.id != \"\" && @request.auth.${roleField} = \"admin\"`,\n }),\n\n /**\n * Public read, authenticated write\n * Anyone can list/view, but only authenticated users can create/update/delete\n */\n readPublic: (): PermissionSchema => ({\n listRule: \"\",\n viewRule: \"\",\n createRule: '@request.auth.id != \"\"',\n updateRule: '@request.auth.id != \"\"',\n deleteRule: '@request.auth.id != \"\"',\n }),\n\n /**\n * Locked access - only superusers can perform operations\n * All rules are set to null (locked)\n */\n locked: (): PermissionSchema => ({\n listRule: null,\n viewRule: null,\n createRule: null,\n updateRule: null,\n deleteRule: null,\n }),\n\n /**\n * Read-only authenticated - authenticated users can read, no write access\n */\n readOnlyAuthenticated: (): PermissionSchema => ({\n listRule: '@request.auth.id != \"\"',\n viewRule: '@request.auth.id != \"\"',\n createRule: null,\n updateRule: null,\n deleteRule: null,\n }),\n};\n\n/**\n * Resolve template configuration to concrete permission schema\n * @param config - Template configuration or direct permission schema\n * @returns Resolved permission schema with all rules defined\n */\nexport function resolveTemplate(config: PermissionTemplateConfig): PermissionSchema {\n let baseRules: PermissionSchema;\n\n switch (config.template) {\n case \"public\":\n baseRules = PermissionTemplates.public();\n break;\n case \"authenticated\":\n baseRules = PermissionTemplates.authenticated();\n break;\n case \"owner-only\":\n baseRules = PermissionTemplates.ownerOnly(config.ownerField);\n break;\n case \"admin-only\":\n baseRules = PermissionTemplates.adminOnly(config.roleField);\n break;\n case \"read-public\":\n baseRules = PermissionTemplates.readPublic();\n break;\n case \"custom\":\n baseRules = {};\n break;\n default: {\n // Exhaustive check - TypeScript will error if we miss a template type\n const _exhaustive: never = config.template;\n throw new Error(`Unknown template type: ${_exhaustive}`);\n }\n }\n\n // Merge with custom rules if provided (custom rules override template rules)\n return {\n ...baseRules,\n ...config.customRules,\n };\n}\n\n/**\n * Check if a configuration is a template config or direct permission schema\n * @param config - Configuration to check\n * @returns True if it's a template configuration\n */\nexport function isTemplateConfig(\n config: PermissionTemplateConfig | PermissionSchema\n): config is PermissionTemplateConfig {\n return \"template\" in config;\n}\n\n/**\n * Check if a configuration is a direct permission schema\n * @param config - Configuration to check\n * @returns True if it's a direct permission schema\n */\nexport function isPermissionSchema(config: PermissionTemplateConfig | PermissionSchema): config is PermissionSchema {\n return (\n \"listRule\" in config ||\n \"viewRule\" in config ||\n \"createRule\" in config ||\n \"updateRule\" in config ||\n \"deleteRule\" in config ||\n \"manageRule\" in config\n );\n}\n\n/**\n * Validation result for permission configuration\n */\nexport interface PermissionValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/**\n * Validate a permission configuration\n * @param config - Permission configuration to validate\n * @param isAuthCollection - Whether this is for an auth collection\n * @returns Validation result\n */\nexport function validatePermissionConfig(\n config: PermissionTemplateConfig | PermissionSchema,\n isAuthCollection: boolean = false\n): PermissionValidationResult {\n const result: PermissionValidationResult = {\n valid: true,\n errors: [],\n warnings: [],\n };\n\n // Resolve to permission schema\n let permissions: PermissionSchema;\n if (isTemplateConfig(config)) {\n // Validate template config\n if (config.template === \"owner-only\" && !config.ownerField) {\n result.warnings.push(\"owner-only template without ownerField specified - using default 'User'\");\n }\n if (config.template === \"admin-only\" && !config.roleField) {\n result.warnings.push(\"admin-only template without roleField specified - using default 'role'\");\n }\n permissions = resolveTemplate(config);\n } else {\n permissions = config;\n }\n\n // Validate manageRule usage\n if (permissions.manageRule !== undefined && !isAuthCollection) {\n result.errors.push(\"manageRule is only valid for auth collections\");\n result.valid = false;\n }\n\n // Validate rule expressions\n const ruleTypes: (keyof PermissionSchema)[] = [\"listRule\", \"viewRule\", \"createRule\", \"updateRule\", \"deleteRule\"];\n if (isAuthCollection) {\n ruleTypes.push(\"manageRule\");\n }\n\n for (const ruleType of ruleTypes) {\n const rule = permissions[ruleType];\n if (rule !== undefined && rule !== null && rule !== \"\") {\n const ruleValidation = validateRuleExpression(rule);\n if (!ruleValidation.valid) {\n result.errors.push(`${ruleType}: ${ruleValidation.errors.join(\", \")}`);\n result.valid = false;\n }\n result.warnings.push(...ruleValidation.warnings.map((w) => `${ruleType}: ${w}`));\n }\n }\n\n return result;\n}\n\n/**\n * Validate a single rule expression for basic syntax\n * @param expression - Rule expression to validate\n * @returns Validation result\n */\nexport function validateRuleExpression(expression: RuleExpression): PermissionValidationResult {\n const result: PermissionValidationResult = {\n valid: true,\n errors: [],\n warnings: [],\n };\n\n // Null and empty string are always valid\n if (expression === null || expression === \"\") {\n return result;\n }\n\n // Check for balanced parentheses\n let parenCount = 0;\n for (const char of expression) {\n if (char === \"(\") parenCount++;\n if (char === \")\") parenCount--;\n if (parenCount < 0) {\n result.errors.push(\"Unbalanced parentheses\");\n result.valid = false;\n return result;\n }\n }\n if (parenCount !== 0) {\n result.errors.push(\"Unbalanced parentheses\");\n result.valid = false;\n }\n\n // Check for common mistakes\n if (expression.includes(\"==\")) {\n result.warnings.push(\"Use '=' instead of '==' for equality comparison\");\n }\n\n // Check for valid @request references\n const requestRefs = expression.match(/@request\\.[a-zA-Z_][a-zA-Z0-9_.]*/g) || [];\n for (const ref of requestRefs) {\n const isValid =\n ref.startsWith(\"@request.auth.\") ||\n ref === \"@request.method\" ||\n ref === \"@request.context\" ||\n ref.startsWith(\"@request.body.\") ||\n ref.startsWith(\"@request.query.\") ||\n ref.startsWith(\"@request.headers.\");\n\n if (!isValid) {\n result.errors.push(`Invalid @request reference: '${ref}'`);\n result.valid = false;\n }\n }\n\n return result;\n}\n\n/**\n * Create a custom permission schema with type safety\n * @param permissions - Partial permission schema\n * @returns Complete permission schema with null defaults\n */\nexport function createPermissions(permissions: Partial<PermissionSchema>): PermissionSchema {\n return {\n listRule: permissions.listRule ?? null,\n viewRule: permissions.viewRule ?? null,\n createRule: permissions.createRule ?? null,\n updateRule: permissions.updateRule ?? null,\n deleteRule: permissions.deleteRule ?? null,\n manageRule: permissions.manageRule ?? null,\n };\n}\n\n/**\n * Merge multiple permission schemas, with later schemas taking precedence\n * @param schemas - Permission schemas to merge\n * @returns Merged permission schema\n */\nexport function mergePermissions(...schemas: Partial<PermissionSchema>[]): PermissionSchema {\n const merged: PermissionSchema = {\n listRule: null,\n viewRule: null,\n createRule: null,\n updateRule: null,\n deleteRule: null,\n manageRule: null,\n };\n\n for (const schema of schemas) {\n if (schema.listRule !== undefined) merged.listRule = schema.listRule;\n if (schema.viewRule !== undefined) merged.viewRule = schema.viewRule;\n if (schema.createRule !== undefined) merged.createRule = schema.createRule;\n if (schema.updateRule !== undefined) merged.updateRule = schema.updateRule;\n if (schema.deleteRule !== undefined) merged.deleteRule = schema.deleteRule;\n if (schema.manageRule !== undefined) merged.manageRule = schema.manageRule;\n }\n\n return merged;\n}\n","/**\n * Rule validator for PocketBase API rule expressions\n *\n * Validates permission rule expressions against PocketBase syntax rules,\n * including field references, @request references, and basic syntax validation.\n */\n\nimport type { APIRuleType, RuleExpression } from \"../schema/permissions\";\nimport type { FieldDefinition } from \"./types\";\n\n/**\n * Validation result for rule expressions\n */\nexport interface RuleValidationResult {\n /** Whether the rule expression is valid */\n valid: boolean;\n\n /** List of validation errors */\n errors: string[];\n\n /** List of validation warnings */\n warnings: string[];\n\n /** List of field references found in the expression */\n fieldReferences: string[];\n}\n\n/**\n * Rule expression validator\n *\n * Validates PocketBase API rule expressions for:\n * - Field reference existence and validity\n * - @request reference syntax\n * - Basic expression syntax (parentheses, operators)\n * - Auth collection specific rules (manageRule)\n */\nexport class RuleValidator {\n private fields: Map<string, FieldDefinition>;\n private collectionName: string;\n private isAuthCollection: boolean;\n\n constructor(collectionName: string, fields: FieldDefinition[], isAuthCollection: boolean = false) {\n this.collectionName = collectionName;\n this.fields = new Map(fields.map((f) => [f.name, f]));\n this.isAuthCollection = isAuthCollection;\n\n // Add system fields that are always available in PocketBase\n this.addSystemFields();\n }\n\n /**\n * Add system fields that are always available in PocketBase collections\n * These fields are automatically added by PocketBase and can be referenced in rules\n */\n private addSystemFields(): void {\n // Base system fields available in all collections\n const systemFields: FieldDefinition[] = [\n { name: \"id\", type: \"text\", required: true, options: {} },\n { name: \"created\", type: \"date\", required: true, options: {} },\n { name: \"updated\", type: \"date\", required: true, options: {} },\n { name: \"collectionId\", type: \"text\", required: true, options: {} },\n { name: \"collectionName\", type: \"text\", required: true, options: {} },\n ];\n\n // Auth collection specific system fields\n if (this.isAuthCollection) {\n systemFields.push(\n { name: \"email\", type: \"email\", required: true, options: {} },\n { name: \"emailVisibility\", type: \"bool\", required: false, options: {} },\n { name: \"verified\", type: \"bool\", required: false, options: {} },\n { name: \"tokenKey\", type: \"text\", required: true, options: {} },\n { name: \"password\", type: \"text\", required: true, options: {} }\n );\n }\n\n // Add system fields to the fields map (don't overwrite user-defined fields)\n for (const field of systemFields) {\n if (!this.fields.has(field.name)) {\n this.fields.set(field.name, field);\n }\n }\n }\n\n /**\n * Validate a rule expression\n *\n * @param ruleType - The type of rule being validated\n * @param expression - The rule expression to validate\n * @returns Validation result with errors, warnings, and field references\n */\n validate(ruleType: APIRuleType, expression: RuleExpression): RuleValidationResult {\n const result: RuleValidationResult = {\n valid: true,\n errors: [],\n warnings: [],\n fieldReferences: [],\n };\n\n // Null means locked (superuser only) - always valid\n if (expression === null) {\n return result;\n }\n\n // Empty string means public - always valid but warn\n if (expression === \"\") {\n result.warnings.push(`${ruleType} is public - anyone can perform this operation`);\n return result;\n }\n\n // Validate manageRule only for auth collections\n if (ruleType === \"manageRule\" && !this.isAuthCollection) {\n result.valid = false;\n result.errors.push(\"manageRule is only valid for auth collections\");\n return result;\n }\n\n // Extract and validate field references\n const fieldRefs = this.extractFieldReferences(expression);\n result.fieldReferences = fieldRefs;\n\n for (const fieldRef of fieldRefs) {\n this.validateFieldReference(fieldRef, result);\n }\n\n // Validate @request references\n this.validateRequestReferences(expression, result);\n\n // Validate syntax patterns\n this.validateSyntax(expression, result);\n\n return result;\n }\n\n /**\n * Extract field references from expression\n *\n * Matches field names that are not @request references.\n * Handles dot notation for relations: user.email, post.author.name\n *\n * @param expression - The rule expression\n * @returns Array of unique field references\n */\n private extractFieldReferences(expression: string): string[] {\n const refs: string[] = [];\n\n // First, remove string literals and @request references to avoid matching them\n let cleaned = expression.replace(/\"[^\"]*\"/g, '\"\"').replace(/'[^']*'/g, \"''\");\n cleaned = cleaned.replace(/@request\\.[a-zA-Z_][a-zA-Z0-9_.]*/g, \"\");\n\n // Match field names (not starting with @)\n // Handles dot notation for relations: user.email, post.author.name\n const fieldPattern = /(?:^|[^@\\w])([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)(?=[^a-zA-Z0-9_.]|$)/g;\n\n let match;\n while ((match = fieldPattern.exec(cleaned)) !== null) {\n const ref = match[1];\n // Exclude PocketBase keywords and operators\n if (!this.isKeyword(ref)) {\n refs.push(ref);\n }\n }\n\n return [...new Set(refs)]; // Remove duplicates\n }\n\n /**\n * Check if a word is a PocketBase keyword\n *\n * @param word - The word to check\n * @returns True if the word is a keyword\n */\n private isKeyword(word: string): boolean {\n const keywords = [\"true\", \"false\", \"null\", \"AND\", \"OR\", \"NOT\", \"LIKE\", \"IN\"];\n return keywords.includes(word.toUpperCase());\n }\n\n /**\n * Validate a field reference exists in schema\n *\n * Checks if the root field exists and validates relation chains.\n * For nested references, warns about potential issues since we can't\n * validate across collections without loading related schemas.\n *\n * @param fieldRef - The field reference to validate (e.g., \"user\" or \"user.email\")\n * @param result - The validation result to update\n */\n private validateFieldReference(fieldRef: string, result: RuleValidationResult): void {\n const parts = fieldRef.split(\".\");\n const rootField = parts[0];\n\n if (!this.fields.has(rootField)) {\n result.errors.push(`Field '${rootField}' does not exist in collection '${this.collectionName}'`);\n result.valid = false;\n return;\n }\n\n // For nested references, validate relation chain\n if (parts.length > 1) {\n const field = this.fields.get(rootField)!;\n if (field.type !== \"relation\") {\n result.errors.push(`Field '${rootField}' is not a relation field, cannot access nested property '${parts[1]}'`);\n result.valid = false;\n } else {\n // Note: We can't validate nested fields without loading related schemas\n // This would require cross-schema validation\n result.warnings.push(\n `Nested field reference '${fieldRef}' - ensure target collection has field '${parts.slice(1).join(\".\")}'`\n );\n }\n }\n }\n\n /**\n * Validate @request references\n *\n * Checks that @request references follow valid PocketBase patterns:\n * - @request.auth.* - authenticated user data\n * - @request.body.* - request body fields\n * - @request.query.* - query parameters\n * - @request.headers.* - request headers\n * - @request.method - HTTP method\n * - @request.context - execution context\n *\n * @param expression - The rule expression\n * @param result - The validation result to update\n */\n private validateRequestReferences(expression: string, result: RuleValidationResult): void {\n // Find all @request references\n const requestRefs = expression.match(/@request\\.[a-zA-Z_][a-zA-Z0-9_.]*/g) || [];\n\n for (const ref of requestRefs) {\n // Check if the reference starts with a valid pattern\n const isValid =\n ref.startsWith(\"@request.auth.\") ||\n ref === \"@request.method\" ||\n ref === \"@request.context\" ||\n ref.startsWith(\"@request.body.\") ||\n ref.startsWith(\"@request.query.\") ||\n ref.startsWith(\"@request.headers.\");\n\n if (!isValid) {\n result.errors.push(`Invalid @request reference: '${ref}'`);\n result.valid = false;\n }\n }\n }\n\n /**\n * Validate basic syntax patterns\n *\n * Checks for:\n * - Balanced parentheses\n * - Common operator mistakes (== instead of =)\n *\n * @param expression - The rule expression\n * @param result - The validation result to update\n */\n private validateSyntax(expression: string, result: RuleValidationResult): void {\n // Check for balanced parentheses\n let parenCount = 0;\n for (const char of expression) {\n if (char === \"(\") parenCount++;\n if (char === \")\") parenCount--;\n if (parenCount < 0) {\n result.errors.push(\"Unbalanced parentheses in expression\");\n result.valid = false;\n return;\n }\n }\n if (parenCount !== 0) {\n result.errors.push(\"Unbalanced parentheses in expression\");\n result.valid = false;\n }\n\n // Warn about common mistakes\n if (expression.includes(\"==\")) {\n result.warnings.push(\"Use '=' instead of '==' for equality comparison in PocketBase rules\");\n }\n }\n}\n","/**\n * Permission analyzer for extracting and validating permissions from Zod schemas\n *\n * This module provides utilities to:\n * - Extract permission metadata from Zod schema descriptions\n * - Resolve template configurations to concrete permission schemas\n * - Validate permission rules against collection fields\n * - Merge permissions with default values\n */\n\nimport { resolveTemplate } from \"../schema/permission-templates\";\nimport type { APIRuleType, PermissionSchema, PermissionTemplateConfig } from \"../schema/permissions\";\nimport type { RuleValidationResult } from \"./rule-validator\";\nimport { RuleValidator } from \"./rule-validator\";\nimport type { FieldDefinition } from \"./types\";\n\n/**\n * Extract and analyze permissions from schema\n *\n * The PermissionAnalyzer class provides methods to work with permission\n * definitions attached to Zod schemas, including extraction, resolution,\n * validation, and normalization.\n */\nexport class PermissionAnalyzer {\n /**\n * Extract permission metadata from Zod schema description\n *\n * Zod schemas can have permission metadata attached via the describe() method.\n * This method parses the description and extracts the permission configuration.\n *\n * @param schemaDescription - The Zod schema description string\n * @returns Permission schema if found, null otherwise\n *\n * @example\n * ```typescript\n * const analyzer = new PermissionAnalyzer();\n * const permissions = analyzer.extractPermissions(schema.description);\n * ```\n */\n extractPermissions(schemaDescription: string | undefined): PermissionSchema | null {\n if (!schemaDescription) {\n return null;\n }\n\n try {\n const metadata = JSON.parse(schemaDescription);\n if (metadata.permissions) {\n return metadata.permissions;\n }\n } catch {\n // Not JSON or no permissions - this is expected for schemas without permissions\n return null;\n }\n\n return null;\n }\n\n /**\n * Resolve template configuration to concrete rules\n *\n * Takes either a template configuration or a direct permission schema\n * and returns a fully resolved permission schema with all rules defined.\n *\n * If the input is already a permission schema (has rule properties),\n * it's returned as-is. Otherwise, the template is resolved using the\n * template resolver.\n *\n * @param config - Template configuration or direct permission schema\n * @returns Resolved permission schema\n *\n * @example\n * ```typescript\n * const analyzer = new PermissionAnalyzer();\n *\n * // Resolve from template\n * const permissions = analyzer.resolvePermissions({\n * template: 'owner-only',\n * ownerField: 'User'\n * });\n *\n * // Or pass direct schema\n * const permissions = analyzer.resolvePermissions({\n * listRule: '@request.auth.id != \"\"',\n * viewRule: '@request.auth.id != \"\"'\n * });\n * ```\n */\n resolvePermissions(config: PermissionTemplateConfig | PermissionSchema): PermissionSchema {\n // If it's already a permission schema (has rule properties), return as-is\n if (\n \"listRule\" in config ||\n \"viewRule\" in config ||\n \"createRule\" in config ||\n \"updateRule\" in config ||\n \"deleteRule\" in config ||\n \"manageRule\" in config\n ) {\n return config as PermissionSchema;\n }\n\n // Otherwise resolve template\n return resolveTemplate(config as PermissionTemplateConfig);\n }\n\n /**\n * Validate all rules in a permission schema\n *\n * Validates each rule in the permission schema against the collection's\n * field definitions. Returns a map of validation results keyed by rule type.\n *\n * Only validates rules that are defined (not undefined). Undefined rules\n * are treated as null (locked) by default.\n *\n * @param collectionName - Name of the collection being validated\n * @param permissions - Permission schema to validate\n * @param fields - Collection field definitions\n * @param isAuthCollection - Whether this is an auth collection (allows manageRule)\n * @returns Map of validation results by rule type\n *\n * @example\n * ```typescript\n * const analyzer = new PermissionAnalyzer();\n * const results = analyzer.validatePermissions(\n * 'posts',\n * { listRule: '@request.auth.id != \"\"', viewRule: 'author = @request.auth.id' },\n * fields,\n * false\n * );\n *\n * for (const [ruleType, result] of results) {\n * if (!result.valid) {\n * console.error(`${ruleType} validation failed:`, result.errors);\n * }\n * }\n * ```\n */\n validatePermissions(\n collectionName: string,\n permissions: PermissionSchema,\n fields: FieldDefinition[],\n isAuthCollection: boolean = false\n ): Map<APIRuleType, RuleValidationResult> {\n const validator = new RuleValidator(collectionName, fields, isAuthCollection);\n const results = new Map<APIRuleType, RuleValidationResult>();\n\n // Define all possible rule types\n const ruleTypes: APIRuleType[] = [\"listRule\", \"viewRule\", \"createRule\", \"updateRule\", \"deleteRule\"];\n\n // Add manageRule for auth collections\n if (isAuthCollection) {\n ruleTypes.push(\"manageRule\");\n }\n\n // Validate each defined rule\n for (const ruleType of ruleTypes) {\n const expression = permissions[ruleType];\n if (expression !== undefined) {\n results.set(ruleType, validator.validate(ruleType, expression));\n }\n }\n\n return results;\n }\n\n /**\n * Merge permissions with defaults\n *\n * Ensures all rule types have a defined value. Undefined rules are set\n * to null (locked to superusers only), which is the PocketBase default.\n *\n * This is useful when generating migrations to ensure all rules are\n * explicitly set in the collection configuration.\n *\n * @param permissions - Permission schema (may have undefined rules)\n * @returns Permission schema with all rules defined (null if not specified)\n *\n * @example\n * ```typescript\n * const analyzer = new PermissionAnalyzer();\n * const merged = analyzer.mergeWithDefaults({\n * listRule: '@request.auth.id != \"\"'\n * // other rules undefined\n * });\n *\n * // Result:\n * // {\n * // listRule: '@request.auth.id != \"\"',\n * // viewRule: null,\n * // createRule: null,\n * // updateRule: null,\n * // deleteRule: null,\n * // manageRule: null\n * // }\n * ```\n */\n mergeWithDefaults(permissions: PermissionSchema): PermissionSchema {\n return {\n listRule: permissions.listRule ?? null,\n viewRule: permissions.viewRule ?? null,\n createRule: permissions.createRule ?? null,\n updateRule: permissions.updateRule ?? null,\n deleteRule: permissions.deleteRule ?? null,\n manageRule: permissions.manageRule ?? null,\n };\n }\n}\n","/**\n * Collection name pluralization utilities\n */\n\n/**\n * Special case pluralization rules\n * Maps singular forms to their plural forms\n */\nconst SPECIAL_CASES: Record<string, string> = {\n // Common irregular plurals\n person: \"people\",\n Person: \"People\",\n child: \"children\",\n Child: \"Children\",\n man: \"men\",\n Man: \"Men\",\n woman: \"women\",\n Woman: \"Women\",\n tooth: \"teeth\",\n Tooth: \"Teeth\",\n foot: \"feet\",\n Foot: \"Feet\",\n mouse: \"mice\",\n Mouse: \"Mice\",\n goose: \"geese\",\n Goose: \"Geese\",\n\n // Words ending in -y\n category: \"categories\",\n Category: \"Categories\",\n company: \"companies\",\n Company: \"Companies\",\n city: \"cities\",\n City: \"Cities\",\n country: \"countries\",\n Country: \"Countries\",\n story: \"stories\",\n Story: \"Stories\",\n party: \"parties\",\n Party: \"Parties\",\n family: \"families\",\n Family: \"Families\",\n activity: \"activities\",\n Activity: \"Activities\",\n priority: \"priorities\",\n Priority: \"Priorities\",\n\n // Words ending in -f or -fe\n life: \"lives\",\n Life: \"Lives\",\n wife: \"wives\",\n Wife: \"Wives\",\n knife: \"knives\",\n Knife: \"Knives\",\n leaf: \"leaves\",\n Leaf: \"Leaves\",\n shelf: \"shelves\",\n Shelf: \"Shelves\",\n half: \"halves\",\n Half: \"Halves\",\n\n // Words ending in -is\n analysis: \"analyses\",\n Analysis: \"Analyses\",\n basis: \"bases\",\n Basis: \"Bases\",\n crisis: \"crises\",\n Crisis: \"Crises\",\n thesis: \"theses\",\n Thesis: \"Theses\",\n\n // Words ending in -us\n cactus: \"cacti\",\n Cactus: \"Cacti\",\n focus: \"foci\",\n Focus: \"Foci\",\n fungus: \"fungi\",\n Fungus: \"Fungi\",\n nucleus: \"nuclei\",\n Nucleus: \"Nuclei\",\n radius: \"radii\",\n Radius: \"Radii\",\n\n // Words ending in -on\n phenomenon: \"phenomena\",\n Phenomenon: \"Phenomena\",\n criterion: \"criteria\",\n Criterion: \"Criteria\",\n\n // Words ending in -um\n datum: \"data\",\n Datum: \"Data\",\n medium: \"media\",\n Medium: \"Media\",\n curriculum: \"curricula\",\n Curriculum: \"Curricula\",\n\n // Unchanged plurals\n sheep: \"sheep\",\n Sheep: \"Sheep\",\n deer: \"deer\",\n Deer: \"Deer\",\n fish: \"fish\",\n Fish: \"Fish\",\n species: \"species\",\n Species: \"Species\",\n series: \"series\",\n Series: \"Series\",\n};\n\n/**\n * Pluralizes a singular noun to its plural form\n * Handles special cases and common English pluralization rules\n *\n * @param singular - The singular form of the noun\n * @returns The plural form of the noun\n */\nexport function pluralize(singular: string): string {\n // Check special cases first (before checking if already plural)\n if (SPECIAL_CASES[singular]) {\n return SPECIAL_CASES[singular];\n }\n\n // Check if it's already plural (ends with 's' and is longer than 3 chars)\n if (singular.length > 3 && singular.endsWith(\"s\") && !singular.endsWith(\"ss\")) {\n // Could already be plural, return as-is\n return singular;\n }\n\n // Preserve case for the transformation\n const lowerSingular = singular.toLowerCase();\n\n let plural: string;\n\n // Rule 1: Words ending in -s, -ss, -sh, -ch, -x, -z -> add -es\n if (/(?:s|ss|sh|ch|x|z)$/.test(lowerSingular)) {\n plural = singular + \"es\";\n }\n // Rule 2: Words ending in consonant + y -> change y to ies\n else if (/[^aeiou]y$/.test(lowerSingular)) {\n plural = singular.slice(0, -1) + \"ies\";\n }\n // Rule 3: Words ending in consonant + o -> add -es\n else if (/[^aeiou]o$/.test(lowerSingular)) {\n plural = singular + \"es\";\n }\n // Rule 4: Words ending in -f or -fe -> change to -ves\n else if (/fe?$/.test(lowerSingular)) {\n if (lowerSingular.endsWith(\"fe\")) {\n plural = singular.slice(0, -2) + \"ves\";\n } else {\n plural = singular.slice(0, -1) + \"ves\";\n }\n }\n // Rule 5: Default -> add -s\n else {\n plural = singular + \"s\";\n }\n\n return plural;\n}\n\n/**\n * Converts a singular entity name to a collection name\n * This is an alias for pluralize for better semantic clarity\n *\n * @param entityName - The singular entity name (e.g., \"User\", \"Project\")\n * @returns The collection name (e.g., \"Users\", \"Projects\")\n */\nexport function toCollectionName(entityName: string): string {\n return pluralize(entityName);\n}\n\n/**\n * Attempts to singularize a plural noun (reverse of pluralize)\n * Note: This is a best-effort implementation and may not handle all edge cases\n *\n * @param plural - The plural form of the noun\n * @returns The singular form of the noun\n */\nexport function singularize(plural: string): string {\n // Check reverse special cases\n for (const [singular, pluralForm] of Object.entries(SPECIAL_CASES)) {\n if (pluralForm === plural) {\n return singular;\n }\n }\n\n const lower = plural.toLowerCase();\n\n // Rule 1: Words ending in -ies -> change to -y\n if (lower.endsWith(\"ies\") && plural.length > 3) {\n return plural.slice(0, -3) + \"y\";\n }\n\n // Rule 2: Words ending in -ves -> change to -f or -fe\n if (lower.endsWith(\"ves\")) {\n // Try -fe first (more common)\n return plural.slice(0, -3) + \"fe\";\n }\n\n // Rule 3: Words ending in -ses, -shes, -ches, -xes, -zes -> remove -es\n if (/(?:ses|shes|ches|xes|zes)$/.test(lower)) {\n return plural.slice(0, -2);\n }\n\n // Rule 4: Words ending in -s -> remove -s\n if (lower.endsWith(\"s\") && plural.length > 1) {\n return plural.slice(0, -1);\n }\n\n // Default: return as-is\n return plural;\n}\n","/**\n * Relation field detection utilities\n */\n\nimport { z } from \"zod\";\nimport { pluralize } from \"./pluralize\";\n\n/**\n * Detects if a field is a single relation based on naming convention\n * Single relation: field name matches a collection name (e.g., \"User\" -> \"Users\" collection)\n */\nexport function isSingleRelationField(fieldName: string, zodType: z.ZodTypeAny): boolean {\n // Unwrap optional/nullable/default\n let unwrappedType = zodType;\n if (zodType instanceof z.ZodOptional) {\n unwrappedType = zodType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodNullable) {\n unwrappedType = unwrappedType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodDefault) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n // Must be a string type\n if (!(unwrappedType instanceof z.ZodString)) {\n return false;\n }\n\n // Field name should start with uppercase (convention for entity references)\n // and not be a common string field name\n const startsWithUppercase = /^[A-Z]/.test(fieldName);\n\n // Exclude common string fields that start with uppercase\n const commonStringFields = [\"Title\", \"Name\", \"Description\", \"Content\", \"Summary\", \"Status\", \"Type\"];\n const isCommonField = commonStringFields.includes(fieldName);\n\n return startsWithUppercase && !isCommonField;\n}\n\n/**\n * Detects if a field is a multiple relation based on naming convention\n * Multiple relation: field name is an array of strings ending with entity name\n * (e.g., \"SubscriberUsers\" -> \"Users\" collection)\n */\nexport function isMultipleRelationField(fieldName: string, zodType: z.ZodTypeAny): boolean {\n // Unwrap optional/nullable/default\n let unwrappedType = zodType;\n if (zodType instanceof z.ZodOptional) {\n unwrappedType = zodType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodNullable) {\n unwrappedType = unwrappedType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodDefault) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n // Must be an array type\n if (!(unwrappedType instanceof z.ZodArray)) {\n return false;\n }\n\n // Element type must be string\n const elementType = unwrappedType._def.type;\n if (!(elementType instanceof z.ZodString)) {\n return false;\n }\n\n // Field name should contain an uppercase letter (entity reference pattern)\n const hasUppercase = /[A-Z]/.test(fieldName);\n\n return hasUppercase;\n}\n\n/**\n * Resolves the target collection name from a relation field name\n * Examples:\n * - \"User\" -> \"Users\"\n * - \"SubscriberUsers\" -> \"Users\"\n * - \"Author\" -> \"Authors\"\n * - \"Category\" -> \"Categories\"\n */\nexport function resolveTargetCollection(fieldName: string): string {\n // For single relations, the field name is typically the entity name\n // For multiple relations, extract the entity name from the end\n\n // Check if field name ends with a known plural entity name\n // Common patterns: \"SubscriberUsers\", \"RelatedPosts\", \"Tags\"\n\n // Try to find the entity name by looking for uppercase letters\n const matches = fieldName.match(/[A-Z][a-z]+/g);\n\n if (!matches || matches.length === 0) {\n // Fallback: pluralize the entire field name\n return pluralize(fieldName);\n }\n\n // Take the last matched entity name (e.g., \"Users\" from \"SubscriberUsers\")\n const entityName = matches[matches.length - 1];\n\n // Pluralize the entity name to get collection name\n return pluralize(entityName);\n}\n\n/**\n * Detects if a field is any type of relation (single or multiple)\n */\nexport function isRelationField(fieldName: string, zodType: z.ZodTypeAny): boolean {\n return isSingleRelationField(fieldName, zodType) || isMultipleRelationField(fieldName, zodType);\n}\n\n/**\n * Gets the maximum number of relations allowed for a relation field\n * Returns 1 for single relations, or the max constraint for multiple relations\n */\nexport function getMaxSelect(fieldName: string, zodType: z.ZodTypeAny): number {\n if (isSingleRelationField(fieldName, zodType)) {\n return 1;\n }\n\n if (isMultipleRelationField(fieldName, zodType)) {\n // Unwrap to get to the array type\n let unwrappedType = zodType;\n if (zodType instanceof z.ZodOptional) {\n unwrappedType = zodType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodNullable) {\n unwrappedType = unwrappedType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodDefault) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n if (unwrappedType instanceof z.ZodArray) {\n // Access the checks array from the array definition\n const arrayDef = unwrappedType._def;\n if (arrayDef.maxLength) {\n return arrayDef.maxLength.value;\n }\n // Default to 999 for multiple relations without explicit max\n return 999;\n }\n }\n\n return 1;\n}\n\n/**\n * Gets the minimum number of relations required for a relation field\n */\nexport function getMinSelect(fieldName: string, zodType: z.ZodTypeAny): number | undefined {\n if (!isMultipleRelationField(fieldName, zodType)) {\n return undefined;\n }\n\n // Unwrap to get to the array type\n let unwrappedType = zodType;\n if (zodType instanceof z.ZodOptional) {\n unwrappedType = zodType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodNullable) {\n unwrappedType = unwrappedType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodDefault) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n if (unwrappedType instanceof z.ZodArray) {\n // Access the minLength from the array definition\n const arrayDef = unwrappedType._def;\n if (arrayDef.minLength) {\n return arrayDef.minLength.value;\n }\n }\n\n return undefined;\n}\n","/**\n * Zod to PocketBase type mapping utilities\n *\n * This module provides comprehensive mapping between Zod schema types\n * and PocketBase field types, including support for all PocketBase field types:\n * - text, email, url, editor\n * - number, bool\n * - date, autodate\n * - select (single/multiple)\n * - relation (single/multiple)\n * - file (single/multiple)\n * - json\n * - geoPoint\n */\n\nimport { z } from \"zod\";\nimport type { PocketBaseFieldType } from \"../types\";\n\n/**\n * All supported PocketBase field types\n */\nexport const POCKETBASE_FIELD_TYPES: readonly PocketBaseFieldType[] = [\n \"text\",\n \"email\",\n \"url\",\n \"number\",\n \"bool\",\n \"date\",\n \"select\",\n \"relation\",\n \"file\",\n \"json\",\n \"editor\",\n \"geoPoint\",\n \"autodate\",\n] as const;\n\n/**\n * Field type metadata for documentation and validation\n */\nexport interface FieldTypeInfo {\n type: PocketBaseFieldType;\n description: string;\n zodTypes: string[];\n supportsMultiple: boolean;\n}\n\n/**\n * Metadata about each PocketBase field type\n */\nexport const FIELD_TYPE_INFO: Record<PocketBaseFieldType, FieldTypeInfo> = {\n text: {\n type: \"text\",\n description: \"Plain text field\",\n zodTypes: [\"ZodString\"],\n supportsMultiple: false,\n },\n email: {\n type: \"email\",\n description: \"Email address field with validation\",\n zodTypes: [\"ZodString with email()\"],\n supportsMultiple: false,\n },\n url: {\n type: \"url\",\n description: \"URL field with validation\",\n zodTypes: [\"ZodString with url()\"],\n supportsMultiple: false,\n },\n editor: {\n type: \"editor\",\n description: \"Rich text editor field\",\n zodTypes: [\"ZodString\"],\n supportsMultiple: false,\n },\n number: {\n type: \"number\",\n description: \"Numeric field (integer or float)\",\n zodTypes: [\"ZodNumber\"],\n supportsMultiple: false,\n },\n bool: {\n type: \"bool\",\n description: \"Boolean field\",\n zodTypes: [\"ZodBoolean\"],\n supportsMultiple: false,\n },\n date: {\n type: \"date\",\n description: \"Date/datetime field\",\n zodTypes: [\"ZodDate\", \"ZodString with datetime format\"],\n supportsMultiple: false,\n },\n autodate: {\n type: \"autodate\",\n description: \"Auto-managed date field (created/updated)\",\n zodTypes: [\"ZodString\"],\n supportsMultiple: false,\n },\n select: {\n type: \"select\",\n description: \"Single or multiple select from predefined values\",\n zodTypes: [\"ZodEnum\", \"ZodArray<ZodEnum>\"],\n supportsMultiple: true,\n },\n relation: {\n type: \"relation\",\n description: \"Reference to another collection\",\n zodTypes: [\"ZodString\", \"ZodArray<ZodString>\"],\n supportsMultiple: true,\n },\n file: {\n type: \"file\",\n description: \"File upload field\",\n zodTypes: [\"File\", \"ZodArray<File>\"],\n supportsMultiple: true,\n },\n json: {\n type: \"json\",\n description: \"JSON data field\",\n zodTypes: [\"ZodRecord\", \"ZodObject\", \"ZodArray\"],\n supportsMultiple: false,\n },\n geoPoint: {\n type: \"geoPoint\",\n description: \"Geographic coordinates (lon, lat)\",\n zodTypes: [\"ZodObject with lon/lat\"],\n supportsMultiple: false,\n },\n};\n\n/**\n * Maps Zod string types to PocketBase field types\n */\nexport function mapZodStringType(zodType: z.ZodString): PocketBaseFieldType {\n const checks = (zodType as any)._def.checks || [];\n\n // Check for email validation\n const hasEmail = checks.some((check: any) => check.kind === \"email\");\n if (hasEmail) {\n return \"email\";\n }\n\n // Check for URL validation\n const hasUrl = checks.some((check: any) => check.kind === \"url\");\n if (hasUrl) {\n return \"url\";\n }\n\n // Check for datetime validation (could be date field)\n const hasDatetime = checks.some((check: any) => check.kind === \"datetime\");\n if (hasDatetime) {\n return \"date\";\n }\n\n // Default to text\n return \"text\";\n}\n\n/**\n * Maps Zod number types to PocketBase number type\n */\nexport function mapZodNumberType(_zodType: z.ZodNumber): PocketBaseFieldType {\n return \"number\";\n}\n\n/**\n * Maps Zod boolean types to PocketBase bool type\n */\nexport function mapZodBooleanType(_zodType: z.ZodBoolean): PocketBaseFieldType {\n return \"bool\";\n}\n\n/**\n * Maps Zod enum types to PocketBase select type\n */\nexport function mapZodEnumType(_zodType: z.ZodEnum<any>): PocketBaseFieldType {\n return \"select\";\n}\n\n/**\n * Maps Zod array types to appropriate PocketBase types\n * Arrays of strings could be relations or file fields depending on context\n */\nexport function mapZodArrayType(zodType: z.ZodArray<any>, _fieldName: string): PocketBaseFieldType {\n const elementType = zodType._def.type;\n\n // Check if it's an array of File instances (file upload)\n if (elementType instanceof z.ZodType) {\n const typeName = elementType._def.typeName;\n if (typeName === \"ZodType\" && (elementType as any)._def?.innerType?.name === \"File\") {\n return \"file\";\n }\n }\n\n // Check for instanceof File\n if (elementType._def?.typeName === \"ZodType\") {\n const checks = (elementType as any)._def?.checks || [];\n const isFileInstance = checks.some(\n (check: any) => check.kind === \"instanceof\" || (elementType as any)._def?.innerType?.name === \"File\"\n );\n if (isFileInstance) {\n return \"file\";\n }\n }\n\n // Array of strings - could be relation (will be determined by relation detector)\n if (elementType instanceof z.ZodString) {\n return \"relation\";\n }\n\n // Default to JSON for other array types\n return \"json\";\n}\n\n/**\n * Maps Zod date types to PocketBase date type\n */\nexport function mapZodDateType(_zodType: z.ZodDate): PocketBaseFieldType {\n return \"date\";\n}\n\n/**\n * Maps Zod record/object types to PocketBase JSON type\n */\nexport function mapZodRecordType(_zodType: z.ZodRecord | z.ZodObject<any>): PocketBaseFieldType {\n return \"json\";\n}\n\n/**\n * Main type mapping function that determines PocketBase field type from Zod type\n */\nexport function mapZodTypeToPocketBase(zodType: z.ZodTypeAny, fieldName: string): PocketBaseFieldType {\n // Handle optional and nullable types by unwrapping\n let unwrappedType = zodType;\n\n if (zodType instanceof z.ZodOptional) {\n unwrappedType = zodType._def.innerType;\n }\n\n if (unwrappedType instanceof z.ZodNullable) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n if (unwrappedType instanceof z.ZodDefault) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n // Check for ZodEffects (which is what z.instanceof() creates)\n if ((unwrappedType as any)._def?.typeName === \"ZodEffects\") {\n const effect = (unwrappedType as any)._def?.effect;\n\n // z.instanceof(File) creates a refinement effect\n // We need to check if this is a File instance check\n // The field name 'avatar', 'image', 'file', 'attachment' etc. are hints\n if (effect?.type === \"refinement\") {\n // Common file field names\n const fileFieldNames = [\"avatar\", \"image\", \"file\", \"attachment\", \"photo\", \"picture\", \"document\", \"upload\"];\n if (fileFieldNames.some((name) => fieldName.toLowerCase().includes(name))) {\n return \"file\";\n }\n }\n }\n\n // Check for instanceof File (z.instanceof(File)) - legacy check\n if ((unwrappedType as any)._def?.typeName === \"ZodType\") {\n const checks = (unwrappedType as any)._def?.checks || [];\n const innerType = (unwrappedType as any)._def?.innerType;\n\n // Check if it's instanceof File\n if (innerType?.name === \"File\" || checks.some((check: any) => check.kind === \"instanceof\")) {\n return \"file\";\n }\n }\n\n // Map based on Zod type\n if (unwrappedType instanceof z.ZodString) {\n return mapZodStringType(unwrappedType);\n }\n\n if (unwrappedType instanceof z.ZodNumber) {\n return mapZodNumberType(unwrappedType);\n }\n\n if (unwrappedType instanceof z.ZodBoolean) {\n return mapZodBooleanType(unwrappedType);\n }\n\n if (unwrappedType instanceof z.ZodEnum) {\n return mapZodEnumType(unwrappedType);\n }\n\n if (unwrappedType instanceof z.ZodArray) {\n return mapZodArrayType(unwrappedType, fieldName);\n }\n\n if (unwrappedType instanceof z.ZodDate) {\n return mapZodDateType(unwrappedType);\n }\n\n if (unwrappedType instanceof z.ZodRecord || unwrappedType instanceof z.ZodObject) {\n return mapZodRecordType(unwrappedType);\n }\n\n // Default to text for unknown types\n return \"text\";\n}\n\n/**\n * Extracts field options from Zod type (min, max, pattern, etc.)\n */\nexport function extractFieldOptions(zodType: z.ZodTypeAny): Record<string, any> {\n const options: Record<string, any> = {};\n\n // Unwrap optional/nullable/default\n let unwrappedType = zodType;\n if (zodType instanceof z.ZodOptional) {\n unwrappedType = zodType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodNullable) {\n unwrappedType = unwrappedType._def.innerType;\n }\n if (unwrappedType instanceof z.ZodDefault) {\n unwrappedType = unwrappedType._def.innerType;\n }\n\n const checks = (unwrappedType as any)._def?.checks || [];\n\n // Extract string constraints\n if (unwrappedType instanceof z.ZodString) {\n for (const check of checks) {\n if (check.kind === \"min\") {\n options.min = check.value;\n }\n if (check.kind === \"max\") {\n options.max = check.value;\n }\n if (check.kind === \"regex\") {\n options.pattern = check.regex.source;\n }\n }\n }\n\n // Extract number constraints\n if (unwrappedType instanceof z.ZodNumber) {\n for (const check of checks) {\n if (check.kind === \"min\") {\n options.min = check.value;\n }\n if (check.kind === \"max\") {\n options.max = check.value;\n }\n }\n }\n\n // Extract enum values\n if (unwrappedType instanceof z.ZodEnum) {\n options.values = unwrappedType._def.values;\n }\n\n // Extract array constraints\n if (unwrappedType instanceof z.ZodArray) {\n const arrayChecks = (unwrappedType as any)._def?.checks || [];\n for (const check of arrayChecks) {\n if (check.kind === \"min\") {\n options.minSelect = check.value;\n }\n if (check.kind === \"max\") {\n options.maxSelect = check.value;\n }\n }\n }\n\n return options;\n}\n\n/**\n * Determines if a Zod field is required (not optional)\n */\nexport function isFieldRequired(zodType: z.ZodTypeAny): boolean {\n // Check if it's optional\n if (zodType instanceof z.ZodOptional) {\n return false;\n }\n\n // Check if it has a default value (makes it optional)\n if (zodType instanceof z.ZodDefault) {\n return false;\n }\n\n // Check for nullable (in PocketBase context, nullable means optional)\n if (zodType instanceof z.ZodNullable) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Unwraps a Zod type to get the inner type\n * Handles optional, nullable, and default wrappers\n */\nexport function unwrapZodType(zodType: z.ZodTypeAny): z.ZodTypeAny {\n let unwrapped = zodType;\n\n if (unwrapped instanceof z.ZodOptional) {\n unwrapped = unwrapped._def.innerType;\n }\n\n if (unwrapped instanceof z.ZodNullable) {\n unwrapped = unwrapped._def.innerType;\n }\n\n if (unwrapped instanceof z.ZodDefault) {\n unwrapped = unwrapped._def.innerType;\n }\n\n return unwrapped;\n}\n\n/**\n * Gets the default value from a Zod type if it has one\n */\nexport function getDefaultValue(zodType: z.ZodTypeAny): any {\n if (zodType instanceof z.ZodDefault) {\n return zodType._def.defaultValue();\n }\n return undefined;\n}\n\n/**\n * Checks if a Zod type is an array type\n */\nexport function isArrayType(zodType: z.ZodTypeAny): boolean {\n const unwrapped = unwrapZodType(zodType);\n return unwrapped instanceof z.ZodArray;\n}\n\n/**\n * Gets the element type of an array Zod type\n */\nexport function getArrayElementType(zodType: z.ZodTypeAny): z.ZodTypeAny | null {\n const unwrapped = unwrapZodType(zodType);\n if (unwrapped instanceof z.ZodArray) {\n return unwrapped._def.type;\n }\n return null;\n}\n\n/**\n * Checks if a Zod type represents a geo point (object with lon/lat)\n */\nexport function isGeoPointType(zodType: z.ZodTypeAny): boolean {\n const unwrapped = unwrapZodType(zodType);\n if (!(unwrapped instanceof z.ZodObject)) {\n return false;\n }\n\n const shape = unwrapped._def.shape();\n const hasLon = \"lon\" in shape && shape.lon instanceof z.ZodNumber;\n const hasLat = \"lat\" in shape && shape.lat instanceof z.ZodNumber;\n\n return hasLon && hasLat;\n}\n\n/**\n * Complete field options extracted from a Zod type\n */\nexport interface ExtractedFieldOptions {\n min?: number;\n max?: number;\n pattern?: string;\n values?: string[];\n minSelect?: number;\n maxSelect?: number;\n mimeTypes?: string[];\n maxSize?: number;\n thumbs?: string[];\n}\n\n/**\n * Extracts comprehensive field options from Zod type\n * Includes all constraints that can be mapped to PocketBase field options\n */\nexport function extractComprehensiveFieldOptions(zodType: z.ZodTypeAny): ExtractedFieldOptions {\n const options: ExtractedFieldOptions = {};\n const unwrapped = unwrapZodType(zodType);\n const checks = (unwrapped as any)._def?.checks || [];\n\n // Extract string constraints\n if (unwrapped instanceof z.ZodString) {\n for (const check of checks) {\n if (check.kind === \"min\") {\n options.min = check.value;\n }\n if (check.kind === \"max\") {\n options.max = check.value;\n }\n if (check.kind === \"regex\") {\n options.pattern = check.regex.source;\n }\n }\n }\n\n // Extract number constraints\n if (unwrapped instanceof z.ZodNumber) {\n for (const check of checks) {\n if (check.kind === \"min\") {\n options.min = check.value;\n }\n if (check.kind === \"max\") {\n options.max = check.value;\n }\n }\n }\n\n // Extract enum values\n if (unwrapped instanceof z.ZodEnum) {\n options.values = unwrapped._def.values;\n }\n\n // Extract array constraints\n if (unwrapped instanceof z.ZodArray) {\n const arrayDef = unwrapped._def;\n if (arrayDef.minLength) {\n options.minSelect = arrayDef.minLength.value;\n }\n if (arrayDef.maxLength) {\n options.maxSelect = arrayDef.maxLength.value;\n }\n\n // Check for enum element type\n const elementType = arrayDef.type;\n if (elementType instanceof z.ZodEnum) {\n options.values = elementType._def.values;\n }\n }\n\n return options;\n}\n\n/**\n * Determines if a field should be treated as an editor field\n * based on field name conventions\n */\nexport function isEditorField(fieldName: string): boolean {\n const editorFieldNames = [\n \"content\",\n \"body\",\n \"description\",\n \"bio\",\n \"about\",\n \"summary\",\n \"notes\",\n \"details\",\n \"html\",\n \"richtext\",\n \"editor\",\n ];\n return editorFieldNames.some((name) => fieldName.toLowerCase().includes(name));\n}\n\n/**\n * Determines if a field should be treated as a file field\n * based on field name conventions\n */\nexport function isFileFieldByName(fieldName: string): boolean {\n const fileFieldNames = [\n \"avatar\",\n \"image\",\n \"file\",\n \"attachment\",\n \"photo\",\n \"picture\",\n \"document\",\n \"upload\",\n \"thumbnail\",\n \"cover\",\n \"banner\",\n \"logo\",\n \"icon\",\n \"media\",\n ];\n return fileFieldNames.some((name) => fieldName.toLowerCase().includes(name));\n}\n\n/**\n * Gets the PocketBase field type with additional context\n */\nexport interface FieldTypeResult {\n type: PocketBaseFieldType;\n isMultiple: boolean;\n options: ExtractedFieldOptions;\n}\n\n/**\n * Comprehensive type mapping that returns full field information\n */\nexport function getFieldTypeInfo(zodType: z.ZodTypeAny, fieldName: string): FieldTypeResult {\n const type = mapZodTypeToPocketBase(zodType, fieldName);\n const isMultiple = isArrayType(zodType);\n const options = extractComprehensiveFieldOptions(zodType);\n\n return {\n type,\n isMultiple,\n options,\n };\n}\n","/**\n * Schema Analyzer - Parses Zod schemas and extracts field definitions\n *\n * This module provides a standalone, configurable schema analyzer that can be used\n * by consumer projects to parse Zod schemas and convert them to PocketBase collection schemas.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { z } from \"zod\";\nimport type { PermissionSchema } from \"../schema/permissions\";\nimport { FileSystemError, SchemaParsingError } from \"./errors\";\nimport { PermissionAnalyzer } from \"./permission-analyzer\";\nimport type { CollectionSchema, FieldDefinition, SchemaDefinition } from \"./types\";\nimport { toCollectionName } from \"./utils/pluralize\";\nimport { getMaxSelect, getMinSelect, isRelationField, resolveTargetCollection } from \"./utils/relation-detector\";\nimport { extractFieldOptions, isFieldRequired, mapZodTypeToPocketBase } from \"./utils/type-mapper\";\n\n/**\n * Configuration options for schema discovery and parsing\n */\nexport interface SchemaAnalyzerConfig {\n /**\n * Directory containing schema files (source or compiled)\n * Can be absolute or relative to workspaceRoot\n */\n schemaDir: string;\n\n /**\n * Workspace root directory for resolving relative paths\n * Defaults to process.cwd()\n */\n workspaceRoot?: string;\n\n /**\n * File patterns to exclude from schema discovery\n * Defaults to ['base.ts', 'index.ts', 'permissions.ts', 'permission-templates.ts']\n */\n excludePatterns?: string[];\n\n /**\n * File extensions to include in schema discovery\n * Defaults to ['.ts', '.js']\n */\n includeExtensions?: string[];\n\n /**\n * Schema export name patterns to look for\n * Defaults to ['Schema', 'InputSchema']\n */\n schemaPatterns?: string[];\n\n /**\n * Whether to use compiled JavaScript files instead of TypeScript source\n * When true, looks for .js files; when false, looks for .ts files\n * Defaults to true (use compiled files for dynamic import)\n */\n useCompiledFiles?: boolean;\n\n /**\n * Custom path transformation function for converting source paths to import paths\n * Useful for monorepo setups where source and dist directories differ\n * If not provided, uses the schemaDir directly\n */\n pathTransformer?: (sourcePath: string) => string;\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_CONFIG: Required<Omit<SchemaAnalyzerConfig, \"schemaDir\" | \"pathTransformer\">> = {\n workspaceRoot: process.cwd(),\n excludePatterns: [\n \"base.ts\",\n \"index.ts\",\n \"permissions.ts\",\n \"permission-templates.ts\",\n \"base.js\",\n \"index.js\",\n \"permissions.js\",\n \"permission-templates.js\",\n ],\n includeExtensions: [\".ts\", \".js\"],\n schemaPatterns: [\"Schema\", \"InputSchema\"],\n useCompiledFiles: true,\n};\n\n/**\n * Merges user config with defaults\n */\nfunction mergeConfig(\n config: SchemaAnalyzerConfig\n): Required<Omit<SchemaAnalyzerConfig, \"pathTransformer\">> & { pathTransformer?: (sourcePath: string) => string } {\n return {\n ...DEFAULT_CONFIG,\n ...config,\n excludePatterns: config.excludePatterns || DEFAULT_CONFIG.excludePatterns,\n includeExtensions: config.includeExtensions || DEFAULT_CONFIG.includeExtensions,\n schemaPatterns: config.schemaPatterns || DEFAULT_CONFIG.schemaPatterns,\n };\n}\n\n/**\n * Resolves the schema directory path\n */\nfunction resolveSchemaDir(config: SchemaAnalyzerConfig): string {\n const workspaceRoot = config.workspaceRoot || process.cwd();\n\n if (path.isAbsolute(config.schemaDir)) {\n return config.schemaDir;\n }\n\n return path.join(workspaceRoot, config.schemaDir);\n}\n\n/**\n * Discovers schema files in the specified directory\n * Filters based on configuration patterns\n *\n * @param config - Schema analyzer configuration\n * @returns Array of schema file paths (without extension)\n */\nexport function discoverSchemaFiles(config: SchemaAnalyzerConfig | string): string[] {\n // Support legacy string-only parameter\n const normalizedConfig: SchemaAnalyzerConfig = typeof config === \"string\" ? { schemaDir: config } : config;\n\n const mergedConfig = mergeConfig(normalizedConfig);\n const schemaDir = resolveSchemaDir(normalizedConfig);\n\n try {\n if (!fs.existsSync(schemaDir)) {\n throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, \"access\", \"ENOENT\");\n }\n\n const files = fs.readdirSync(schemaDir);\n\n // Filter files based on configuration\n const schemaFiles = files.filter((file) => {\n // Check extension\n const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));\n if (!hasValidExtension) return false;\n\n // Check exclusion patterns\n const isExcluded = mergedConfig.excludePatterns.some((pattern) => {\n // Support both exact match and glob-like patterns\n if (pattern.includes(\"*\")) {\n const regex = new RegExp(\"^\" + pattern.replace(/\\*/g, \".*\") + \"$\");\n return regex.test(file);\n }\n return file === pattern;\n });\n if (isExcluded) return false;\n\n return true;\n });\n\n // Return full paths without extension (for dynamic import)\n return schemaFiles.map((file) => {\n const ext = mergedConfig.includeExtensions.find((ext) => file.endsWith(ext)) || \".ts\";\n return path.join(schemaDir, file.replace(new RegExp(`\\\\${ext}$`), \"\"));\n });\n } catch (error) {\n if (error instanceof FileSystemError) {\n throw error;\n }\n\n const fsError = error as NodeJS.ErrnoException;\n if (fsError.code === \"EACCES\" || fsError.code === \"EPERM\") {\n throw new FileSystemError(\n `Permission denied reading schema directory: ${schemaDir}`,\n schemaDir,\n \"read\",\n fsError.code,\n error as Error\n );\n }\n\n throw new FileSystemError(\n `Failed to read schema directory: ${schemaDir}`,\n schemaDir,\n \"read\",\n fsError.code,\n error as Error\n );\n }\n}\n\n/**\n * Dynamically imports a schema module\n *\n * @param filePath - Path to the schema file (without extension)\n * @param config - Optional configuration for path transformation\n * @returns The imported module\n */\nexport async function importSchemaModule(filePath: string, config?: SchemaAnalyzerConfig): Promise<any> {\n try {\n let importPath = filePath;\n\n // Apply path transformation if provided\n if (config?.pathTransformer) {\n importPath = config.pathTransformer(filePath);\n }\n\n // Add .js extension for ESM import\n if (!importPath.endsWith(\".js\")) {\n importPath = `${importPath}.js`;\n }\n\n // Convert to file URL for proper ESM import\n const fileUrl = new URL(`file://${path.resolve(importPath)}`);\n\n // Use dynamic import to load the module\n const module = await import(fileUrl.href);\n return module;\n } catch (error) {\n throw new SchemaParsingError(\n `Failed to import schema module. Make sure the schema files are compiled to JavaScript.`,\n filePath,\n error as Error\n );\n }\n}\n\n/**\n * Gets the collection name from a schema file path\n * Converts the filename (without extension) to a pluralized collection name\n *\n * @param filePath - Path to the schema file (with or without extension)\n * @returns The collection name\n */\nexport function getCollectionNameFromFile(filePath: string): string {\n // Remove both .ts and .js extensions if present\n const filename = path.basename(filePath).replace(/\\.(ts|js)$/, \"\");\n return toCollectionName(filename);\n}\n\n/**\n * Extracts Zod schema definitions from a module\n * Looks for schemas ending with configured patterns (default: \"Schema\" or \"InputSchema\")\n *\n * @param module - The imported schema module\n * @param patterns - Schema name patterns to look for (default: ['Schema', 'InputSchema'])\n * @returns Object containing found schemas\n */\nexport function extractSchemaDefinitions(\n module: any,\n patterns: string[] = [\"Schema\", \"InputSchema\"]\n): { inputSchema?: z.ZodObject<any>; schema?: z.ZodObject<any> } {\n const result: { inputSchema?: z.ZodObject<any>; schema?: z.ZodObject<any> } = {};\n\n // Look for InputSchema and Schema exports\n for (const [key, value] of Object.entries(module)) {\n // Check if it's a Zod schema\n if (value instanceof z.ZodObject) {\n // Check for InputSchema pattern first (more specific)\n if (patterns.includes(\"InputSchema\") && key.endsWith(\"InputSchema\")) {\n result.inputSchema = value as z.ZodObject<any>;\n } else if (patterns.includes(\"Schema\") && key.endsWith(\"Schema\") && !key.endsWith(\"InputSchema\")) {\n result.schema = value as z.ZodObject<any>;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Identifies whether to use InputSchema or Schema pattern\n * Prefers Schema over InputSchema as it includes base fields\n *\n * @param schemas - Object containing inputSchema and/or schema\n * @returns The schema to use for collection definition\n */\nexport function selectSchemaForCollection(schemas: {\n inputSchema?: z.ZodObject<any>;\n schema?: z.ZodObject<any>;\n}): z.ZodObject<any> | null {\n // Prefer the full Schema over InputSchema as it includes base fields\n if (schemas.schema) {\n return schemas.schema;\n }\n\n if (schemas.inputSchema) {\n return schemas.inputSchema;\n }\n\n return null;\n}\n\n/**\n * Extracts field definitions from a Zod object schema\n * Filters out base schema fields (id, collectionId, created, updated, expand)\n *\n * @param zodSchema - The Zod object schema\n * @param excludeFields - Additional fields to exclude (default: base schema fields)\n * @returns Array of field names and their Zod types\n */\nexport function extractFieldDefinitions(\n zodSchema: z.ZodObject<any>,\n excludeFields?: string[]\n): Array<{ name: string; zodType: z.ZodTypeAny }> {\n const shape = zodSchema.shape;\n const fields: Array<{ name: string; zodType: z.ZodTypeAny }> = [];\n\n // Base schema fields to exclude (these are system fields in PocketBase)\n const baseFields = [\"id\", \"collectionId\", \"collectionName\", \"created\", \"updated\", \"expand\"];\n\n // Additional fields to exclude (image file handling fields)\n const defaultExcludeFields = [\"thumbnailURL\", \"imageFiles\"];\n\n // Combine all exclusions\n const allExclusions = new Set([...baseFields, ...defaultExcludeFields, ...(excludeFields || [])]);\n\n for (const [fieldName, zodType] of Object.entries(shape)) {\n // Skip excluded fields\n if (!allExclusions.has(fieldName)) {\n fields.push({ name: fieldName, zodType: zodType as z.ZodTypeAny });\n }\n }\n\n return fields;\n}\n\n/**\n * Detects if a collection is an auth collection\n * Auth collections have email and password fields\n *\n * @param fields - Array of field definitions\n * @returns True if the collection is an auth collection\n */\nexport function isAuthCollection(fields: Array<{ name: string; zodType: z.ZodTypeAny }>): boolean {\n const fieldNames = fields.map((f) => f.name.toLowerCase());\n\n // Auth collections must have both email and password fields\n const hasEmail = fieldNames.includes(\"email\");\n const hasPassword = fieldNames.includes(\"password\");\n\n return hasEmail && hasPassword;\n}\n\n/**\n * Extracts validation constraints from Zod type\n * Includes min, max, required, unique, and other options\n *\n * @param fieldName - The field name\n * @param zodType - The Zod type\n * @returns Field definition with constraints\n */\nexport function buildFieldDefinition(fieldName: string, zodType: z.ZodTypeAny): FieldDefinition {\n const fieldType = mapZodTypeToPocketBase(zodType, fieldName);\n const required = isFieldRequired(zodType);\n const options = extractFieldOptions(zodType);\n\n const fieldDef: FieldDefinition = {\n name: fieldName,\n type: fieldType,\n required,\n options,\n };\n\n // Handle relation fields\n if (isRelationField(fieldName, zodType)) {\n // Override type to 'relation' for relation fields\n fieldDef.type = \"relation\";\n\n const targetCollection = resolveTargetCollection(fieldName);\n const maxSelect = getMaxSelect(fieldName, zodType);\n const minSelect = getMinSelect(fieldName, zodType);\n\n fieldDef.relation = {\n collection: targetCollection,\n maxSelect,\n minSelect,\n cascadeDelete: false, // Default to false, can be configured later\n };\n }\n\n return fieldDef;\n}\n\n/**\n * Extracts index definitions from a Zod schema\n * Parses the schema description metadata to find index definitions\n *\n * @param schema - Zod schema with index metadata\n * @returns Array of index SQL statements or undefined\n */\nexport function extractIndexes(schema: z.ZodTypeAny): string[] | undefined {\n // Try to extract indexes from schema description\n const schemaDescription = schema.description;\n\n if (!schemaDescription) {\n return undefined;\n }\n\n try {\n const metadata = JSON.parse(schemaDescription);\n\n // Check if indexes are present in metadata\n if (metadata.indexes && Array.isArray(metadata.indexes)) {\n return metadata.indexes;\n }\n } catch {\n // If description is not valid JSON, return undefined\n }\n\n return undefined;\n}\n\n/**\n * Converts a Zod schema to a CollectionSchema interface\n *\n * @param collectionName - The name of the collection\n * @param zodSchema - The Zod object schema\n * @returns CollectionSchema definition\n */\nexport function convertZodSchemaToCollectionSchema(\n collectionName: string,\n zodSchema: z.ZodObject<any>\n): CollectionSchema {\n // Extract field definitions from Zod schema\n const rawFields = extractFieldDefinitions(zodSchema);\n\n // Determine collection type (auth or base)\n const collectionType = isAuthCollection(rawFields) ? \"auth\" : \"base\";\n\n // Build field definitions with constraints\n const fields: FieldDefinition[] = rawFields.map(({ name, zodType }) => buildFieldDefinition(name, zodType));\n\n // Extract indexes from schema\n const indexes = extractIndexes(zodSchema) || [];\n\n // Extract and validate permissions from schema\n const permissionAnalyzer = new PermissionAnalyzer();\n let permissions: PermissionSchema | undefined = undefined;\n\n // Try to extract permissions from schema description\n const schemaDescription = zodSchema.description;\n const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);\n\n if (extractedPermissions) {\n // Resolve template configurations to concrete rules\n const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);\n\n // Validate permissions against collection fields\n const validationResults = permissionAnalyzer.validatePermissions(\n collectionName,\n resolvedPermissions,\n fields,\n collectionType === \"auth\"\n );\n\n // Log validation errors and warnings\n for (const [ruleType, result] of validationResults) {\n if (!result.valid) {\n console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);\n result.errors.forEach((error) => console.error(` - ${error}`));\n }\n\n if (result.warnings.length > 0) {\n console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);\n result.warnings.forEach((warning) => console.warn(` - ${warning}`));\n }\n }\n\n // Merge with defaults to ensure all rules are defined\n permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);\n }\n\n // Build collection schema\n const collectionSchema: CollectionSchema = {\n name: collectionName,\n type: collectionType,\n fields,\n indexes,\n rules: {\n listRule: null,\n viewRule: null,\n createRule: null,\n updateRule: null,\n deleteRule: null,\n },\n permissions,\n };\n\n return collectionSchema;\n}\n\n/**\n * Builds a complete SchemaDefinition from schema files\n * Main entry point for the Schema Analyzer\n *\n * @param config - Schema analyzer configuration or path to schema directory\n * @returns Complete SchemaDefinition with all collections\n */\nexport async function buildSchemaDefinition(config: SchemaAnalyzerConfig | string): Promise<SchemaDefinition> {\n // Support legacy string-only parameter\n const normalizedConfig: SchemaAnalyzerConfig = typeof config === \"string\" ? { schemaDir: config } : config;\n\n const mergedConfig = mergeConfig(normalizedConfig);\n const collections = new Map<string, CollectionSchema>();\n\n // Discover schema files\n const schemaFiles = discoverSchemaFiles(normalizedConfig);\n\n if (schemaFiles.length === 0) {\n const schemaDir = resolveSchemaDir(normalizedConfig);\n throw new SchemaParsingError(\n `No schema files found in ${schemaDir}. Make sure you have schema files in the directory.`,\n schemaDir\n );\n }\n\n // Process each schema file\n for (const filePath of schemaFiles) {\n try {\n let importPath = filePath;\n\n // Apply path transformation if provided (for monorepo setups)\n if (normalizedConfig.pathTransformer) {\n importPath = normalizedConfig.pathTransformer(filePath);\n } else if (mergedConfig.useCompiledFiles) {\n // Default transformation: convert /src/ to /dist/ for compiled files\n // This is a common pattern but can be overridden with pathTransformer\n importPath = filePath.replace(/\\/src\\//, \"/dist/\");\n }\n\n // Import the module\n const module = await importSchemaModule(importPath, normalizedConfig);\n\n // Extract schema definitions\n const schemas = extractSchemaDefinitions(module, mergedConfig.schemaPatterns);\n\n // Select the appropriate schema\n const zodSchema = selectSchemaForCollection(schemas);\n\n if (!zodSchema) {\n console.warn(`No valid schema found in ${filePath}, skipping...`);\n continue;\n }\n\n // Get collection name from file\n const collectionName = getCollectionNameFromFile(filePath);\n\n // Convert to CollectionSchema\n const collectionSchema = convertZodSchemaToCollectionSchema(collectionName, zodSchema);\n\n // Add to collections map\n collections.set(collectionName, collectionSchema);\n } catch (error) {\n // If it's already a SchemaParsingError, re-throw it\n if (error instanceof SchemaParsingError) {\n throw error;\n }\n\n // Otherwise, wrap it in a SchemaParsingError\n throw new SchemaParsingError(\n `Error processing schema file: ${error instanceof Error ? error.message : String(error)}`,\n filePath,\n error as Error\n );\n }\n }\n\n return { collections };\n}\n\n/**\n * Parses schema files and returns SchemaDefinition\n * Alias for buildSchemaDefinition for better semantic clarity\n *\n * @param config - Schema analyzer configuration or path to schema directory\n * @returns Complete SchemaDefinition with all collections\n */\nexport async function parseSchemaFiles(config: SchemaAnalyzerConfig | string): Promise<SchemaDefinition> {\n return buildSchemaDefinition(config);\n}\n\n/**\n * Creates a SchemaAnalyzer instance with the given configuration\n * Provides an object-oriented interface for schema analysis\n */\nexport class SchemaAnalyzer {\n private config: Required<Omit<SchemaAnalyzerConfig, \"pathTransformer\">> & {\n pathTransformer?: (sourcePath: string) => string;\n };\n\n constructor(config: SchemaAnalyzerConfig) {\n this.config = mergeConfig(config);\n }\n\n /**\n * Discovers schema files in the configured directory\n */\n discoverSchemaFiles(): string[] {\n return discoverSchemaFiles(this.config);\n }\n\n /**\n * Parses all schema files and returns a SchemaDefinition\n */\n async parseSchemaFiles(): Promise<SchemaDefinition> {\n return buildSchemaDefinition(this.config);\n }\n\n /**\n * Converts a single Zod schema to a CollectionSchema\n */\n convertZodSchemaToCollectionSchema(name: string, schema: z.ZodObject<any>): CollectionSchema {\n return convertZodSchemaToCollectionSchema(name, schema);\n }\n}\n"]}