@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
JavaScript
"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