@cleartrip/frontguard 0.2.0 → 0.2.1

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.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,18 @@
1
1
  /** Phase 1: no merge blocking; `block` is reserved for later phases. */
2
2
  type Severity = 'info' | 'warn' | 'block';
3
3
 
4
+ /** Optional PR size tiers: total changed lines = additions + deletions (Bitbucket/git). */
5
+ interface PrSizeTier {
6
+ /** Fire when changed lines are >= this value. */
7
+ minLines: number;
8
+ severity: Severity;
9
+ /** Finding id (default: `pr-size-tier-0`, …) */
10
+ id?: string;
11
+ /**
12
+ * Message shown in report. Use `${lines}` for the current line count and `${min}` for this tier’s min.
13
+ */
14
+ message?: string;
15
+ }
4
16
  type GuardMode = 'warn' | 'enforce';
5
17
  /** Per-check gate: maps to Finding severity when violated. */
6
18
  type CheckGate = 'info' | 'warn' | 'block';
@@ -60,8 +72,21 @@ interface FrontGuardConfig {
60
72
  };
61
73
  prSize: {
62
74
  enabled: boolean;
75
+ /**
76
+ * Default “elevated” threshold (info) when `tiers` is omitted.
77
+ * @deprecated Prefer `tiers` for custom limits and severities.
78
+ */
63
79
  warnLines: number;
80
+ /**
81
+ * Default “very large” threshold (warn) when `tiers` is omitted.
82
+ * @deprecated Prefer `tiers`.
83
+ */
64
84
  softBlockLines: number;
85
+ /**
86
+ * Custom thresholds on total changed lines. All tiers where `lines >= minLines` produce a finding (largest `minLines` first in report order).
87
+ * When set (non-empty), `warnLines` / `softBlockLines` are ignored.
88
+ */
89
+ tiers?: PrSizeTier[];
65
90
  };
66
91
  /** Count new `any` usage introduced in the diff vs merge-base (requires git). */
67
92
  tsAnyDelta: {
@@ -110,8 +135,11 @@ interface FrontGuardConfig {
110
135
  maxDeltaBytes: number | null;
111
136
  maxTotalBytes: number | null;
112
137
  };
113
- /** Heuristic “web vitals hygiene” for Next/React web (not RN). */
114
- cwv: {
138
+ /**
139
+ * Core Web Vitals hygiene (static heuristics for Next/React web; not React Native).
140
+ * Report check id: `core-web-vitals`.
141
+ */
142
+ coreWebVitals: {
115
143
  enabled: boolean;
116
144
  gate: CheckGate;
117
145
  scanGlobs: string[];
@@ -149,4 +177,4 @@ declare const defaultConfig: FrontGuardConfig;
149
177
  */
150
178
  declare function defineConfig(partial: Partial<FrontGuardConfig>): FrontGuardConfig;
151
179
 
152
- export { type CheckGate, type CustomRuleDefinition, type FrontGuardConfig, type GuardMode, type RuleFileContext, type RulesMap, defaultConfig, defineConfig };
180
+ export { type CheckGate, type CustomRuleDefinition, type FrontGuardConfig, type GuardMode, type PrSizeTier, type RuleFileContext, type RulesMap, defaultConfig, defineConfig };
package/dist/index.js CHANGED
@@ -112,7 +112,7 @@ var defaultConfig = {
112
112
  maxDeltaBytes: null,
113
113
  maxTotalBytes: null
114
114
  },
115
- cwv: {
115
+ coreWebVitals: {
116
116
  enabled: true,
117
117
  gate: "warn",
118
118
  scanGlobs: ["app/**/*.{tsx,jsx}", "pages/**/*.{tsx,jsx}", "src/**/*.{tsx,jsx}"],
@@ -133,8 +133,19 @@ var defaultConfig = {
133
133
  }
134
134
  };
135
135
 
136
+ // src/config/migrate.ts
137
+ function migrateLegacyConfigKeys(config) {
138
+ const ch = config.checks;
139
+ if (!ch) return;
140
+ if ("cwv" in ch && !("coreWebVitals" in ch)) {
141
+ ch.coreWebVitals = ch.cwv;
142
+ delete ch.cwv;
143
+ }
144
+ }
145
+
136
146
  // src/index.ts
137
147
  function defineConfig(partial) {
148
+ migrateLegacyConfigKeys(partial);
138
149
  return defu(partial, defaultConfig);
139
150
  }
140
151
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/defu/dist/defu.mjs","../src/config/defaults.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["function isPlainObject(value) {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {\n return false;\n }\n if (Symbol.iterator in value) {\n return false;\n }\n if (Symbol.toStringTag in value) {\n return Object.prototype.toString.call(value) === \"[object Module]\";\n }\n return true;\n}\n\nfunction _defu(baseObject, defaults, namespace = \".\", merger) {\n if (!isPlainObject(defaults)) {\n return _defu(baseObject, {}, namespace, merger);\n }\n const object = { ...defaults };\n for (const key of Object.keys(baseObject)) {\n if (key === \"__proto__\" || key === \"constructor\") {\n continue;\n }\n const value = baseObject[key];\n if (value === null || value === void 0) {\n continue;\n }\n if (merger && merger(object, key, value, namespace)) {\n continue;\n }\n if (Array.isArray(value) && Array.isArray(object[key])) {\n object[key] = [...value, ...object[key]];\n } else if (isPlainObject(value) && isPlainObject(object[key])) {\n object[key] = _defu(\n value,\n object[key],\n (namespace ? `${namespace}.` : \"\") + key.toString(),\n merger\n );\n } else {\n object[key] = value;\n }\n }\n return object;\n}\nfunction createDefu(merger) {\n return (...arguments_) => (\n // eslint-disable-next-line unicorn/no-array-reduce\n arguments_.reduce((p, c) => _defu(p, c, \"\", merger), {})\n );\n}\nconst defu = createDefu();\nconst defuFn = createDefu((object, key, currentValue) => {\n if (object[key] !== void 0 && typeof currentValue === \"function\") {\n object[key] = currentValue(object[key]);\n return true;\n }\n});\nconst defuArrayFn = createDefu((object, key, currentValue) => {\n if (Array.isArray(object[key]) && typeof currentValue === \"function\") {\n object[key] = currentValue(object[key]);\n return true;\n }\n});\n\nexport { createDefu, defu as default, defu, defuArrayFn, defuFn };\n","import type { FrontGuardConfig } from './schema.js'\n\nexport const defaultConfig: FrontGuardConfig = {\n mode: 'warn',\n rules: {},\n checks: {\n eslint: { enabled: true, glob: '**/*.{js,cjs,mjs,jsx,ts,tsx}' },\n prettier: {\n enabled: true,\n glob: '**/*.{js,cjs,mjs,jsx,ts,tsx,json,md,css,scss,yml,yaml}',\n },\n typescript: { enabled: true },\n secrets: { enabled: true },\n prHygiene: {\n enabled: true,\n minBodyLength: 80,\n requireSections: false,\n sectionHints: ['what', 'why', 'test', 'how to test', 'screenshot'],\n requireAiDisclosureSection: true,\n gateWhenAiDisclosureAmbiguous: 'warn',\n },\n aiAssistedReview: {\n enabled: true,\n gate: 'warn',\n escalate: {\n secretFindingsToBlock: true,\n tsAnyDeltaToBlock: true,\n },\n },\n prSize: { enabled: true, warnLines: 400, softBlockLines: 800 },\n\n tsAnyDelta: {\n enabled: true,\n gate: 'warn',\n baseRef: 'main',\n maxAdded: 0,\n },\n cycles: {\n enabled: true,\n gate: 'warn',\n entries: ['src'],\n extraArgs: [],\n },\n deadCode: {\n enabled: true,\n gate: 'info',\n extraArgs: [],\n maxReportLines: 80,\n },\n bundle: {\n enabled: true,\n gate: 'warn',\n runBuild: true,\n buildCommand: 'npm run build',\n measureGlobs: ['dist/**/*', 'build/static/**/*', '.next/static/**/*'],\n baselinePath: '.frontguard/bundle-baseline.json',\n baselineRef: 'main',\n maxDeltaBytes: null,\n maxTotalBytes: null,\n },\n cwv: {\n enabled: true,\n gate: 'warn',\n scanGlobs: ['app/**/*.{tsx,jsx}', 'pages/**/*.{tsx,jsx}', 'src/**/*.{tsx,jsx}'],\n maxFileBytes: 400_000,\n },\n llm: {\n enabled: false,\n provider: 'openai',\n model: 'gpt-4o-mini',\n apiKeyEnv: 'OPENAI_API_KEY',\n maxDiffChars: 48_000,\n timeoutMs: 60_000,\n ollamaUrl: 'http://127.0.0.1:11434',\n perFindingFixes: false,\n maxFixSuggestions: 12,\n maxFileContextChars: 24_000,\n },\n },\n}\n","import defu from 'defu'\nimport type { FrontGuardConfig } from './config/schema.js'\nimport { defaultConfig } from './config/defaults.js'\n\nexport type {\n FrontGuardConfig,\n GuardMode,\n CheckGate,\n RulesMap,\n CustomRuleDefinition,\n RuleFileContext,\n} from './config/schema.js'\nexport { defaultConfig } from './config/defaults.js'\n\n/**\n * Define repo-level config; shallow-merged over built-in defaults.\n * Org packages can be referenced via `extends` in config file.\n */\nexport function defineConfig(partial: Partial<FrontGuardConfig>): FrontGuardConfig {\n return defu(partial, defaultConfig) as FrontGuardConfig\n}\n"]}
1
+ {"version":3,"sources":["../node_modules/defu/dist/defu.mjs","../src/config/defaults.ts","../src/config/migrate.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["function isPlainObject(value) {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {\n return false;\n }\n if (Symbol.iterator in value) {\n return false;\n }\n if (Symbol.toStringTag in value) {\n return Object.prototype.toString.call(value) === \"[object Module]\";\n }\n return true;\n}\n\nfunction _defu(baseObject, defaults, namespace = \".\", merger) {\n if (!isPlainObject(defaults)) {\n return _defu(baseObject, {}, namespace, merger);\n }\n const object = { ...defaults };\n for (const key of Object.keys(baseObject)) {\n if (key === \"__proto__\" || key === \"constructor\") {\n continue;\n }\n const value = baseObject[key];\n if (value === null || value === void 0) {\n continue;\n }\n if (merger && merger(object, key, value, namespace)) {\n continue;\n }\n if (Array.isArray(value) && Array.isArray(object[key])) {\n object[key] = [...value, ...object[key]];\n } else if (isPlainObject(value) && isPlainObject(object[key])) {\n object[key] = _defu(\n value,\n object[key],\n (namespace ? `${namespace}.` : \"\") + key.toString(),\n merger\n );\n } else {\n object[key] = value;\n }\n }\n return object;\n}\nfunction createDefu(merger) {\n return (...arguments_) => (\n // eslint-disable-next-line unicorn/no-array-reduce\n arguments_.reduce((p, c) => _defu(p, c, \"\", merger), {})\n );\n}\nconst defu = createDefu();\nconst defuFn = createDefu((object, key, currentValue) => {\n if (object[key] !== void 0 && typeof currentValue === \"function\") {\n object[key] = currentValue(object[key]);\n return true;\n }\n});\nconst defuArrayFn = createDefu((object, key, currentValue) => {\n if (Array.isArray(object[key]) && typeof currentValue === \"function\") {\n object[key] = currentValue(object[key]);\n return true;\n }\n});\n\nexport { createDefu, defu as default, defu, defuArrayFn, defuFn };\n","import type { FrontGuardConfig } from './schema.js'\n\nexport const defaultConfig: FrontGuardConfig = {\n mode: 'warn',\n rules: {},\n checks: {\n eslint: { enabled: true, glob: '**/*.{js,cjs,mjs,jsx,ts,tsx}' },\n prettier: {\n enabled: true,\n glob: '**/*.{js,cjs,mjs,jsx,ts,tsx,json,md,css,scss,yml,yaml}',\n },\n typescript: { enabled: true },\n secrets: { enabled: true },\n prHygiene: {\n enabled: true,\n minBodyLength: 80,\n requireSections: false,\n sectionHints: ['what', 'why', 'test', 'how to test', 'screenshot'],\n requireAiDisclosureSection: true,\n gateWhenAiDisclosureAmbiguous: 'warn',\n },\n aiAssistedReview: {\n enabled: true,\n gate: 'warn',\n escalate: {\n secretFindingsToBlock: true,\n tsAnyDeltaToBlock: true,\n },\n },\n prSize: { enabled: true, warnLines: 400, softBlockLines: 800 },\n\n tsAnyDelta: {\n enabled: true,\n gate: 'warn',\n baseRef: 'main',\n maxAdded: 0,\n },\n cycles: {\n enabled: true,\n gate: 'warn',\n entries: ['src'],\n extraArgs: [],\n },\n deadCode: {\n enabled: true,\n gate: 'info',\n extraArgs: [],\n maxReportLines: 80,\n },\n bundle: {\n enabled: true,\n gate: 'warn',\n runBuild: true,\n buildCommand: 'npm run build',\n measureGlobs: ['dist/**/*', 'build/static/**/*', '.next/static/**/*'],\n baselinePath: '.frontguard/bundle-baseline.json',\n baselineRef: 'main',\n maxDeltaBytes: null,\n maxTotalBytes: null,\n },\n coreWebVitals: {\n enabled: true,\n gate: 'warn',\n scanGlobs: ['app/**/*.{tsx,jsx}', 'pages/**/*.{tsx,jsx}', 'src/**/*.{tsx,jsx}'],\n maxFileBytes: 400_000,\n },\n llm: {\n enabled: false,\n provider: 'openai',\n model: 'gpt-4o-mini',\n apiKeyEnv: 'OPENAI_API_KEY',\n maxDiffChars: 48_000,\n timeoutMs: 60_000,\n ollamaUrl: 'http://127.0.0.1:11434',\n perFindingFixes: false,\n maxFixSuggestions: 12,\n maxFileContextChars: 24_000,\n },\n },\n}\n","import type { FrontGuardConfig } from './schema.js'\n\n/** Normalize legacy config keys before merging with defaults. */\nexport function migrateLegacyConfigKeys(config: Partial<FrontGuardConfig>): void {\n const ch = config.checks as Record<string, unknown> | undefined\n if (!ch) return\n if ('cwv' in ch && !('coreWebVitals' in ch)) {\n ch.coreWebVitals = ch.cwv\n delete ch.cwv\n }\n}\n","import defu from 'defu'\nimport type { FrontGuardConfig } from './config/schema.js'\nimport { defaultConfig } from './config/defaults.js'\nimport { migrateLegacyConfigKeys } from './config/migrate.js'\n\nexport type {\n FrontGuardConfig,\n GuardMode,\n CheckGate,\n RulesMap,\n CustomRuleDefinition,\n RuleFileContext,\n PrSizeTier,\n} from './config/schema.js'\nexport { defaultConfig } from './config/defaults.js'\n\n/**\n * Define repo-level config; shallow-merged over built-in defaults.\n * Org packages can be referenced via `extends` in config file.\n */\nexport function defineConfig(partial: Partial<FrontGuardConfig>): FrontGuardConfig {\n migrateLegacyConfigKeys(partial)\n return defu(partial, defaultConfig) as FrontGuardConfig\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleartrip/frontguard",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Org-wide frontend PR guardrails: linting, hygiene, any-delta, cycles, dead code, bundle/CWV hints, custom rules, optional LLM brief",
5
5
  "type": "module",
6
6
  "bin": {