@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.
- package/dist/checks/data-integrity/internal-link-validation.d.ts +10 -0
- package/dist/checks/data-integrity/internal-link-validation.d.ts.map +1 -0
- package/dist/checks/data-integrity/internal-link-validation.js +279 -0
- package/dist/checks/data-integrity/internal-link-validation.js.map +1 -0
- package/dist/checks/data-integrity/scan-billing-enforcement.d.ts +10 -0
- package/dist/checks/data-integrity/scan-billing-enforcement.d.ts.map +1 -0
- package/dist/checks/data-integrity/scan-billing-enforcement.js +596 -0
- package/dist/checks/data-integrity/scan-billing-enforcement.js.map +1 -0
- package/dist/checks/performance/barrel-import-detection.d.ts +10 -0
- package/dist/checks/performance/barrel-import-detection.d.ts.map +1 -0
- package/dist/checks/performance/barrel-import-detection.js +245 -0
- package/dist/checks/performance/barrel-import-detection.js.map +1 -0
- package/dist/checks/store/team-member-access-consistency.d.ts +10 -0
- package/dist/checks/store/team-member-access-consistency.d.ts.map +1 -0
- package/dist/checks/store/team-member-access-consistency.js +199 -0
- package/dist/checks/store/team-member-access-consistency.js.map +1 -0
- package/dist/checks/ui/missing-page-layout.d.ts +10 -0
- package/dist/checks/ui/missing-page-layout.d.ts.map +1 -0
- package/dist/checks/ui/missing-page-layout.js +350 -0
- package/dist/checks/ui/missing-page-layout.js.map +1 -0
- package/package.json +1 -1
|
@@ -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"}
|