@jmruthers/pace-core 0.6.6 → 0.6.7
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +291 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +241 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-7PMH7XN7.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
- package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
- package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
- package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
- package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
- package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
- package/dist/components.d.ts +5 -4
- package/dist/components.js +27 -32
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -17
- package/dist/rbac/index.js +6 -6
- package/dist/theming/runtime.d.ts +14 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +47 -31
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +21 -10
- package/package.json +6 -5
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +284 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +137 -153
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +10 -9
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +5 -5
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +1 -4
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/storage/README.md +1 -1
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Installation Script for pace-core Cursor Rules
|
|
4
|
+
* Installation Script for pace-core Cursor Rules
|
|
5
5
|
* @package @jmruthers/pace-core
|
|
6
6
|
* @module Scripts/install-cursor-rules
|
|
7
7
|
*
|
|
8
|
-
* Sets up
|
|
9
|
-
*
|
|
10
|
-
* 2. ESLint config - Adds pace-core ESLint config to consuming app's ESLint configuration
|
|
8
|
+
* Sets up cursor rules:
|
|
9
|
+
* - Copies cursor rules from pace-core to consuming app's .cursor/rules/ directory
|
|
11
10
|
*
|
|
12
11
|
* This is an opt-in script - it does NOT run automatically via postinstall.
|
|
13
12
|
*
|
|
13
|
+
* For ESLint setup, use install-eslint-config.cjs separately.
|
|
14
|
+
*
|
|
14
15
|
* Usage:
|
|
15
|
-
* node install-cursor-rules.cjs
|
|
16
|
-
* node install-cursor-rules.cjs --
|
|
17
|
-
* node install-cursor-rules.cjs --skip-cursor # Only setup ESLint
|
|
18
|
-
* node install-cursor-rules.cjs --force # Force update even if already configured
|
|
16
|
+
* node install-cursor-rules.cjs # Install cursor rules
|
|
17
|
+
* node install-cursor-rules.cjs --force # Force update even if already configured
|
|
19
18
|
*/
|
|
20
19
|
|
|
21
20
|
const fs = require('fs');
|
|
@@ -219,250 +218,21 @@ function installCursorRules(force = false) {
|
|
|
219
218
|
console.log(`${colors.cyan}Restart Cursor to load the new rules.${colors.reset}`);
|
|
220
219
|
}
|
|
221
220
|
|
|
222
|
-
// Find existing ESLint config file
|
|
223
|
-
function findESLintConfig() {
|
|
224
|
-
const cwd = process.cwd();
|
|
225
|
-
const possibleConfigs = [
|
|
226
|
-
'eslint.config.js',
|
|
227
|
-
'eslint.config.cjs',
|
|
228
|
-
'eslint.config.mjs',
|
|
229
|
-
'.eslintrc.js',
|
|
230
|
-
'.eslintrc.cjs',
|
|
231
|
-
'.eslintrc.json',
|
|
232
|
-
'.eslintrc.yaml',
|
|
233
|
-
'.eslintrc.yml',
|
|
234
|
-
];
|
|
235
|
-
|
|
236
|
-
for (const configFile of possibleConfigs) {
|
|
237
|
-
const configPath = path.join(cwd, configFile);
|
|
238
|
-
if (fs.existsSync(configPath)) {
|
|
239
|
-
return { path: configPath, name: configFile, isESM: configFile.endsWith('.js') || configFile.endsWith('.mjs') };
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return null;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Check if pace-core config is already included
|
|
247
|
-
function hasPaceCoreConfig(configContent) {
|
|
248
|
-
// Check for pace-core config import/require
|
|
249
|
-
const paceCorePatterns = [
|
|
250
|
-
/@jmruthers\/pace-core\/eslint-config/,
|
|
251
|
-
/pace-core\/eslint-config/,
|
|
252
|
-
/paceCoreConfig/,
|
|
253
|
-
/pace-core-compliance/,
|
|
254
|
-
];
|
|
255
|
-
|
|
256
|
-
return paceCorePatterns.some(pattern => pattern.test(configContent));
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Detect if file is ES module
|
|
260
|
-
function isESModule(filePath, content) {
|
|
261
|
-
if (filePath.endsWith('.mjs')) return true;
|
|
262
|
-
if (filePath.endsWith('.cjs')) return false;
|
|
263
|
-
if (filePath.endsWith('.js')) {
|
|
264
|
-
// Check for ES module indicators
|
|
265
|
-
return /^import\s+.*from|^export\s+default/.test(content.trim());
|
|
266
|
-
}
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Backup file before modification
|
|
271
|
-
function backupFile(filePath) {
|
|
272
|
-
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
273
|
-
fs.copyFileSync(filePath, backupPath);
|
|
274
|
-
return backupPath;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Setup ESLint configuration
|
|
278
|
-
function setupESLintConfig(force = false, skipIfExists = false) {
|
|
279
|
-
const cwd = process.cwd();
|
|
280
|
-
const existingConfig = findESLintConfig();
|
|
281
|
-
|
|
282
|
-
if (existingConfig) {
|
|
283
|
-
// Read existing config
|
|
284
|
-
let content = fs.readFileSync(existingConfig.path, 'utf8');
|
|
285
|
-
const isESM = isESModule(existingConfig.path, content);
|
|
286
|
-
const format = isESM ? 'ES Module' : 'CommonJS';
|
|
287
|
-
|
|
288
|
-
console.log(`${colors.cyan}Found ESLint config:${colors.reset} ${existingConfig.name} (${format})`);
|
|
289
|
-
|
|
290
|
-
// Check if already configured
|
|
291
|
-
if (hasPaceCoreConfig(content)) {
|
|
292
|
-
if (skipIfExists && !force) {
|
|
293
|
-
console.log(`${colors.blue}○${colors.reset} ${existingConfig.name} already includes pace-core rules`);
|
|
294
|
-
return { action: 'skipped', file: existingConfig.name, format };
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (force) {
|
|
298
|
-
console.log(`${colors.yellow}Updating existing ESLint config...${colors.reset}`);
|
|
299
|
-
} else {
|
|
300
|
-
console.log(`${colors.blue}○${colors.reset} ${existingConfig.name} already configured. Use --force to update.`);
|
|
301
|
-
return { action: 'skipped', file: existingConfig.name, format };
|
|
302
|
-
}
|
|
303
|
-
} else {
|
|
304
|
-
console.log(`${colors.cyan}Adding pace-core config to ${existingConfig.name}...${colors.reset}`);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Backup before modification
|
|
308
|
-
const backupPath = backupFile(existingConfig.path);
|
|
309
|
-
console.log(`${colors.cyan} Backed up to ${path.basename(backupPath)}${colors.reset}`);
|
|
310
|
-
|
|
311
|
-
// Add pace-core config
|
|
312
|
-
if (isESM) {
|
|
313
|
-
// ES Module format
|
|
314
|
-
if (!content.includes('import paceCoreConfig')) {
|
|
315
|
-
// Add import at top (after other imports if they exist)
|
|
316
|
-
const importLines = content.match(/^(import\s+[^;]+;?\s*\n)+/m);
|
|
317
|
-
if (importLines) {
|
|
318
|
-
// Add after existing imports
|
|
319
|
-
content = content.replace(
|
|
320
|
-
importLines[0],
|
|
321
|
-
`${importLines[0]}import paceCoreConfig from '@jmruthers/pace-core/eslint-config';\n`
|
|
322
|
-
);
|
|
323
|
-
} else {
|
|
324
|
-
// Add at the beginning
|
|
325
|
-
content = `import paceCoreConfig from '@jmruthers/pace-core/eslint-config';\n${content}`;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Add to export default array
|
|
330
|
-
if (content.includes('export default [')) {
|
|
331
|
-
// Already an array, add paceCoreConfig at the beginning
|
|
332
|
-
if (!content.includes('...paceCoreConfig')) {
|
|
333
|
-
content = content.replace(
|
|
334
|
-
/(export\s+default\s*\[)\s*/,
|
|
335
|
-
'$1\n ...paceCoreConfig,'
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
} else if (content.includes('export default')) {
|
|
339
|
-
// Not an array, wrap it
|
|
340
|
-
const exportMatch = content.match(/(export\s+default\s+)(.+?)(;?\s*$)/s);
|
|
341
|
-
if (exportMatch) {
|
|
342
|
-
content = content.replace(
|
|
343
|
-
exportMatch[0],
|
|
344
|
-
`${exportMatch[1]}[\n ...paceCoreConfig,\n ${exportMatch[2]}\n];`
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
} else {
|
|
349
|
-
// CommonJS format
|
|
350
|
-
if (!content.includes('require(\'@jmruthers/pace-core/eslint-config\')')) {
|
|
351
|
-
// Add require at top (after other requires if they exist)
|
|
352
|
-
const requireLines = content.match(/^(const\s+\w+\s*=\s*require\([^)]+\);\s*\n)+/m);
|
|
353
|
-
if (requireLines) {
|
|
354
|
-
content = content.replace(
|
|
355
|
-
requireLines[0],
|
|
356
|
-
`${requireLines[0]}const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');\n`
|
|
357
|
-
);
|
|
358
|
-
} else {
|
|
359
|
-
content = `const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');\n${content}`;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Add to module.exports
|
|
364
|
-
if (content.includes('module.exports = [')) {
|
|
365
|
-
// Already an array, add paceCoreConfig at the beginning
|
|
366
|
-
if (!content.includes('...paceCoreConfig')) {
|
|
367
|
-
content = content.replace(
|
|
368
|
-
/(module\.exports\s*=\s*\[)\s*/,
|
|
369
|
-
'$1\n ...paceCoreConfig,'
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
} else if (content.includes('module.exports =')) {
|
|
373
|
-
// Not an array, wrap it
|
|
374
|
-
const exportMatch = content.match(/(module\.exports\s*=\s*)(.+?)(;?\s*$)/s);
|
|
375
|
-
if (exportMatch) {
|
|
376
|
-
content = content.replace(
|
|
377
|
-
exportMatch[0],
|
|
378
|
-
`${exportMatch[1]}[\n ...paceCoreConfig,\n ${exportMatch[2]}\n];`
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Write updated config
|
|
385
|
-
fs.writeFileSync(existingConfig.path, content, 'utf8');
|
|
386
|
-
console.log(`${colors.green}✓${colors.reset} Updated ${existingConfig.name}`);
|
|
387
|
-
return { action: 'updated', file: existingConfig.name, backup: backupPath, format };
|
|
388
|
-
} else {
|
|
389
|
-
// Create new ESLint config (default to ES modules)
|
|
390
|
-
const configPath = path.join(cwd, 'eslint.config.js');
|
|
391
|
-
const configContent = `import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
|
|
392
|
-
|
|
393
|
-
export default [
|
|
394
|
-
...paceCoreConfig,
|
|
395
|
-
// Your app-specific ESLint configuration
|
|
396
|
-
{
|
|
397
|
-
// Add your rules here
|
|
398
|
-
},
|
|
399
|
-
];
|
|
400
|
-
`;
|
|
401
|
-
|
|
402
|
-
console.log(`${colors.cyan}No ESLint config found. Creating eslint.config.js...${colors.reset}`);
|
|
403
|
-
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
404
|
-
console.log(`${colors.green}✓${colors.reset} Created eslint.config.js`);
|
|
405
|
-
console.log(`${colors.cyan} Edit eslint.config.js to add your app-specific ESLint rules.${colors.reset}`);
|
|
406
|
-
return { action: 'created', file: 'eslint.config.js', format: 'ES Module' };
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
221
|
|
|
410
222
|
// Main execution
|
|
411
223
|
function main() {
|
|
412
224
|
const force = process.argv.includes('--force');
|
|
413
|
-
const skipCursor = process.argv.includes('--skip-cursor');
|
|
414
|
-
const skipESLint = process.argv.includes('--skip-eslint');
|
|
415
225
|
|
|
416
226
|
if (force) {
|
|
417
227
|
console.log(`${colors.yellow}Warning: --force flag is set. This will overwrite existing configurations.${colors.reset}\n`);
|
|
418
228
|
}
|
|
419
229
|
|
|
420
230
|
try {
|
|
421
|
-
|
|
422
|
-
let eslintResult = null;
|
|
423
|
-
|
|
424
|
-
// Install cursor rules
|
|
425
|
-
if (!skipCursor) {
|
|
426
|
-
installCursorRules(force);
|
|
427
|
-
cursorResult = { completed: true };
|
|
428
|
-
} else {
|
|
429
|
-
console.log(`${colors.blue}Skipping cursor rules installation (--skip-cursor)${colors.reset}\n`);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Setup ESLint config
|
|
433
|
-
if (!skipESLint) {
|
|
434
|
-
console.log(`\n${colors.cyan}Setting up ESLint configuration...${colors.reset}\n`);
|
|
435
|
-
eslintResult = setupESLintConfig(force, true);
|
|
436
|
-
|
|
437
|
-
// Output is handled in setupESLintConfig, but ensure we have consistent formatting
|
|
438
|
-
} else {
|
|
439
|
-
console.log(`\n${colors.blue}Skipping ESLint setup (--skip-eslint)${colors.reset}`);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Summary
|
|
443
|
-
console.log(`\n${colors.bold}Setup Summary:${colors.reset}`);
|
|
444
|
-
if (cursorResult) {
|
|
445
|
-
console.log(` ${colors.green}Cursor Rules:${colors.reset} Installed`);
|
|
446
|
-
}
|
|
447
|
-
if (eslintResult) {
|
|
448
|
-
if (eslintResult.action === 'created') {
|
|
449
|
-
console.log(` ${colors.green}ESLint Config:${colors.reset} Created ${eslintResult.file} (${eslintResult.format})`);
|
|
450
|
-
} else if (eslintResult.action === 'updated') {
|
|
451
|
-
console.log(` ${colors.green}ESLint Config:${colors.reset} Updated ${eslintResult.file} (${eslintResult.format})`);
|
|
452
|
-
console.log(` ${colors.yellow}Backup:${colors.reset} ${path.basename(eslintResult.backup)}`);
|
|
453
|
-
} else {
|
|
454
|
-
console.log(` ${colors.blue}ESLint Config:${colors.reset} Already configured (${eslintResult.file}, ${eslintResult.format})`);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
231
|
+
installCursorRules(force);
|
|
457
232
|
|
|
458
233
|
console.log(`\n${colors.cyan}Next steps:${colors.reset}`);
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
if (!skipESLint) {
|
|
463
|
-
console.log(` • Run ${colors.bold}npm run lint${colors.reset} to verify ESLint is working`);
|
|
464
|
-
console.log(` • Edit your ESLint config to add app-specific rules`);
|
|
465
|
-
}
|
|
234
|
+
console.log(` • Restart Cursor to load the new rules`);
|
|
235
|
+
console.log(` • For ESLint setup, run: ${colors.bold}node node_modules/@jmruthers/pace-core/scripts/install-eslint-config.cjs${colors.reset}`);
|
|
466
236
|
|
|
467
237
|
} catch (error) {
|
|
468
238
|
console.error(`${colors.red}Error during setup:${colors.reset}`);
|
|
@@ -481,7 +251,5 @@ if (require.main === module) {
|
|
|
481
251
|
|
|
482
252
|
module.exports = {
|
|
483
253
|
installCursorRules,
|
|
484
|
-
getCursorRulesTarget
|
|
485
|
-
setupESLintConfig,
|
|
486
|
-
findESLintConfig
|
|
254
|
+
getCursorRulesTarget
|
|
487
255
|
};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Installation Script for pace-core ESLint Config
|
|
5
|
+
* @package @jmruthers/pace-core
|
|
6
|
+
* @module Scripts/install-eslint-config
|
|
7
|
+
*
|
|
8
|
+
* Sets up pace-core ESLint configuration in consuming apps.
|
|
9
|
+
* Adds pace-core ESLint config to consuming app's ESLint configuration.
|
|
10
|
+
*
|
|
11
|
+
* This is an opt-in script - it does NOT run automatically via postinstall.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node install-eslint-config.cjs # Setup ESLint config
|
|
15
|
+
* node install-eslint-config.cjs --force # Force update even if already configured
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// Check for safety guards
|
|
22
|
+
function checkSafetyGuards() {
|
|
23
|
+
// Check environment variable
|
|
24
|
+
if (process.env.PACE_ESLINT_CONFIG_DISABLED === '1') {
|
|
25
|
+
console.log(`${colors.yellow}Skipping ESLint config installation: PACE_ESLINT_CONFIG_DISABLED=1${colors.reset}`);
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check for .git folder (safety guard for CI)
|
|
30
|
+
const cwd = process.cwd();
|
|
31
|
+
if (!fs.existsSync(path.join(cwd, '.git'))) {
|
|
32
|
+
console.log(`${colors.yellow}Skipping ESLint config installation: No .git folder found${colors.reset}`);
|
|
33
|
+
console.log(`${colors.yellow}This is a safety guard. If you want to install anyway, run with --force${colors.reset}`);
|
|
34
|
+
if (!process.argv.includes('--force')) {
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ANSI color codes for terminal output
|
|
41
|
+
const colors = {
|
|
42
|
+
reset: '\x1b[0m',
|
|
43
|
+
green: '\x1b[32m',
|
|
44
|
+
yellow: '\x1b[33m',
|
|
45
|
+
blue: '\x1b[34m',
|
|
46
|
+
cyan: '\x1b[36m',
|
|
47
|
+
bold: '\x1b[1m',
|
|
48
|
+
red: '\x1b[31m'
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Find existing ESLint config file
|
|
52
|
+
function findESLintConfig() {
|
|
53
|
+
const cwd = process.cwd();
|
|
54
|
+
const possibleConfigs = [
|
|
55
|
+
'eslint.config.js',
|
|
56
|
+
'eslint.config.cjs',
|
|
57
|
+
'eslint.config.mjs',
|
|
58
|
+
'.eslintrc.js',
|
|
59
|
+
'.eslintrc.cjs',
|
|
60
|
+
'.eslintrc.json',
|
|
61
|
+
'.eslintrc.yaml',
|
|
62
|
+
'.eslintrc.yml',
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
for (const configFile of possibleConfigs) {
|
|
66
|
+
const configPath = path.join(cwd, configFile);
|
|
67
|
+
if (fs.existsSync(configPath)) {
|
|
68
|
+
return { path: configPath, name: configFile, isESM: configFile.endsWith('.js') || configFile.endsWith('.mjs') };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check if pace-core config is already included
|
|
76
|
+
function hasPaceCoreConfig(configContent) {
|
|
77
|
+
// Check for pace-core config import/require
|
|
78
|
+
const paceCorePatterns = [
|
|
79
|
+
/@jmruthers\/pace-core\/eslint-config/,
|
|
80
|
+
/pace-core\/eslint-config/,
|
|
81
|
+
/paceCoreConfig/,
|
|
82
|
+
/pace-core-compliance/,
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
return paceCorePatterns.some(pattern => pattern.test(configContent));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Detect if file is ES module
|
|
89
|
+
function isESModule(filePath, content) {
|
|
90
|
+
if (filePath.endsWith('.mjs')) return true;
|
|
91
|
+
if (filePath.endsWith('.cjs')) return false;
|
|
92
|
+
if (filePath.endsWith('.js')) {
|
|
93
|
+
// Check for ES module indicators
|
|
94
|
+
return /^import\s+.*from|^export\s+default/.test(content.trim());
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Backup file before modification
|
|
100
|
+
function backupFile(filePath) {
|
|
101
|
+
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
102
|
+
fs.copyFileSync(filePath, backupPath);
|
|
103
|
+
return backupPath;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Setup ESLint configuration
|
|
107
|
+
function setupESLintConfig(force = false) {
|
|
108
|
+
const cwd = process.cwd();
|
|
109
|
+
const existingConfig = findESLintConfig();
|
|
110
|
+
|
|
111
|
+
if (existingConfig) {
|
|
112
|
+
// Read existing config
|
|
113
|
+
let content = fs.readFileSync(existingConfig.path, 'utf8');
|
|
114
|
+
const isESM = isESModule(existingConfig.path, content);
|
|
115
|
+
const format = isESM ? 'ES Module' : 'CommonJS';
|
|
116
|
+
|
|
117
|
+
console.log(`${colors.cyan}Found ESLint config:${colors.reset} ${existingConfig.name} (${format})`);
|
|
118
|
+
|
|
119
|
+
// Check if already configured
|
|
120
|
+
if (hasPaceCoreConfig(content)) {
|
|
121
|
+
if (!force) {
|
|
122
|
+
console.log(`${colors.blue}○${colors.reset} ${existingConfig.name} already includes pace-core rules`);
|
|
123
|
+
console.log(`${colors.blue} Use --force to update.${colors.reset}`);
|
|
124
|
+
return { action: 'skipped', file: existingConfig.name, format };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(`${colors.yellow}Updating existing ESLint config...${colors.reset}`);
|
|
128
|
+
} else {
|
|
129
|
+
console.log(`${colors.cyan}Adding pace-core config to ${existingConfig.name}...${colors.reset}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Backup before modification
|
|
133
|
+
const backupPath = backupFile(existingConfig.path);
|
|
134
|
+
console.log(`${colors.cyan} Backed up to ${path.basename(backupPath)}${colors.reset}`);
|
|
135
|
+
|
|
136
|
+
// Add pace-core config
|
|
137
|
+
if (isESM) {
|
|
138
|
+
// ES Module format
|
|
139
|
+
if (!content.includes('import paceCoreConfig')) {
|
|
140
|
+
// Add import at top (after other imports if they exist)
|
|
141
|
+
const importLines = content.match(/^(import\s+[^;]+;?\s*\n)+/m);
|
|
142
|
+
if (importLines) {
|
|
143
|
+
// Add after existing imports
|
|
144
|
+
content = content.replace(
|
|
145
|
+
importLines[0],
|
|
146
|
+
`${importLines[0]}import paceCoreConfig from '@jmruthers/pace-core/eslint-config';\n`
|
|
147
|
+
);
|
|
148
|
+
} else {
|
|
149
|
+
// Add at the beginning
|
|
150
|
+
content = `import paceCoreConfig from '@jmruthers/pace-core/eslint-config';\n${content}`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Add to export default array
|
|
155
|
+
if (content.includes('export default [')) {
|
|
156
|
+
// Already an array, add paceCoreConfig at the beginning
|
|
157
|
+
if (!content.includes('...paceCoreConfig')) {
|
|
158
|
+
content = content.replace(
|
|
159
|
+
/(export\s+default\s*\[)\s*/,
|
|
160
|
+
'$1\n ...paceCoreConfig,'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
} else if (content.includes('export default')) {
|
|
164
|
+
// Not an array, wrap it
|
|
165
|
+
const exportMatch = content.match(/(export\s+default\s+)(.+?)(;?\s*$)/s);
|
|
166
|
+
if (exportMatch) {
|
|
167
|
+
content = content.replace(
|
|
168
|
+
exportMatch[0],
|
|
169
|
+
`${exportMatch[1]}[\n ...paceCoreConfig,\n ${exportMatch[2]}\n];`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
// CommonJS format
|
|
175
|
+
if (!content.includes('require(\'@jmruthers/pace-core/eslint-config\')')) {
|
|
176
|
+
// Add require at top (after other requires if they exist)
|
|
177
|
+
const requireLines = content.match(/^(const\s+\w+\s*=\s*require\([^)]+\);\s*\n)+/m);
|
|
178
|
+
if (requireLines) {
|
|
179
|
+
content = content.replace(
|
|
180
|
+
requireLines[0],
|
|
181
|
+
`${requireLines[0]}const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');\n`
|
|
182
|
+
);
|
|
183
|
+
} else {
|
|
184
|
+
content = `const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');\n${content}`;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Add to module.exports
|
|
189
|
+
if (content.includes('module.exports = [')) {
|
|
190
|
+
// Already an array, add paceCoreConfig at the beginning
|
|
191
|
+
if (!content.includes('...paceCoreConfig')) {
|
|
192
|
+
content = content.replace(
|
|
193
|
+
/(module\.exports\s*=\s*\[)\s*/,
|
|
194
|
+
'$1\n ...paceCoreConfig,'
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
} else if (content.includes('module.exports =')) {
|
|
198
|
+
// Not an array, wrap it
|
|
199
|
+
const exportMatch = content.match(/(module\.exports\s*=\s*)(.+?)(;?\s*$)/s);
|
|
200
|
+
if (exportMatch) {
|
|
201
|
+
content = content.replace(
|
|
202
|
+
exportMatch[0],
|
|
203
|
+
`${exportMatch[1]}[\n ...paceCoreConfig,\n ${exportMatch[2]}\n];`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Write updated config
|
|
210
|
+
fs.writeFileSync(existingConfig.path, content, 'utf8');
|
|
211
|
+
console.log(`${colors.green}✓${colors.reset} Updated ${existingConfig.name}`);
|
|
212
|
+
return { action: 'updated', file: existingConfig.name, backup: backupPath, format };
|
|
213
|
+
} else {
|
|
214
|
+
// Create new ESLint config (default to ES modules)
|
|
215
|
+
const configPath = path.join(cwd, 'eslint.config.js');
|
|
216
|
+
const configContent = `import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
|
|
217
|
+
|
|
218
|
+
export default [
|
|
219
|
+
...paceCoreConfig,
|
|
220
|
+
// Your app-specific ESLint configuration
|
|
221
|
+
{
|
|
222
|
+
// Add your rules here
|
|
223
|
+
},
|
|
224
|
+
];
|
|
225
|
+
`;
|
|
226
|
+
|
|
227
|
+
console.log(`${colors.cyan}No ESLint config found. Creating eslint.config.js...${colors.reset}`);
|
|
228
|
+
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
229
|
+
console.log(`${colors.green}✓${colors.reset} Created eslint.config.js`);
|
|
230
|
+
console.log(`${colors.cyan} Edit eslint.config.js to add your app-specific ESLint rules.${colors.reset}`);
|
|
231
|
+
return { action: 'created', file: 'eslint.config.js', format: 'ES Module' };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Main execution
|
|
236
|
+
function main() {
|
|
237
|
+
checkSafetyGuards();
|
|
238
|
+
|
|
239
|
+
const force = process.argv.includes('--force');
|
|
240
|
+
|
|
241
|
+
if (force) {
|
|
242
|
+
console.log(`${colors.yellow}Warning: --force flag is set. This will overwrite existing configurations.${colors.reset}\n`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
console.log(`${colors.cyan}Setting up ESLint configuration from pace-core...${colors.reset}\n`);
|
|
247
|
+
const result = setupESLintConfig(force);
|
|
248
|
+
|
|
249
|
+
// Summary
|
|
250
|
+
console.log(`\n${colors.bold}Setup Summary:${colors.reset}`);
|
|
251
|
+
if (result.action === 'created') {
|
|
252
|
+
console.log(` ${colors.green}ESLint Config:${colors.reset} Created ${result.file} (${result.format})`);
|
|
253
|
+
} else if (result.action === 'updated') {
|
|
254
|
+
console.log(` ${colors.green}ESLint Config:${colors.reset} Updated ${result.file} (${result.format})`);
|
|
255
|
+
console.log(` ${colors.yellow}Backup:${colors.reset} ${path.basename(result.backup)}`);
|
|
256
|
+
} else {
|
|
257
|
+
console.log(` ${colors.blue}ESLint Config:${colors.reset} Already configured (${result.file}, ${result.format})`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log(`\n${colors.cyan}ESLint configuration is now available${colors.reset}`);
|
|
261
|
+
console.log(`\n${colors.cyan}Next steps:${colors.reset}`);
|
|
262
|
+
console.log(` • Run ${colors.bold}npm run lint${colors.reset} to verify ESLint is working`);
|
|
263
|
+
console.log(` • Edit your ESLint config to add app-specific rules`);
|
|
264
|
+
console.log(` • See ${colors.bold}packages/core/docs/standards/${colors.reset} for complete standards documentation`);
|
|
265
|
+
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error(`${colors.red}Error during setup:${colors.reset}`);
|
|
268
|
+
console.error(error.message);
|
|
269
|
+
if (error.stack) {
|
|
270
|
+
console.error(error.stack);
|
|
271
|
+
}
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Run if called directly
|
|
277
|
+
if (require.main === module) {
|
|
278
|
+
main();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = {
|
|
282
|
+
setupESLintConfig,
|
|
283
|
+
findESLintConfig
|
|
284
|
+
};
|
|
@@ -23,7 +23,7 @@ vi.mock('../test-utils', () => ({
|
|
|
23
23
|
describe('[helpers] componentTestPatterns', () => {
|
|
24
24
|
describe('testRenders', () => {
|
|
25
25
|
it('creates test that renders component without crashing', () => {
|
|
26
|
-
const TestComponent = () => <
|
|
26
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
27
27
|
const testFn = componentTestPatterns.testRenders(TestComponent);
|
|
28
28
|
|
|
29
29
|
expect(typeof testFn).toBe('function');
|
|
@@ -33,7 +33,7 @@ describe('[helpers] componentTestPatterns', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('creates test that renders component with props', () => {
|
|
36
|
-
const TestComponent = ({ name }: { name: string }) => <
|
|
36
|
+
const TestComponent = ({ name }: { name: string }) => <p data-testid="test-component">{name}</p>;
|
|
37
37
|
const testFn = componentTestPatterns.testRenders(TestComponent, { name: 'Test Name' });
|
|
38
38
|
|
|
39
39
|
expect(typeof testFn).toBe('function');
|
|
@@ -14,11 +14,11 @@ import { TestProviderWrapper, renderWithProviders, createMockUseUnifiedAuth, use
|
|
|
14
14
|
function TestComponent() {
|
|
15
15
|
const auth = useUnifiedAuth();
|
|
16
16
|
return (
|
|
17
|
-
<
|
|
17
|
+
<p>
|
|
18
18
|
<span data-testid="user-email">{auth.user?.email}</span>
|
|
19
19
|
<span data-testid="is-authenticated">{auth.isAuthenticated ? 'true' : 'false'}</span>
|
|
20
20
|
<span data-testid="app-name">{auth.appName}</span>
|
|
21
|
-
</
|
|
21
|
+
</p>
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -41,32 +41,32 @@ vi.mock('../fixtures/test-data', () => ({
|
|
|
41
41
|
|
|
42
42
|
describe('[helpers] renderWithProviders', () => {
|
|
43
43
|
it('renders component with QueryClient provider by default', () => {
|
|
44
|
-
const TestComponent = () => <
|
|
44
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
45
45
|
|
|
46
46
|
renderWithProviders(<TestComponent />);
|
|
47
47
|
|
|
48
|
-
expect(screen.getByTestId('test-component')).
|
|
48
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
it('renders component without QueryClient when withQueryClient is false', () => {
|
|
52
|
-
const TestComponent = () => <
|
|
52
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
53
53
|
|
|
54
54
|
renderWithProviders(<TestComponent />, { withQueryClient: false });
|
|
55
55
|
|
|
56
|
-
expect(screen.getByTestId('test-component')).
|
|
56
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
it('uses custom QueryClient when provided', () => {
|
|
60
60
|
const customQueryClient = new QueryClient();
|
|
61
|
-
const TestComponent = () => <
|
|
61
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
62
62
|
|
|
63
63
|
renderWithProviders(<TestComponent />, { queryClient: customQueryClient });
|
|
64
64
|
|
|
65
|
-
expect(screen.getByTestId('test-component')).
|
|
65
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
it('forwards additional render options', () => {
|
|
69
|
-
const TestComponent = () => <
|
|
69
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
70
70
|
|
|
71
71
|
const { container } = renderWithProviders(<TestComponent />, {
|
|
72
72
|
container: document.body
|
|
@@ -273,7 +273,7 @@ describe('[helpers] createMockSupabaseClient', () => {
|
|
|
273
273
|
|
|
274
274
|
it('creates mock query builder with chaining methods', () => {
|
|
275
275
|
const mockClient = createMockSupabaseClient();
|
|
276
|
-
const queryBuilder = mockClient.from('test_table');
|
|
276
|
+
const queryBuilder = (mockClient.from as any)('test_table');
|
|
277
277
|
|
|
278
278
|
expect(queryBuilder).toHaveProperty('select');
|
|
279
279
|
expect(queryBuilder).toHaveProperty('insert');
|
|
@@ -302,7 +302,7 @@ describe('[helpers] createMockSupabaseClient', () => {
|
|
|
302
302
|
|
|
303
303
|
describe('[helpers] TestWrapper', () => {
|
|
304
304
|
it('renders children with QueryClient provider', () => {
|
|
305
|
-
const TestComponent = () => <
|
|
305
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
306
306
|
|
|
307
307
|
render(
|
|
308
308
|
<TestWrapper>
|
|
@@ -310,7 +310,7 @@ describe('[helpers] TestWrapper', () => {
|
|
|
310
310
|
</TestWrapper>
|
|
311
311
|
);
|
|
312
312
|
|
|
313
|
-
expect(screen.getByTestId('test-component')).
|
|
313
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
314
314
|
});
|
|
315
315
|
});
|
|
316
316
|
|