# ESLint Rules for PlatformServiceMixin Migration ## Overview Custom ESLint rules to enforce PlatformServiceMixin patterns and prevent regression to legacy patterns. ## Rules Configuration Add to `.eslintrc.js`: ```javascript module.exports = { // ... existing config rules: { // ... existing rules // Custom rules for PlatformServiceMixin migration 'timesafari/no-direct-database-util': 'error', 'timesafari/no-legacy-logging': 'error', 'timesafari/require-mixin-for-database': 'error', 'timesafari/no-direct-platform-service': 'warn', 'timesafari/prefer-mixin-methods': 'warn', }, // Custom rules plugin plugins: ['timesafari'], } ``` ## Custom Rules Implementation Create `eslint-plugin-timesafari/index.js`: ```javascript module.exports = { rules: { 'no-direct-database-util': { meta: { type: 'problem', docs: { description: 'Disallow direct imports from databaseUtil', category: 'Migration', recommended: true, }, schema: [], }, create(context) { return { ImportDeclaration(node) { if (node.source.value.includes('databaseUtil')) { context.report({ node, message: 'Direct databaseUtil imports are deprecated. Use PlatformServiceMixin instead.', }); } }, }; }, }, 'no-legacy-logging': { meta: { type: 'problem', docs: { description: 'Disallow legacy logging methods', category: 'Migration', recommended: true, }, schema: [], }, create(context) { return { ImportDeclaration(node) { if (node.specifiers.some(spec => spec.imported?.name === 'logConsoleAndDb')) { context.report({ node, message: 'logConsoleAndDb is deprecated. Use PlatformServiceMixin $log methods instead.', }); } }, CallExpression(node) { if (node.callee.name === 'logConsoleAndDb') { context.report({ node, message: 'logConsoleAndDb is deprecated. Use this.$logAndConsole() instead.', }); } }, }; }, }, 'require-mixin-for-database': { meta: { type: 'suggestion', docs: { description: 'Require PlatformServiceMixin for components using database operations', category: 'Migration', recommended: true, }, schema: [], }, create(context) { let hasDbOperations = false; let hasMixin = false; return { CallExpression(node) { // Check for database operations if (node.callee.property && ['dbQuery', 'dbExec', 'dbGetOneRow'].includes(node.callee.property.name)) { hasDbOperations = true; } }, Property(node) { // Check for mixin usage if (node.key.name === 'mixins' && node.value.elements?.some(el => el.name === 'PlatformServiceMixin')) { hasMixin = true; } }, 'Program:exit'() { if (hasDbOperations && !hasMixin) { context.report({ node: context.getSourceCode().ast, message: 'Components using database operations should include PlatformServiceMixin.', }); } }, }; }, }, 'no-direct-platform-service': { meta: { type: 'suggestion', docs: { description: 'Discourage direct PlatformServiceFactory usage', category: 'Migration', recommended: false, }, schema: [], }, create(context) { return { CallExpression(node) { if (node.callee.object?.name === 'PlatformServiceFactory' && node.callee.property?.name === 'getInstance') { context.report({ node, message: 'Consider using PlatformServiceMixin methods instead of direct PlatformServiceFactory.', }); } }, }; }, }, 'prefer-mixin-methods': { meta: { type: 'suggestion', docs: { description: 'Prefer mixin convenience methods over direct database calls', category: 'Migration', recommended: false, }, schema: [], }, create(context) { return { CallExpression(node) { // Check for patterns that could use mixin methods if (node.callee.property?.name === 'dbQuery') { const arg = node.arguments[0]; if (arg && arg.type === 'Literal') { const sql = arg.value.toLowerCase(); if (sql.includes('select * from contacts')) { context.report({ node, message: 'Consider using this.$getAllContacts() instead of direct SQL.', }); } if (sql.includes('select * from settings')) { context.report({ node, message: 'Consider using this.$settings() instead of direct SQL.', }); } } } }, }; }, }, }, }; ``` ## Pre-commit Hook Create `.pre-commit-config.yaml`: ```yaml repos: - repo: local hooks: - id: eslint-migration-check name: ESLint Migration Check entry: npx eslint --ext .vue --rule 'timesafari/no-direct-database-util: error' language: system files: \.vue$ - id: no-legacy-logging name: No Legacy Logging entry: bash -c 'if grep -r "logConsoleAndDb" src/ --include="*.vue" --include="*.ts"; then echo "Found legacy logging imports"; exit 1; fi' language: system pass_filenames: false ``` ## Migration Validation Script Create `scripts/validate-migration.sh`: ```bash #!/bin/bash echo "🔍 Validating PlatformServiceMixin migration..." # Check for legacy patterns echo "Checking for legacy databaseUtil imports..." LEGACY_DB_IMPORTS=$(grep -r "import.*databaseUtil" src/ --include="*.vue" --include="*.ts" | wc -l) echo "Found $LEGACY_DB_IMPORTS legacy databaseUtil imports" echo "Checking for legacy logging imports..." LEGACY_LOG_IMPORTS=$(grep -r "logConsoleAndDb" src/ --include="*.vue" --include="*.ts" | wc -l) echo "Found $LEGACY_LOG_IMPORTS legacy logging imports" # Check for mixin usage echo "Checking for PlatformServiceMixin usage..." MIXIN_USAGE=$(grep -r "PlatformServiceMixin" src/ --include="*.vue" | wc -l) echo "Found $MIXIN_USAGE files using PlatformServiceMixin" # Check for direct PlatformService usage echo "Checking for direct PlatformService usage..." DIRECT_PLATFORM=$(grep -r "PlatformServiceFactory.getInstance" src/ --include="*.vue" --include="*.ts" | wc -l) echo "Found $DIRECT_PLATFORM direct PlatformService usages" # Summary echo "" echo "📊 Migration Status Summary:" echo "- Legacy databaseUtil imports: $LEGACY_DB_IMPORTS (should be 0)" echo "- Legacy logging imports: $LEGACY_LOG_IMPORTS (should be 0)" echo "- Mixin usage: $MIXIN_USAGE (should be high)" echo "- Direct PlatformService usage: $DIRECT_PLATFORM (should be low)" # Set exit code based on legacy usage if [ $LEGACY_DB_IMPORTS -gt 0 ] || [ $LEGACY_LOG_IMPORTS -gt 0 ]; then echo "❌ Migration validation failed - legacy patterns found" exit 1 else echo "✅ Migration validation passed - no legacy patterns found" exit 0 fi ``` ## Usage 1. **Install ESLint rules**: ```bash npm install --save-dev eslint-plugin-timesafari ``` 2. **Run validation**: ```bash npm run lint ./scripts/validate-migration.sh ``` 3. **Fix issues automatically**: ```bash npm run lint -- --fix ``` ## IDE Integration ### VS Code Settings Add to `.vscode/settings.json`: ```json { "eslint.validate": [ "javascript", "typescript", "vue" ], "eslint.options": { "extensions": [".js", ".ts", ".vue"] } } ``` ### WebStorm Settings 1. Go to Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint 2. Enable ESLint 3. Set configuration file to `.eslintrc.js` 4. Add `.vue` to file extensions