@empline/preflight 1.1.3 → 1.1.4
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/checks/card-processing/dimension-variance-blocking.d.ts +8 -0
- package/dist/checks/card-processing/dimension-variance-blocking.d.ts.map +1 -0
- package/dist/checks/card-processing/dimension-variance-blocking.js +256 -0
- package/dist/checks/card-processing/dimension-variance-blocking.js.map +1 -0
- package/dist/checks/card-processing/edge-detection-integration.d.ts +8 -0
- package/dist/checks/card-processing/edge-detection-integration.d.ts.map +1 -0
- package/dist/checks/card-processing/edge-detection-integration.js +180 -0
- package/dist/checks/card-processing/edge-detection-integration.js.map +1 -0
- package/dist/checks/card-processing/front-back-detection-validation.d.ts +8 -0
- package/dist/checks/card-processing/front-back-detection-validation.d.ts.map +1 -0
- package/dist/checks/card-processing/front-back-detection-validation.js +83 -0
- package/dist/checks/card-processing/front-back-detection-validation.js.map +1 -0
- package/dist/checks/card-processing/image-deskew-system.d.ts +8 -0
- package/dist/checks/card-processing/image-deskew-system.d.ts.map +1 -0
- package/dist/checks/card-processing/image-deskew-system.js +62 -0
- package/dist/checks/card-processing/image-deskew-system.js.map +1 -0
- package/dist/checks/card-processing/image-filename-uniqueness.d.ts +8 -0
- package/dist/checks/card-processing/image-filename-uniqueness.d.ts.map +1 -0
- package/dist/checks/card-processing/image-filename-uniqueness.js +229 -0
- package/dist/checks/card-processing/image-filename-uniqueness.js.map +1 -0
- package/dist/checks/card-processing/image-processing-config-validation.d.ts +8 -0
- package/dist/checks/card-processing/image-processing-config-validation.d.ts.map +1 -0
- package/dist/checks/card-processing/image-processing-config-validation.js +440 -0
- package/dist/checks/card-processing/image-processing-config-validation.js.map +1 -0
- package/dist/checks/code-quality/price-formatting-consistency.d.ts +28 -0
- package/dist/checks/code-quality/price-formatting-consistency.d.ts.map +1 -0
- package/dist/checks/code-quality/price-formatting-consistency.js +230 -0
- package/dist/checks/code-quality/price-formatting-consistency.js.map +1 -0
- package/dist/checks/data/constants-validation.d.ts +19 -0
- package/dist/checks/data/constants-validation.d.ts.map +1 -0
- package/dist/checks/data/constants-validation.js +297 -0
- package/dist/checks/data/constants-validation.js.map +1 -0
- package/dist/checks/data/crockford-id-validation.d.ts +24 -0
- package/dist/checks/data/crockford-id-validation.d.ts.map +1 -0
- package/dist/checks/data/crockford-id-validation.js +227 -0
- package/dist/checks/data/crockford-id-validation.js.map +1 -0
- package/dist/checks/data/geographic-constants-validation.d.ts +16 -0
- package/dist/checks/data/geographic-constants-validation.d.ts.map +1 -0
- package/dist/checks/data/geographic-constants-validation.js +168 -0
- package/dist/checks/data/geographic-constants-validation.js.map +1 -0
- package/dist/checks/data/hardcoded-options-validation.d.ts +24 -0
- package/dist/checks/data/hardcoded-options-validation.d.ts.map +1 -0
- package/dist/checks/data/hardcoded-options-validation.js +362 -0
- package/dist/checks/data/hardcoded-options-validation.js.map +1 -0
- package/dist/checks/data/league-data-integrity-with-env.d.ts +14 -0
- package/dist/checks/data/league-data-integrity-with-env.d.ts.map +1 -0
- package/dist/checks/data/league-data-integrity-with-env.js +21 -0
- package/dist/checks/data/league-data-integrity-with-env.js.map +1 -0
- package/dist/checks/data/product-slug-architecture.d.ts +36 -0
- package/dist/checks/data/product-slug-architecture.d.ts.map +1 -0
- package/dist/checks/data/product-slug-architecture.js +167 -0
- package/dist/checks/data/product-slug-architecture.js.map +1 -0
- package/dist/checks/data/schema-fk-defaults-validation.d.ts +21 -0
- package/dist/checks/data/schema-fk-defaults-validation.d.ts.map +1 -0
- package/dist/checks/data/schema-fk-defaults-validation.js +168 -0
- package/dist/checks/data/schema-fk-defaults-validation.js.map +1 -0
- package/dist/checks/ui/admin-filter-patterns.d.ts +27 -0
- package/dist/checks/ui/admin-filter-patterns.d.ts.map +1 -0
- package/dist/checks/ui/admin-filter-patterns.js +225 -0
- package/dist/checks/ui/admin-filter-patterns.js.map +1 -0
- package/dist/checks/ui/form-field-variant-consistency.d.ts +28 -0
- package/dist/checks/ui/form-field-variant-consistency.d.ts.map +1 -0
- package/dist/checks/ui/form-field-variant-consistency.js +218 -0
- package/dist/checks/ui/form-field-variant-consistency.js.map +1 -0
- package/dist/checks/ui/integration-component-consolidation.d.ts +47 -0
- package/dist/checks/ui/integration-component-consolidation.d.ts.map +1 -0
- package/dist/checks/ui/integration-component-consolidation.js +383 -0
- package/dist/checks/ui/integration-component-consolidation.js.map +1 -0
- package/dist/checks/ui/notification-system-consistency.d.ts +42 -0
- package/dist/checks/ui/notification-system-consistency.d.ts.map +1 -0
- package/dist/checks/ui/notification-system-consistency.js +243 -0
- package/dist/checks/ui/notification-system-consistency.js.map +1 -0
- package/dist/utils/console-chars.d.ts +18 -10
- package/dist/utils/console-chars.d.ts.map +1 -1
- package/dist/utils/console-chars.js +19 -5
- package/dist/utils/console-chars.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Price Formatting Consistency Preflight
|
|
5
|
+
*
|
|
6
|
+
* Detects inline price/currency formatting that should use centralized utilities.
|
|
7
|
+
*
|
|
8
|
+
* Anti-patterns detected:
|
|
9
|
+
* - .toFixed(2) near price/amount/cost variables
|
|
10
|
+
* - toLocaleString() with currency formatting options
|
|
11
|
+
* - Manual "$" + value patterns
|
|
12
|
+
* - Number formatting without formatCurrency/formatMoneyFixed
|
|
13
|
+
*
|
|
14
|
+
* Correct patterns:
|
|
15
|
+
* - formatCurrency() from @/lib/utils/format
|
|
16
|
+
* - formatMoneyFixed() from @/lib/utils/format
|
|
17
|
+
* - formatNumber() from @/lib/utils/format
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* pnpm preflight:price-formatting
|
|
21
|
+
* pnpm preflight:price-formatting --verbose
|
|
22
|
+
*/
|
|
23
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(o, k2, desc);
|
|
30
|
+
}) : (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
o[k2] = m[k];
|
|
33
|
+
}));
|
|
34
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
+
}) : function(o, v) {
|
|
37
|
+
o["default"] = v;
|
|
38
|
+
});
|
|
39
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
40
|
+
var ownKeys = function(o) {
|
|
41
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
42
|
+
var ar = [];
|
|
43
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
+
return ar;
|
|
45
|
+
};
|
|
46
|
+
return ownKeys(o);
|
|
47
|
+
};
|
|
48
|
+
return function (mod) {
|
|
49
|
+
if (mod && mod.__esModule) return mod;
|
|
50
|
+
var result = {};
|
|
51
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
52
|
+
__setModuleDefault(result, mod);
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
})();
|
|
56
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
+
exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
|
|
58
|
+
const fs = __importStar(require("fs"));
|
|
59
|
+
const glob_1 = require("glob");
|
|
60
|
+
const console_chars_1 = require("../../utils/console-chars");
|
|
61
|
+
const exclusions_1 = require("../../shared/exclusions");
|
|
62
|
+
let appExclusions = [];
|
|
63
|
+
// METADATA
|
|
64
|
+
exports.id = "code-quality/price-formatting-consistency";
|
|
65
|
+
exports.name = "Price Formatting Consistency";
|
|
66
|
+
exports.description = "Detects inline price formatting - use formatCurrency instead";
|
|
67
|
+
exports.category = "code-quality";
|
|
68
|
+
exports.blocking = false;
|
|
69
|
+
exports.tags = ["code-quality", "formatting", "price", "currency"];
|
|
70
|
+
// Anti-patterns - with context indicators
|
|
71
|
+
const ANTI_PATTERNS = [
|
|
72
|
+
{
|
|
73
|
+
// .toFixed(2) near price-related context
|
|
74
|
+
pattern: /(?:price|amount|cost|total|balance|fee|value|revenue|profit|sale)[\w.]*\.toFixed\s*\(\s*2\s*\)/gi,
|
|
75
|
+
name: "toFixed-price",
|
|
76
|
+
message: "Using .toFixed(2) for price formatting",
|
|
77
|
+
suggestion: "Use formatMoneyFixed(value) from @/lib/utils/format",
|
|
78
|
+
severity: "info",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
// Manual dollar sign concatenation
|
|
82
|
+
pattern: /["'`]\$["'`]\s*\+\s*(?:price|amount|cost|total|value)/gi,
|
|
83
|
+
name: "manual-dollar-concat",
|
|
84
|
+
message: "Manual dollar sign concatenation for currency",
|
|
85
|
+
suggestion: "Use formatCurrency(value) from @/lib/utils/format",
|
|
86
|
+
severity: "info",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
// Template literal with $ and toFixed
|
|
90
|
+
pattern: /\$\$\{[^}]*\.toFixed\s*\(\s*2\s*\)\}/g,
|
|
91
|
+
name: "template-toFixed",
|
|
92
|
+
message: "Template literal with toFixed for currency",
|
|
93
|
+
suggestion: "Use formatCurrency(value) from @/lib/utils/format",
|
|
94
|
+
severity: "info",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
// toLocaleString with currency style
|
|
98
|
+
pattern: /\.toLocaleString\s*\([^)]*style:\s*["']currency["']/g,
|
|
99
|
+
name: "toLocaleString-currency",
|
|
100
|
+
message: "Using toLocaleString with currency style",
|
|
101
|
+
suggestion: "Use formatCurrency(value) from @/lib/utils/format for consistency",
|
|
102
|
+
severity: "info",
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
// Good patterns that indicate proper handling
|
|
106
|
+
const GOOD_PATTERNS = [
|
|
107
|
+
/import\s*\{[^}]*formatCurrency[^}]*\}\s*from/,
|
|
108
|
+
/import\s*\{[^}]*formatMoneyFixed[^}]*\}\s*from/,
|
|
109
|
+
/formatCurrency\s*\(/,
|
|
110
|
+
/formatMoneyFixed\s*\(/,
|
|
111
|
+
];
|
|
112
|
+
// Files to skip (format utilities themselves)
|
|
113
|
+
const SKIP_FILES = [
|
|
114
|
+
"lib/utils/format.ts",
|
|
115
|
+
"lib/format-utils.ts",
|
|
116
|
+
"lib/locale-utils.ts",
|
|
117
|
+
];
|
|
118
|
+
async function findSourceFiles() {
|
|
119
|
+
const patterns = [
|
|
120
|
+
"app/**/*.tsx",
|
|
121
|
+
"app/**/*.ts",
|
|
122
|
+
"components/**/*.tsx",
|
|
123
|
+
"components/**/*.ts",
|
|
124
|
+
"lib/**/*.ts",
|
|
125
|
+
];
|
|
126
|
+
const allFiles = [];
|
|
127
|
+
for (const pattern of patterns) {
|
|
128
|
+
const matches = await (0, glob_1.glob)(pattern, {
|
|
129
|
+
ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.stories.tsx", "**/*.d.ts"],
|
|
130
|
+
});
|
|
131
|
+
allFiles.push(...matches);
|
|
132
|
+
}
|
|
133
|
+
return allFiles.filter((file) => {
|
|
134
|
+
if ((0, exclusions_1.shouldExcludeFile)(file, appExclusions))
|
|
135
|
+
return false;
|
|
136
|
+
if (SKIP_FILES.some((skip) => file.includes(skip)))
|
|
137
|
+
return false;
|
|
138
|
+
return true;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function checkFile(filePath, content) {
|
|
142
|
+
const issues = [];
|
|
143
|
+
const lines = content.split("\n");
|
|
144
|
+
// Check if file imports formatting utilities
|
|
145
|
+
const hasGoodPattern = GOOD_PATTERNS.some((pattern) => pattern.test(content));
|
|
146
|
+
// If file already uses format utilities, lower severity of issues
|
|
147
|
+
for (const antiPattern of ANTI_PATTERNS) {
|
|
148
|
+
// Reset lastIndex for global patterns
|
|
149
|
+
antiPattern.pattern.lastIndex = 0;
|
|
150
|
+
let match;
|
|
151
|
+
while ((match = antiPattern.pattern.exec(content)) !== null) {
|
|
152
|
+
let lineNumber = 1;
|
|
153
|
+
let charCount = 0;
|
|
154
|
+
for (let i = 0; i < lines.length; i++) {
|
|
155
|
+
charCount += lines[i].length + 1;
|
|
156
|
+
if (charCount > match.index) {
|
|
157
|
+
lineNumber = i + 1;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
issues.push({
|
|
162
|
+
file: filePath,
|
|
163
|
+
line: lineNumber,
|
|
164
|
+
severity: hasGoodPattern ? "info" : antiPattern.severity,
|
|
165
|
+
message: antiPattern.message,
|
|
166
|
+
suggestion: antiPattern.suggestion,
|
|
167
|
+
code: antiPattern.name,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return { file: filePath, issues };
|
|
172
|
+
}
|
|
173
|
+
async function main() {
|
|
174
|
+
const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
|
|
175
|
+
console.log(`${console_chars_1.emoji.search} Price Formatting Consistency Preflight`);
|
|
176
|
+
console.log((0, console_chars_1.createDivider)(60, "heavy"));
|
|
177
|
+
appExclusions = await (0, exclusions_1.getExclusions)(exports.id);
|
|
178
|
+
const files = await findSourceFiles();
|
|
179
|
+
console.log(`Scanning ${files.length} source files...\n`);
|
|
180
|
+
const results = [];
|
|
181
|
+
const allIssues = [];
|
|
182
|
+
for (const file of files) {
|
|
183
|
+
try {
|
|
184
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
185
|
+
const result = checkFile(file, content);
|
|
186
|
+
results.push(result);
|
|
187
|
+
allIssues.push(...result.issues);
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Skip files that can't be read
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const warnings = allIssues.filter((i) => i.severity === "warning");
|
|
194
|
+
const info = allIssues.filter((i) => i.severity === "info");
|
|
195
|
+
if (warnings.length > 0) {
|
|
196
|
+
console.log(`${console_chars_1.emoji.warning} WARNINGS:`);
|
|
197
|
+
console.log((0, console_chars_1.createDivider)(60, "light"));
|
|
198
|
+
for (const issue of warnings) {
|
|
199
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
200
|
+
console.log(` ${issue.message}`);
|
|
201
|
+
if (verbose) {
|
|
202
|
+
console.log(` ${console_chars_1.emoji.hint} ${issue.suggestion}`);
|
|
203
|
+
}
|
|
204
|
+
console.log("");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (verbose && info.length > 0) {
|
|
208
|
+
console.log(`${console_chars_1.emoji.info} INFO:`);
|
|
209
|
+
console.log((0, console_chars_1.createDivider)(60, "light"));
|
|
210
|
+
for (const issue of info) {
|
|
211
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
212
|
+
console.log(` ${issue.message}`);
|
|
213
|
+
console.log("");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
console.log((0, console_chars_1.createDivider)(60, "heavy"));
|
|
217
|
+
console.log(`Files scanned: ${files.length}`);
|
|
218
|
+
console.log(`Warnings: ${warnings.length}`);
|
|
219
|
+
console.log(`Info: ${info.length}`);
|
|
220
|
+
if (warnings.length === 0 && info.length === 0) {
|
|
221
|
+
console.log(`\n${console_chars_1.emoji.success} Price formatting is consistent`);
|
|
222
|
+
}
|
|
223
|
+
console.log(`\n${console_chars_1.emoji.docs} Canonical imports:`);
|
|
224
|
+
console.log(` ${console_chars_1.chars.bullet} import { formatCurrency, formatMoneyFixed } from "@/lib/utils/format"`);
|
|
225
|
+
console.log(` ${console_chars_1.chars.bullet} formatCurrency(amount) - for display with $ symbol`);
|
|
226
|
+
console.log(` ${console_chars_1.chars.bullet} formatMoneyFixed(amount, decimals) - for fixed decimal formatting`);
|
|
227
|
+
process.exit(0);
|
|
228
|
+
}
|
|
229
|
+
main().catch(console.error);
|
|
230
|
+
//# sourceMappingURL=price-formatting-consistency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-formatting-consistency.js","sourceRoot":"","sources":["../../../src/checks/code-quality/price-formatting-consistency.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Constants Validation Preflight
|
|
4
|
+
*
|
|
5
|
+
* Ensures all constants are imported from centralized locations:
|
|
6
|
+
* - Geographic: @/lib/constants/geographic
|
|
7
|
+
* - Enums: @/lib/constants/enums
|
|
8
|
+
* - Shipping: @/lib/constants/shipping
|
|
9
|
+
* - Limits: @/lib/constants/limits
|
|
10
|
+
*
|
|
11
|
+
* Run: pnpm preflight:constants
|
|
12
|
+
*/
|
|
13
|
+
export declare const id = "data/constants-validation";
|
|
14
|
+
export declare const name = "Constants Validation";
|
|
15
|
+
export declare const description = "Ensures all constants are imported from centralized locations";
|
|
16
|
+
export declare const category = "data";
|
|
17
|
+
export declare const blocking = true;
|
|
18
|
+
export declare const tags: string[];
|
|
19
|
+
//# sourceMappingURL=constants-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-validation.d.ts","sourceRoot":"","sources":["../../../src/checks/data/constants-validation.ts"],"names":[],"mappings":";AASA;;;;;;;;;;GAUG;AAIH,eAAO,MAAM,EAAE,8BAA8B,CAAC;AAC9C,eAAO,MAAM,IAAI,yBAAyB,CAAC;AAC3C,eAAO,MAAM,WAAW,kEAAkE,CAAC;AAC3F,eAAO,MAAM,QAAQ,SAAS,CAAC;AAC/B,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAA0C,CAAC"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const glob_1 = require("glob");
|
|
10
|
+
const console_chars_1 = require("../../utils/console-chars");
|
|
11
|
+
const exclusions_1 = require("../../shared/exclusions");
|
|
12
|
+
// App-specific exclusions loaded from config
|
|
13
|
+
let appExclusions = [];
|
|
14
|
+
/**
|
|
15
|
+
* Constants Validation Preflight
|
|
16
|
+
*
|
|
17
|
+
* Ensures all constants are imported from centralized locations:
|
|
18
|
+
* - Geographic: @/lib/constants/geographic
|
|
19
|
+
* - Enums: @/lib/constants/enums
|
|
20
|
+
* - Shipping: @/lib/constants/shipping
|
|
21
|
+
* - Limits: @/lib/constants/limits
|
|
22
|
+
*
|
|
23
|
+
* Run: pnpm preflight:constants
|
|
24
|
+
*/
|
|
25
|
+
// METADATA - Required for plugin loader discovery
|
|
26
|
+
exports.id = "data/constants-validation";
|
|
27
|
+
exports.name = "Constants Validation";
|
|
28
|
+
exports.description = "Ensures all constants are imported from centralized locations";
|
|
29
|
+
exports.category = "data";
|
|
30
|
+
exports.blocking = true;
|
|
31
|
+
exports.tags = ["data", "constants", "centralization"];
|
|
32
|
+
// PATTERNS TO DETECT
|
|
33
|
+
const CONSTANT_PATTERNS = {
|
|
34
|
+
// Geographic constants
|
|
35
|
+
geographic: {
|
|
36
|
+
patterns: [
|
|
37
|
+
/const\s+US_STATES\s*=\s*\[/,
|
|
38
|
+
/const\s+COUNTRIES\s*=\s*\[/,
|
|
39
|
+
/const\s+CA_PROVINCES\s*=\s*\[/,
|
|
40
|
+
/const\s+US_STATE_CODES\s*=\s*\[/,
|
|
41
|
+
/const\s+COUNTRY_CODES\s*=\s*\[/,
|
|
42
|
+
/export\s+const\s+US_STATES\s*=\s*\[/,
|
|
43
|
+
/export\s+const\s+COUNTRIES\s*=\s*\[/,
|
|
44
|
+
/export\s+const\s+CA_PROVINCES\s*=\s*\[/,
|
|
45
|
+
],
|
|
46
|
+
source: "@/lib/constants/geographic",
|
|
47
|
+
names: ["US_STATES", "COUNTRIES", "CA_PROVINCES", "US_STATE_CODES", "COUNTRY_CODES"],
|
|
48
|
+
},
|
|
49
|
+
// Enum constants (status options)
|
|
50
|
+
enums: {
|
|
51
|
+
patterns: [
|
|
52
|
+
/const\s+ORDER_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
53
|
+
/const\s+LISTING_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
54
|
+
/const\s+APPROVAL_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
55
|
+
/const\s+STORE_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
56
|
+
/const\s+PLATFORM_OPTIONS\s*[=:]\s*\[/,
|
|
57
|
+
/const\s+PRODUCT_TYPE_OPTIONS\s*[=:]\s*\[/,
|
|
58
|
+
/export\s+const\s+ORDER_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
59
|
+
/export\s+const\s+LISTING_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
60
|
+
/export\s+const\s+APPROVAL_STATUS_OPTIONS\s*[=:]\s*\[/,
|
|
61
|
+
/export\s+const\s+PLATFORM_OPTIONS\s*[=:]\s*\[/,
|
|
62
|
+
],
|
|
63
|
+
source: "@/lib/constants/enums",
|
|
64
|
+
names: [
|
|
65
|
+
"ORDER_STATUS_OPTIONS",
|
|
66
|
+
"LISTING_STATUS_OPTIONS",
|
|
67
|
+
"APPROVAL_STATUS_OPTIONS",
|
|
68
|
+
"STORE_STATUS_OPTIONS",
|
|
69
|
+
"PLATFORM_OPTIONS",
|
|
70
|
+
"PRODUCT_TYPE_OPTIONS",
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
// Shipping constants
|
|
74
|
+
shipping: {
|
|
75
|
+
patterns: [
|
|
76
|
+
/const\s+SHIPPING_CARRIERS?\s*=\s*[\[{]/,
|
|
77
|
+
/const\s+SHIPPING_CARRIER_OPTIONS\s*=\s*\[/,
|
|
78
|
+
/const\s+USPS_SERVICE_TYPE(?:S|_OPTIONS)?\s*=\s*[\[{]/,
|
|
79
|
+
/const\s+UPS_SERVICE_TYPE(?:S|_OPTIONS)?\s*=\s*[\[{]/,
|
|
80
|
+
/const\s+FEDEX_SERVICE_TYPE(?:S|_OPTIONS)?\s*=\s*[\[{]/,
|
|
81
|
+
/const\s+DHL_SERVICE_TYPE(?:S|_OPTIONS)?\s*=\s*[\[{]/,
|
|
82
|
+
/const\s+SHIPPING_RULE_TYPE(?:S|_OPTIONS)?\s*=\s*[\[{]/,
|
|
83
|
+
],
|
|
84
|
+
source: "@/lib/constants/shipping",
|
|
85
|
+
names: [
|
|
86
|
+
"SHIPPING_CARRIER",
|
|
87
|
+
"SHIPPING_CARRIERS",
|
|
88
|
+
"USPS_SERVICE_TYPE",
|
|
89
|
+
"UPS_SERVICE_TYPE",
|
|
90
|
+
"FEDEX_SERVICE_TYPE",
|
|
91
|
+
"DHL_SERVICE_TYPE",
|
|
92
|
+
"SHIPPING_RULE_TYPE",
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
// File size limits (check for hardcoded 10MB patterns)
|
|
96
|
+
limits: {
|
|
97
|
+
patterns: [
|
|
98
|
+
// Only flag if it's a constant definition, not inline usage
|
|
99
|
+
/const\s+MAX_FILE_SIZE\s*=\s*\d+\s*\*\s*1024\s*\*\s*1024/,
|
|
100
|
+
/const\s+MAX_UPLOAD_SIZE\s*=\s*\d+\s*\*\s*1024\s*\*\s*1024/,
|
|
101
|
+
/const\s+FILE_SIZE_LIMIT\s*=\s*\d+\s*\*\s*1024\s*\*\s*1024/,
|
|
102
|
+
/const\s+MAX_UPLOAD_BYTES\s*=\s*\d+\s*\*\s*1024\s*\*\s*1024/,
|
|
103
|
+
],
|
|
104
|
+
source: "@/lib/constants/limits or @/lib/image-constants",
|
|
105
|
+
names: ["MAX_FILE_SIZE", "MAX_UPLOAD_SIZE", "FILE_SIZE_LIMIT", "MAX_UPLOAD_BYTES"],
|
|
106
|
+
},
|
|
107
|
+
// Duration constants (toast, animation, debounce, etc.)
|
|
108
|
+
duration: {
|
|
109
|
+
patterns: [
|
|
110
|
+
// Toast duration definitions
|
|
111
|
+
/const\s+TOAST_DURATION\s*=\s*\{/,
|
|
112
|
+
/const\s+TOAST_DURATION_(?:SHORT|MEDIUM|LONG|EXTENDED)\s*=\s*\d{3,5}/,
|
|
113
|
+
// Animation duration definitions
|
|
114
|
+
/const\s+ANIMATION_DURATION\s*=\s*\{/,
|
|
115
|
+
/const\s+TRANSITION_DURATION\s*=\s*\d{2,4}/,
|
|
116
|
+
// Debounce/throttle definitions
|
|
117
|
+
/const\s+DEBOUNCE_(?:DELAY|TIME|MS)\s*=\s*\d{2,4}/,
|
|
118
|
+
/const\s+THROTTLE_(?:DELAY|TIME|MS)\s*=\s*\d{2,4}/,
|
|
119
|
+
],
|
|
120
|
+
source: "@/lib/constants/limits",
|
|
121
|
+
names: [
|
|
122
|
+
"TOAST_DURATION",
|
|
123
|
+
"TOAST_DURATION_SHORT",
|
|
124
|
+
"TOAST_DURATION_MEDIUM",
|
|
125
|
+
"TOAST_DURATION_LONG",
|
|
126
|
+
"TOAST_DURATION_EXTENDED",
|
|
127
|
+
"ANIMATION_DURATION",
|
|
128
|
+
"TRANSITION_DURATION",
|
|
129
|
+
"DEBOUNCE_DELAY",
|
|
130
|
+
"DEBOUNCE_TIME",
|
|
131
|
+
"DEBOUNCE_MS",
|
|
132
|
+
"THROTTLE_DELAY",
|
|
133
|
+
"THROTTLE_TIME",
|
|
134
|
+
"THROTTLE_MS",
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
// FILES TO ALLOW (source of truth files)
|
|
139
|
+
// Files that are allowed to define these constants (source of truth)
|
|
140
|
+
const ALLOWED_FILES = [
|
|
141
|
+
"lib/constants/geographic.ts",
|
|
142
|
+
"lib/constants/enums.ts",
|
|
143
|
+
"lib/constants/shipping.ts",
|
|
144
|
+
"lib/constants/limits.ts",
|
|
145
|
+
"lib/constants/index.ts",
|
|
146
|
+
"lib/image-constants.ts",
|
|
147
|
+
"lib/listings/gridPageSizes.ts",
|
|
148
|
+
];
|
|
149
|
+
// Files that re-export from centralized location (allowed)
|
|
150
|
+
const REEXPORT_FILES = [
|
|
151
|
+
"components/shipping/types.ts",
|
|
152
|
+
"components/forms/constants/cardFormConstants.ts",
|
|
153
|
+
"components/CardEditDialog/constants.ts",
|
|
154
|
+
"components/shared/OrderFilters.tsx", // Will be migrated
|
|
155
|
+
];
|
|
156
|
+
// Note: General file exclusions are handled via centralized config in preflight.config.js
|
|
157
|
+
// HELPER FUNCTIONS
|
|
158
|
+
function isAllowedSourceFile(filePath) {
|
|
159
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
160
|
+
// Check if it's an allowed source file
|
|
161
|
+
for (const allowed of ALLOWED_FILES) {
|
|
162
|
+
if (normalizedPath.endsWith(allowed)) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Check if it's a file that re-exports from centralized location
|
|
167
|
+
for (const reexport of REEXPORT_FILES) {
|
|
168
|
+
if (normalizedPath.endsWith(reexport)) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
function checkFile(filePath) {
|
|
175
|
+
const issues = [];
|
|
176
|
+
const content = fs_1.default.readFileSync(filePath, "utf-8");
|
|
177
|
+
const lines = content.split("\n");
|
|
178
|
+
for (let i = 0; i < lines.length; i++) {
|
|
179
|
+
const line = lines[i];
|
|
180
|
+
const lineNum = i + 1;
|
|
181
|
+
for (const [category, config] of Object.entries(CONSTANT_PATTERNS)) {
|
|
182
|
+
for (const pattern of config.patterns) {
|
|
183
|
+
if (pattern.test(line)) {
|
|
184
|
+
// Extract what's being defined
|
|
185
|
+
let constantName = "constant";
|
|
186
|
+
for (const name of config.names) {
|
|
187
|
+
if (line.includes(name)) {
|
|
188
|
+
constantName = name;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
issues.push({
|
|
193
|
+
file: filePath,
|
|
194
|
+
line: lineNum,
|
|
195
|
+
category,
|
|
196
|
+
constantName,
|
|
197
|
+
source: config.source,
|
|
198
|
+
message: `Local definition of ${constantName} found. Import from ${config.source} instead.`,
|
|
199
|
+
});
|
|
200
|
+
break; // Only report once per line
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return issues;
|
|
206
|
+
}
|
|
207
|
+
// MAIN
|
|
208
|
+
async function main() {
|
|
209
|
+
const args = process.argv.slice(2);
|
|
210
|
+
const categoryFilter = args[0]; // Optional: "geographic", "enums", "shipping", "limits"
|
|
211
|
+
console.log(`${console_chars_1.emoji.package} Constants Validation Preflight\n`);
|
|
212
|
+
// Load app-specific exclusions from config
|
|
213
|
+
appExclusions = await (0, exclusions_1.getExclusions)(exports.id);
|
|
214
|
+
if (categoryFilter) {
|
|
215
|
+
console.log(`Checking for local definitions of ${categoryFilter} constants...\n`);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
console.log("Checking for local definitions of all constants...\n");
|
|
219
|
+
}
|
|
220
|
+
// Find all TypeScript/JavaScript files
|
|
221
|
+
const allFiles = glob_1.glob.sync("**/*.{ts,tsx,js,jsx}", {
|
|
222
|
+
ignore: ["node_modules/**", ".next/**", "coverage/**"],
|
|
223
|
+
});
|
|
224
|
+
const files = allFiles.filter((file) => !(0, exclusions_1.shouldExcludeFile)(file, appExclusions));
|
|
225
|
+
const allIssues = [];
|
|
226
|
+
let filesChecked = 0;
|
|
227
|
+
for (const file of files) {
|
|
228
|
+
// Skip source files that are allowed to define these constants
|
|
229
|
+
if (isAllowedSourceFile(file)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
filesChecked++;
|
|
233
|
+
const issues = checkFile(file);
|
|
234
|
+
// Filter by category if specified
|
|
235
|
+
if (categoryFilter) {
|
|
236
|
+
allIssues.push(...issues.filter((i) => i.category === categoryFilter));
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
allIssues.push(...issues);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Report results
|
|
243
|
+
console.log(`Files checked: ${filesChecked}\n`);
|
|
244
|
+
if (allIssues.length === 0) {
|
|
245
|
+
console.log(`${console_chars_1.emoji.success} No local constant definitions found!\n`);
|
|
246
|
+
console.log("All constants should be imported from:\n");
|
|
247
|
+
console.log(" - Geographic: @/lib/constants/geographic");
|
|
248
|
+
console.log(" - Enums: @/lib/constants/enums");
|
|
249
|
+
console.log(" - Shipping: @/lib/constants/shipping");
|
|
250
|
+
console.log(" - Limits: @/lib/constants/limits (file sizes, TOAST_DURATION, debounce, etc.)\n");
|
|
251
|
+
process.exit(0);
|
|
252
|
+
}
|
|
253
|
+
console.log(`${console_chars_1.emoji.error} Found ${allIssues.length} local definition(s) that should be centralized:\n`);
|
|
254
|
+
// Group by category
|
|
255
|
+
const byCategory = {};
|
|
256
|
+
for (const issue of allIssues) {
|
|
257
|
+
if (!byCategory[issue.category]) {
|
|
258
|
+
byCategory[issue.category] = [];
|
|
259
|
+
}
|
|
260
|
+
byCategory[issue.category].push(issue);
|
|
261
|
+
}
|
|
262
|
+
for (const [category, issues] of Object.entries(byCategory)) {
|
|
263
|
+
console.log(`\n${console_chars_1.emoji.folder} ${category.toUpperCase()} (${issues.length} issues)`);
|
|
264
|
+
console.log(` Source: ${CONSTANT_PATTERNS[category].source}\n`);
|
|
265
|
+
// Group by file
|
|
266
|
+
const byFile = {};
|
|
267
|
+
for (const issue of issues) {
|
|
268
|
+
if (!byFile[issue.file]) {
|
|
269
|
+
byFile[issue.file] = [];
|
|
270
|
+
}
|
|
271
|
+
byFile[issue.file].push(issue);
|
|
272
|
+
}
|
|
273
|
+
for (const [file, fileIssues] of Object.entries(byFile)) {
|
|
274
|
+
console.log(` ${file}`);
|
|
275
|
+
for (const issue of fileIssues) {
|
|
276
|
+
console.log(` Line ${issue.line}: ${issue.constantName}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
console.log("\n" + (0, console_chars_1.createDivider)(60, "light"));
|
|
281
|
+
console.log(`\n${console_chars_1.emoji.clipboard} How to fix:\n`);
|
|
282
|
+
console.log("1. Remove the local definition of the constant");
|
|
283
|
+
console.log("2. Add the appropriate import at the top of the file:");
|
|
284
|
+
console.log(' import { CONSTANT_NAME } from "@/lib/constants";\n');
|
|
285
|
+
console.log("3. Or import from specific module:");
|
|
286
|
+
console.log(' import { US_STATES } from "@/lib/constants/geographic";');
|
|
287
|
+
console.log(' import { ORDER_STATUS_OPTIONS } from "@/lib/constants/enums";');
|
|
288
|
+
console.log(' import { SHIPPING_CARRIERS } from "@/lib/constants/shipping";');
|
|
289
|
+
console.log(' import { FILE_SIZE_LIMITS, TOAST_DURATION } from "@/lib/constants/limits";\n');
|
|
290
|
+
// Exit with error code for CI
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
main().catch((err) => {
|
|
294
|
+
console.error("Error:", err);
|
|
295
|
+
process.exit(1);
|
|
296
|
+
});
|
|
297
|
+
//# sourceMappingURL=constants-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-validation.js","sourceRoot":"","sources":["../../../src/checks/data/constants-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Crockford ID Validation Preflight Check
|
|
4
|
+
*
|
|
5
|
+
* Prevents @default(cuid()) from being added to schema when Crockford middleware is active.
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL: We use Crockford Base32 IDs with entity prefixes (usr_, lst_, ord_) via middleware.
|
|
8
|
+
* The @default(cuid()) directive conflicts with this system and should never be used.
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* 1. No @default(cuid()) in schema (conflicts with Crockford middleware)
|
|
12
|
+
* 2. Middleware must have createIdExtension() active
|
|
13
|
+
* 3. User-facing models should NOT have @default() on id field
|
|
14
|
+
* 4. System/analytics tables can use @default(dbgenerated("gen_random_uuid()"))
|
|
15
|
+
*
|
|
16
|
+
* Cost: Prevents ID generation conflicts and ensures consistent entity prefixes
|
|
17
|
+
*/
|
|
18
|
+
export declare const id = "data/crockford-id-validation";
|
|
19
|
+
export declare const name = "Crockford ID Validation";
|
|
20
|
+
export declare const description = "Validates Crockford Base32 ID generation and prevents @default(cuid()) conflicts";
|
|
21
|
+
export declare const category = "data";
|
|
22
|
+
export declare const blocking = true;
|
|
23
|
+
export declare const tags: string[];
|
|
24
|
+
//# sourceMappingURL=crockford-id-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crockford-id-validation.d.ts","sourceRoot":"","sources":["../../../src/checks/data/crockford-id-validation.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;GAeG;AAIH,eAAO,MAAM,EAAE,iCAAiC,CAAC;AACjD,eAAO,MAAM,IAAI,4BAA4B,CAAC;AAC9C,eAAO,MAAM,WAAW,qFAAqF,CAAC;AAC9G,eAAO,MAAM,QAAQ,SAAS,CAAC;AAC/B,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAAyC,CAAC"}
|