@empline/preflight 1.1.52 → 1.1.54

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.
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
38
+ exports.run = run;
39
+ /**
40
+ * Barrel Import Detection Preflight
41
+ *
42
+ * Detects imports from barrel files (index.ts) that can cause bundle bloat.
43
+ * Large barrel files force bundlers to analyze all exports even when only
44
+ * a few are used, which can prevent effective tree-shaking.
45
+ *
46
+ * Problematic pattern:
47
+ * ```tsx
48
+ * import { Button, Card } from "@/components/ui"; // Analyzes 100+ exports
49
+ * ```
50
+ *
51
+ * Better pattern:
52
+ * ```tsx
53
+ * import { Button } from "@/components/ui/Button";
54
+ * import { Card } from "@/components/ui/Card";
55
+ * ```
56
+ *
57
+ * This check is non-blocking but tracks the count for gradual migration.
58
+ */
59
+ const fs = __importStar(require("node:fs"));
60
+ const path = __importStar(require("node:path"));
61
+ const glob_1 = require("glob");
62
+ const console_chars_1 = require("../../utils/console-chars");
63
+ // METADATA - Required for plugin loader discovery
64
+ exports.id = "performance/barrel-import-detection";
65
+ exports.name = "Barrel Import Detection";
66
+ exports.description = "Detects imports from large barrel files that impact bundle size";
67
+ exports.category = "performance";
68
+ exports.blocking = false; // Advisory - track for gradual migration
69
+ exports.tags = ["performance", "bundle", "imports", "tree-shaking"];
70
+ /**
71
+ * Barrel files to check (with approximate export counts)
72
+ */
73
+ const BARREL_FILES = [
74
+ { path: "@/components/shared", threshold: 10, name: "shared components" },
75
+ { path: "@/components/ui", threshold: 10, name: "UI components" },
76
+ ];
77
+ /**
78
+ * File patterns to check
79
+ */
80
+ const FILE_PATTERNS = ["app/**/*.tsx", "components/**/*.tsx"];
81
+ /**
82
+ * Files/directories to exclude
83
+ */
84
+ const EXCLUDE_PATTERNS = [
85
+ "node_modules/**",
86
+ "**/*.test.tsx",
87
+ "**/*.spec.tsx",
88
+ "**/*.stories.tsx",
89
+ ".storybook/**",
90
+ // Barrel files themselves
91
+ "**/index.ts",
92
+ "**/index.tsx",
93
+ ];
94
+ /**
95
+ * Extract line number from content and position
96
+ */
97
+ function getLineNumber(content, position) {
98
+ return content.substring(0, position).split("\n").length;
99
+ }
100
+ /**
101
+ * Parse imports from a barrel file
102
+ */
103
+ function parseBarrelImports(content, barrelPath) {
104
+ const results = [];
105
+ // Match: import { X, Y, Z } from "@/components/shared"
106
+ // Also match: import { X, Y, Z } from "@/components/shared/index"
107
+ const importRegex = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']${barrelPath.replace("/", "\\/")}(?:\\/index)?["']`, "g");
108
+ let match;
109
+ while ((match = importRegex.exec(content)) !== null) {
110
+ const importList = match[1]
111
+ .split(",")
112
+ .map((s) => s.trim())
113
+ .filter((s) => s && !s.startsWith("type "));
114
+ if (importList.length > 0) {
115
+ results.push({
116
+ line: getLineNumber(content, match.index),
117
+ imports: importList,
118
+ });
119
+ }
120
+ }
121
+ return results;
122
+ }
123
+ async function run() {
124
+ const startTime = Date.now();
125
+ const findings = [];
126
+ const barrelImports = [];
127
+ const statsByBarrel = {};
128
+ // Initialize stats
129
+ for (const barrel of BARREL_FILES) {
130
+ statsByBarrel[barrel.path] = { files: 0, imports: 0 };
131
+ }
132
+ // Find all TSX files
133
+ const allFiles = [];
134
+ for (const pattern of FILE_PATTERNS) {
135
+ const matches = await (0, glob_1.glob)(pattern, {
136
+ cwd: process.cwd(),
137
+ ignore: EXCLUDE_PATTERNS,
138
+ });
139
+ allFiles.push(...matches);
140
+ }
141
+ const uniqueFiles = [...new Set(allFiles)];
142
+ for (const relativePath of uniqueFiles) {
143
+ const filePath = path.join(process.cwd(), relativePath);
144
+ if (!fs.existsSync(filePath))
145
+ continue;
146
+ const content = fs.readFileSync(filePath, "utf-8");
147
+ // Check for preflight-ignore
148
+ if (/preflight-ignore.*barrel/.test(content)) {
149
+ continue;
150
+ }
151
+ // Check each barrel file
152
+ for (const barrel of BARREL_FILES) {
153
+ const imports = parseBarrelImports(content, barrel.path);
154
+ for (const imp of imports) {
155
+ if (imp.imports.length >= barrel.threshold) {
156
+ barrelImports.push({
157
+ file: relativePath,
158
+ line: imp.line,
159
+ barrelPath: barrel.path,
160
+ importCount: imp.imports.length,
161
+ imports: imp.imports,
162
+ });
163
+ findings.push({
164
+ level: "warning",
165
+ message: `Importing ${imp.imports.length} items from ${barrel.path} may impact bundle size`,
166
+ file: relativePath,
167
+ startLine: imp.line,
168
+ ruleId: "barrel-import",
169
+ suggestion: `Consider importing directly: import { ${imp.imports[0]} } from "${barrel.path}/${imp.imports[0]}"`,
170
+ });
171
+ }
172
+ // Track stats for all imports (not just over threshold)
173
+ statsByBarrel[barrel.path].files++;
174
+ statsByBarrel[barrel.path].imports += imp.imports.length;
175
+ }
176
+ }
177
+ }
178
+ const totalBarrelFiles = Object.values(statsByBarrel).reduce((sum, s) => sum + s.files, 0);
179
+ const totalBarrelImports = Object.values(statsByBarrel).reduce((sum, s) => sum + s.imports, 0);
180
+ const highImpactCount = barrelImports.filter((b) => b.importCount >= 10).length;
181
+ return {
182
+ passed: true, // Advisory check - always passes
183
+ findings,
184
+ duration: Date.now() - startTime,
185
+ metadata: {
186
+ filesScanned: uniqueFiles.length,
187
+ totalBarrelFiles,
188
+ totalBarrelImports,
189
+ highImpactImports: highImpactCount,
190
+ statsByBarrel,
191
+ },
192
+ };
193
+ }
194
+ async function main() {
195
+ console.log(`\n${console_chars_1.emoji.package} BARREL IMPORT DETECTION`);
196
+ console.log((0, console_chars_1.createDivider)(65, "heavy"));
197
+ const result = await run();
198
+ const metadata = result.metadata || {};
199
+ const filesScanned = metadata.filesScanned;
200
+ const totalBarrelFiles = metadata.totalBarrelFiles;
201
+ const totalBarrelImports = metadata.totalBarrelImports;
202
+ const highImpactImports = metadata.highImpactImports;
203
+ const statsByBarrel = metadata.statsByBarrel;
204
+ console.log(`\n${console_chars_1.emoji.search} Scanning ${filesScanned} files for barrel imports...`);
205
+ // Summary
206
+ console.log(`\n${console_chars_1.emoji.chart} Barrel Import Statistics:`);
207
+ for (const [barrelPath, stats] of Object.entries(statsByBarrel)) {
208
+ console.log(` ${barrelPath}:`);
209
+ console.log(` Files importing: ${stats.files}`);
210
+ console.log(` Total imports: ${stats.imports}`);
211
+ }
212
+ console.log(`\n Total barrel usage: ${totalBarrelFiles} files, ${totalBarrelImports} imports`);
213
+ // Report high-impact files
214
+ if (highImpactImports && highImpactImports > 0) {
215
+ console.log(`\n${console_chars_1.emoji.warning} High-impact barrel imports (10+ items): ${highImpactImports}`);
216
+ // Show details from findings
217
+ const highImpactFindings = result.findings.filter(f => f.message.includes("10") || f.message.includes("11") || f.message.includes("12"));
218
+ for (const finding of highImpactFindings.slice(0, 10)) {
219
+ console.log(`\n ${finding.file}:${finding.startLine}`);
220
+ console.log(` ${finding.message}`);
221
+ }
222
+ if (highImpactFindings.length > 10) {
223
+ console.log(`\n ... and ${highImpactFindings.length - 10} more files`);
224
+ }
225
+ }
226
+ console.log(`\n${console_chars_1.emoji.info} Migration guide:`);
227
+ console.log(` Replace: import { Button, Card } from "@/components/ui"`);
228
+ console.log(` With: import { Button } from "@/components/ui/Button"`);
229
+ console.log(` import { Card } from "@/components/ui/Card"`);
230
+ console.log(`\n Benefits:`);
231
+ console.log(` - Faster bundling (less code to analyze)`);
232
+ console.log(` - Better tree-shaking (removes unused code)`);
233
+ console.log(` - Smaller client bundles`);
234
+ // This is advisory, not blocking
235
+ console.log(`\n${console_chars_1.emoji.success} BARREL IMPORT DETECTION COMPLETED (advisory)`);
236
+ console.log(` Consider gradually migrating high-impact files to direct imports.`);
237
+ process.exit(0);
238
+ }
239
+ if (require.main === module) {
240
+ main().catch((err) => {
241
+ console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
242
+ process.exit(1);
243
+ });
244
+ }
245
+ //# sourceMappingURL=barrel-import-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"barrel-import-detection.js","sourceRoot":"","sources":["../../../src/checks/performance/barrel-import-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { PreflightCheckResult } from "../../core/types";
3
+ export declare const id = "store/team-member-access-consistency";
4
+ export declare const name = "Team Member Access Consistency";
5
+ export declare const description = "Ensures API routes properly support team member access via getUserStoreAccess()";
6
+ export declare const category = "store";
7
+ export declare const blocking = true;
8
+ export declare const tags: string[];
9
+ export declare function run(): Promise<PreflightCheckResult>;
10
+ //# sourceMappingURL=team-member-access-consistency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-member-access-consistency.d.ts","sourceRoot":"","sources":["../../../src/checks/store/team-member-access-consistency.ts"],"names":[],"mappings":";AAcA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAG1E,eAAO,MAAM,EAAE,yCAAyC,CAAC;AACzD,eAAO,MAAM,IAAI,mCAAmC,CAAC;AACrD,eAAO,MAAM,WAAW,oFAAoF,CAAC;AAC7G,eAAO,MAAM,QAAQ,UAAU,CAAC;AAChC,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAA4D,CAAC;AAgD9E,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAgEzD"}
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
38
+ exports.run = run;
39
+ /**
40
+ * Team Member Access Consistency Preflight (BLOCKING)
41
+ *
42
+ * Ensures API routes use getUserStoreAccess() for store access checks,
43
+ * which properly handles both store owners AND team members.
44
+ *
45
+ * Detects anti-patterns:
46
+ * - user.authStores (only checks ownership, not team membership)
47
+ * - user.role !== "SELLER" (blocks team members who aren't SELLER role)
48
+ */
49
+ const fs = __importStar(require("node:fs"));
50
+ const path = __importStar(require("node:path"));
51
+ const glob_1 = require("glob");
52
+ const console_chars_1 = require("../../utils/console-chars");
53
+ exports.id = "store/team-member-access-consistency";
54
+ exports.name = "Team Member Access Consistency";
55
+ exports.description = "Ensures API routes properly support team member access via getUserStoreAccess()";
56
+ exports.category = "store";
57
+ exports.blocking = true;
58
+ exports.tags = ["team", "access", "store", "consistency", "permissions"];
59
+ // Patterns that indicate direct owner-only checks (anti-patterns)
60
+ const ANTI_PATTERNS = [
61
+ {
62
+ pattern: /user\.authStores/g,
63
+ description: "Direct authStores access only checks ownership, not team membership",
64
+ fix: "Use getUserStoreAccess() from @/lib/seller-stats.server instead",
65
+ },
66
+ {
67
+ pattern: /user\.role\s*!==\s*["']SELLER["']/g,
68
+ description: "Role check excludes team members who may have different roles",
69
+ fix: "Use getUserStoreAccess() which checks team membership regardless of role",
70
+ },
71
+ {
72
+ pattern: /user\.role\s*===\s*["']SELLER["']/g,
73
+ description: "Role check excludes team members who may have different roles",
74
+ fix: "Use getUserStoreAccess() which checks team membership regardless of role",
75
+ },
76
+ ];
77
+ // Files/patterns to exclude from checking
78
+ const EXCLUDED_PATTERNS = [
79
+ // The getUserStoreAccess implementation itself
80
+ "lib/seller-stats.server.ts",
81
+ // Admin routes that legitimately need owner-only access
82
+ "app/api/admin/**",
83
+ // Billing routes may legitimately be owner-only
84
+ "app/api/billing/**",
85
+ // Store settings that are owner-only
86
+ "app/api/store/settings/**",
87
+ // Store team management (owner/admin only)
88
+ "app/api/store/team/**",
89
+ // User deletion is admin-only
90
+ "app/api/admin/users/delete/**",
91
+ ];
92
+ function shouldExclude(filePath) {
93
+ const normalized = filePath.replace(/\\/g, "/");
94
+ return EXCLUDED_PATTERNS.some((pattern) => {
95
+ if (pattern.includes("**")) {
96
+ const prefix = pattern.replace("/**", "");
97
+ return normalized.includes(prefix);
98
+ }
99
+ return normalized.includes(pattern);
100
+ });
101
+ }
102
+ async function run() {
103
+ const startTime = Date.now();
104
+ const findings = [];
105
+ // Scan API routes for anti-patterns
106
+ const apiFiles = await (0, glob_1.glob)("app/api/**/*.ts", {
107
+ cwd: process.cwd(),
108
+ ignore: ["**/*.d.ts", "**/node_modules/**"],
109
+ });
110
+ for (const apiFile of apiFiles) {
111
+ if (shouldExclude(apiFile)) {
112
+ continue;
113
+ }
114
+ const filePath = path.join(process.cwd(), apiFile);
115
+ if (!fs.existsSync(filePath))
116
+ continue;
117
+ const content = fs.readFileSync(filePath, "utf-8");
118
+ const lines = content.split("\n");
119
+ // Check if this file already uses getUserStoreAccess
120
+ const usesGetUserStoreAccess = content.includes("getUserStoreAccess");
121
+ // If file uses getUserStoreAccess, skip user.authStores checks entirely
122
+ // (it's accessing a compatibility object, not doing direct lookup)
123
+ if (usesGetUserStoreAccess) {
124
+ continue;
125
+ }
126
+ for (const antiPattern of ANTI_PATTERNS) {
127
+ antiPattern.pattern.lastIndex = 0;
128
+ let match;
129
+ while ((match = antiPattern.pattern.exec(content)) !== null) {
130
+ const lineNum = content.substring(0, match.index).split("\n").length;
131
+ const lineContent = lines[lineNum - 1]?.trim() || "";
132
+ // Skip if there's a preflight-ignore comment
133
+ if (lineContent.includes("preflight-ignore") || lineContent.includes("eslint-disable")) {
134
+ continue;
135
+ }
136
+ findings.push({
137
+ level: "error",
138
+ message: `${antiPattern.description}: ${match[0]}`,
139
+ file: apiFile,
140
+ startLine: lineNum,
141
+ ruleId: "team-member-access",
142
+ suggestion: antiPattern.fix,
143
+ });
144
+ }
145
+ }
146
+ }
147
+ return {
148
+ passed: findings.length === 0,
149
+ findings,
150
+ duration: Date.now() - startTime,
151
+ metadata: {
152
+ apiFilesScanned: apiFiles.length,
153
+ issuesFound: findings.length,
154
+ },
155
+ };
156
+ }
157
+ async function main() {
158
+ console.log(`\n${console_chars_1.emoji.users} TEAM MEMBER ACCESS CONSISTENCY`);
159
+ console.log((0, console_chars_1.createDivider)(65, "heavy"));
160
+ console.log(`\n${console_chars_1.emoji.file} Scanning API routes...`);
161
+ const result = await run();
162
+ const { apiFilesScanned, issuesFound } = result.metadata || {};
163
+ console.log(`\n${console_chars_1.emoji.chart} Summary:`);
164
+ console.log(` API files scanned: ${apiFilesScanned}`);
165
+ console.log(` Issues found: ${issuesFound}`);
166
+ if (result.passed) {
167
+ console.log(`\n${console_chars_1.emoji.success} TEAM MEMBER ACCESS CONSISTENCY PASSED`);
168
+ console.log(`\nAll API routes use consistent team member access patterns.`);
169
+ process.exit(0);
170
+ }
171
+ // Group issues by file
172
+ const issuesByFile = new Map();
173
+ for (const finding of result.findings) {
174
+ const existing = issuesByFile.get(finding.file || "") || [];
175
+ existing.push(finding);
176
+ issuesByFile.set(finding.file || "", existing);
177
+ }
178
+ console.log(`\n${console_chars_1.emoji.error} Inconsistent team member access patterns:`);
179
+ for (const [file, fileIssues] of issuesByFile) {
180
+ console.log(`\n ${file}`);
181
+ for (const issue of fileIssues) {
182
+ console.log(` Line ${issue.startLine}: ${issue.message}`);
183
+ }
184
+ }
185
+ console.log(`\n${console_chars_1.emoji.info} To fix these issues:`);
186
+ console.log(` 1. Import getUserStoreAccess from "@/lib/seller-stats.server"`);
187
+ console.log(` 2. Replace direct user.authStores lookups with:`);
188
+ console.log(` const storeAccess = await getUserStoreAccess(session.user.id);`);
189
+ console.log(` 3. This ensures both store owners AND team members have access`);
190
+ console.log(`\n${console_chars_1.emoji.error} TEAM MEMBER ACCESS CONSISTENCY FAILED`);
191
+ process.exit(1);
192
+ }
193
+ if (require.main === module) {
194
+ main().catch((err) => {
195
+ console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
196
+ process.exit(1);
197
+ });
198
+ }
199
+ //# sourceMappingURL=team-member-access-consistency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-member-access-consistency.js","sourceRoot":"","sources":["../../../src/checks/store/team-member-access-consistency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { PreflightCheckResult } from "../../core/types";
3
+ export declare const id = "ui/missing-page-layout";
4
+ export declare const name = "Missing Page Layout";
5
+ export declare const description = "Detects dashboard/seller pages missing SellerPageLayout or DashboardPageLayout wrapper";
6
+ export declare const category = "ui";
7
+ export declare const blocking = true;
8
+ export declare const tags: string[];
9
+ export declare function run(): Promise<PreflightCheckResult>;
10
+ //# sourceMappingURL=missing-page-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-page-layout.d.ts","sourceRoot":"","sources":["../../../src/checks/ui/missing-page-layout.ts"],"names":[],"mappings":";AA0CA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAI1E,eAAO,MAAM,EAAE,2BAA2B,CAAC;AAC3C,eAAO,MAAM,IAAI,wBAAwB,CAAC;AAC1C,eAAO,MAAM,WAAW,2FAA2F,CAAC;AACpH,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAAwD,CAAC;AA+K1E,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAqEzD"}