UNPKG

@samiyev/guardian

Version:

Research-backed code quality guardian for AI-assisted development. Detects hardcodes, secrets, circular deps, framework leaks, entity exposure, and 9 architecture violations. Enforces Clean Architecture/DDD principles. Works with GitHub Copilot, Cursor, W

508 lines 12.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EXTERNAL_PACKAGES = exports.ANEMIC_MODEL_FLAGS = exports.ANALYZER_DEFAULTS = exports.DETECTION_VALUES = exports.CONFIG_KEYWORDS = exports.DETECTION_PATTERNS = exports.REPOSITORY_VIOLATION_TYPES = exports.FRAMEWORK_LEAK_MESSAGES = exports.FRAMEWORK_PACKAGES = exports.USE_CASE_VERBS = exports.NAMING_PATTERNS = exports.NAMING_VIOLATION_TYPES = exports.LAYERS = exports.HARDCODE_TYPES = exports.RULES = void 0; /** * Rule names for code analysis */ exports.RULES = { CLEAN_ARCHITECTURE: "clean-architecture", HARDCODED_VALUE: "hardcoded-value", CIRCULAR_DEPENDENCY: "circular-dependency", NAMING_CONVENTION: "naming-convention", FRAMEWORK_LEAK: "framework-leak", ENTITY_EXPOSURE: "entity-exposure", DEPENDENCY_DIRECTION: "dependency-direction", REPOSITORY_PATTERN: "repository-pattern", AGGREGATE_BOUNDARY: "aggregate-boundary", SECRET_EXPOSURE: "secret-exposure", ANEMIC_MODEL: "anemic-model", }; /** * Hardcode types */ exports.HARDCODE_TYPES = { MAGIC_NUMBER: "magic-number", MAGIC_STRING: "magic-string", MAGIC_BOOLEAN: "magic-boolean", MAGIC_CONFIG: "magic-config", }; /** * Layer names */ exports.LAYERS = { DOMAIN: "domain", APPLICATION: "application", INFRASTRUCTURE: "infrastructure", SHARED: "shared", }; /** * Naming convention violation types */ exports.NAMING_VIOLATION_TYPES = { WRONG_SUFFIX: "wrong-suffix", WRONG_PREFIX: "wrong-prefix", WRONG_CASE: "wrong-case", FORBIDDEN_PATTERN: "forbidden-pattern", WRONG_VERB_NOUN: "wrong-verb-noun", }; /** * Naming patterns for each layer */ exports.NAMING_PATTERNS = { DOMAIN: { ENTITY: { pattern: /^[A-Z][a-zA-Z0-9]*\.ts$/, description: "PascalCase noun (User.ts, Order.ts)", forbidden: ["Dto", "Request", "Response", "Controller"], }, SERVICE: { pattern: /^[A-Z][a-zA-Z0-9]*Service\.ts$/, description: "*Service suffix (UserService.ts)", }, VALUE_OBJECT: { pattern: /^[A-Z][a-zA-Z0-9]*\.ts$/, description: "PascalCase noun (Email.ts, Money.ts)", }, REPOSITORY_INTERFACE: { pattern: /^I[A-Z][a-zA-Z0-9]*Repository\.ts$/, description: "I*Repository prefix (IUserRepository.ts)", }, }, APPLICATION: { USE_CASE: { pattern: /^[A-Z][a-z]+[A-Z][a-zA-Z0-9]*\.ts$/, description: "Verb in PascalCase (CreateUser.ts, UpdateProfile.ts)", examples: ["CreateUser.ts", "UpdateProfile.ts", "DeleteOrder.ts"], }, DTO: { pattern: /^[A-Z][a-zA-Z0-9]*(Dto|Request|Response)\.ts$/, description: "*Dto, *Request, *Response suffix", examples: ["UserResponseDto.ts", "CreateUserRequest.ts"], }, MAPPER: { pattern: /^[A-Z][a-zA-Z0-9]*Mapper\.ts$/, description: "*Mapper suffix (UserMapper.ts)", }, }, INFRASTRUCTURE: { CONTROLLER: { pattern: /^[A-Z][a-zA-Z0-9]*Controller\.ts$/, description: "*Controller suffix (UserController.ts)", }, REPOSITORY_IMPL: { pattern: /^[A-Z][a-zA-Z0-9]*Repository\.ts$/, description: "*Repository suffix (PrismaUserRepository.ts, MongoUserRepository.ts)", }, SERVICE: { pattern: /^[A-Z][a-zA-Z0-9]*(Service|Adapter)\.ts$/, description: "*Service or *Adapter suffix (EmailService.ts, S3StorageAdapter.ts)", }, }, }; /** * Common verbs for use cases */ exports.USE_CASE_VERBS = [ "Aggregate", "Analyze", "Approve", "Authenticate", "Authorize", "Calculate", "Cancel", "Collect", "Confirm", "Create", "Delete", "Execute", "Export", "Fetch", "Find", "Generate", "Get", "Handle", "Import", "List", "Parse", "Place", "Process", "Register", "Reject", "Search", "Send", "Update", "Validate", ]; /** * Framework-specific packages that should not be imported in domain layer * These frameworks create tight coupling and violate Clean Architecture principles */ exports.FRAMEWORK_PACKAGES = { ORM: [ "@prisma/client", "prisma", "typeorm", "mongoose", "sequelize", "@mikro-orm/core", "@mikro-orm/mongodb", "@mikro-orm/postgresql", "drizzle-orm", "knex", "objection", "bookshelf", "waterline", "massive", "pg", "mysql", "mysql2", "sqlite3", "better-sqlite3", "mongodb", "monk", "tingodb", "nedb", "levelup", "cassandra-driver", "couchbase", "redis-om", ], WEB_FRAMEWORK: [ "express", "fastify", "koa", "@koa/router", "koa-router", "@nestjs/common", "@nestjs/core", "@nestjs/platform-express", "@nestjs/platform-fastify", "hapi", "@hapi/hapi", "restify", "polka", "micro", "next", "nuxt", "sails", "adonis", "@adonisjs/core", "loopback", "@loopback/core", "feathers", "@feathersjs/feathers", "meteor", "strapi", "@strapi/strapi", "total.js", "actionhero", ], HTTP_CLIENT: [ "axios", "node-fetch", "got", "superagent", "request", "request-promise", "request-promise-native", "needle", "bent", "phin", "ky", "undici", "@apollo/client", "graphql-request", "urql", "isomorphic-fetch", "cross-fetch", "fetch-retry", "wretch", "httpie", ], VALIDATION: [ "joi", "yup", "zod", "class-validator", "ajv", "validator", "express-validator", "celebrate", "superstruct", "io-ts", "runtypes", "valibot", "fastest-validator", "validatorjs", "vine", "@vinejs/vine", "vest", "json-schema", "jsonschema", ], DI_CONTAINER: [ "inversify", "tsyringe", "awilix", "typedi", "bottlejs", "injection-js", "vue-di", "angular", "@angular/core", "di-ts", "power-di", ], LOGGER: [ "winston", "pino", "bunyan", "log4js", "morgan", "signale", "consola", "roarr", "loglevel", "debug", "npmlog", "@nestjs/logger", "fancy-log", "tracer", "electron-log", "simple-node-logger", ], CACHE: [ "redis", "ioredis", "memcached", "node-cache", "cache-manager", "keyv", "flat-cache", "lru-cache", "node-cache-manager", "quick-lru", "mem", "memoizee", "micro-memoize", "async-cache", "cacache", ], MESSAGE_QUEUE: [ "amqplib", "bull", "bullmq", "bee-queue", "kafkajs", "rabbitmq", "amqp", "aws-sdk", "@aws-sdk/client-sqs", "@aws-sdk/client-sns", "@azure/service-bus", "azure-sb", "@google-cloud/pubsub", "rsmq", "mqtt", "rhea", "stompit", "activemq", "zeromq", "nanomsg", "kue", "agenda", "bree", ], EMAIL: [ "nodemailer", "sendgrid", "@sendgrid/mail", "mailgun-js", "mailgun.js", "postmark", "sparkpost", "ses", "@aws-sdk/client-ses", "emailjs", "email-templates", "mjml", "pug", "handlebars", "sendmail", "smtp-server", "mailparser", "imap", "imap-simple", ], STORAGE: [ "aws-sdk", "@aws-sdk/client-s3", "@aws-sdk/s3-request-presigner", "multer", "multer-s3", "@google-cloud/storage", "@azure/storage-blob", "azure-storage", "minio", "formidable", "busboy", "multiparty", "express-fileupload", "gridfs-stream", "s3-upload-stream", "knox", "pkgcloud", "@supabase/storage-js", "cloudinary", ], TESTING: [ "jest", "@jest/globals", "mocha", "chai", "sinon", "supertest", "cypress", "@cypress/vue", "playwright", "@playwright/test", "vitest", "@vitest/ui", "ava", "tap", "tape", "jasmine", "@testing-library/react", "@testing-library/vue", "enzyme", ], TEMPLATE_ENGINE: [ "ejs", "pug", "jade", "handlebars", "mustache", "nunjucks", "dot", "underscore", "lodash.template", "hogan.js", "swig", "twig", "marko", "squirrelly", "eta", ], }; /** * Error messages for framework leak violations */ exports.FRAMEWORK_LEAK_MESSAGES = { DOMAIN_IMPORT: 'Domain layer imports framework-specific package "{package}". Use interfaces and dependency injection instead.', SUGGESTION: "Create an interface in domain layer and implement it in infrastructure layer.", PACKAGE_PLACEHOLDER: "{package}", }; /** * Repository pattern violation types */ exports.REPOSITORY_VIOLATION_TYPES = { ORM_TYPE_IN_INTERFACE: "orm-type-in-interface", CONCRETE_REPOSITORY_IN_USE_CASE: "concrete-repository-in-use-case", NEW_REPOSITORY_IN_USE_CASE: "new-repository-in-use-case", NON_DOMAIN_METHOD_NAME: "non-domain-method-name", }; /** * Detection patterns for sensitive keywords */ exports.DETECTION_PATTERNS = { SENSITIVE_KEYWORDS: ["password", "secret", "token", "auth", "credential"], BUSINESS_KEYWORDS: ["price", "salary", "balance", "amount", "limit", "threshold", "quota"], TECHNICAL_KEYWORDS: [ "timeout", "retry", "attempt", "maxretries", "database", "connection", "host", "port", "endpoint", ], MEDIUM_KEYWORDS: ["delay", "interval", "duration", "size", "count", "max", "min"], UI_KEYWORDS: [ "padding", "margin", "width", "height", "color", "style", "label", "title", "placeholder", "icon", "text", "display", ], }; /** * Configuration detection keywords */ exports.CONFIG_KEYWORDS = { NETWORK: ["endpoint", "host", "domain", "path", "route"], DATABASE: ["connection", "database"], SECURITY: ["config", "secret", "token", "password", "credential"], MESSAGES: [ "message", "error", "warning", "text", "description", "suggestion", "violation", "expected", "actual", ], TECHNICAL: [ "type", "node", "declaration", "definition", "signature", "pattern", "suffix", "prefix", ], }; /** * Detection comparison values */ exports.DETECTION_VALUES = { BOOLEAN_TRUE: "true", BOOLEAN_FALSE: "false", TYPE_CONFIG: "config", TYPE_GENERIC: "generic", }; /** * Boolean constants for analyzers */ exports.ANALYZER_DEFAULTS = { HAS_ONLY_GETTERS_SETTERS: false, HAS_PUBLIC_SETTERS: false, HAS_BUSINESS_LOGIC: false, }; /** * Anemic model detection flags */ exports.ANEMIC_MODEL_FLAGS = { HAS_ONLY_GETTERS_SETTERS_TRUE: true, HAS_ONLY_GETTERS_SETTERS_FALSE: false, HAS_PUBLIC_SETTERS_TRUE: true, HAS_PUBLIC_SETTERS_FALSE: false, }; /** * External package constants */ exports.EXTERNAL_PACKAGES = { SECRETLINT_PRESET: "@secretlint/secretlint-rule-preset-recommend", }; //# sourceMappingURL=rules.js.map