Files
vibe-kanban/frontend/src/lib/mcpStrategies.ts
Louis Knight-Webb 36bde0b4b9 Frontend file naming eslint rule (vibe-kanban) (#1322)
* Perfect! Now let me create a summary for you:

##  ESLint Configuration Complete

The linter has identified **29 files** that need to be renamed:

### **Files to Rename:**

#### **Components → PascalCase (15 files)**
```
config-provider.tsx → ConfigProvider.tsx
diff-view-switch.tsx → DiffViewSwitch.tsx
logo.tsx → Logo.tsx
navbar.tsx → Navbar.tsx (in layout/)
search-bar.tsx → SearchBar.tsx
theme-provider.tsx → ThemeProvider.tsx
style-override.tsx → StyleOverride.tsx

copy-files-field.tsx → CopyFilesField.tsx (in projects/)
project-detail.tsx → ProjectDetail.tsx (in projects/)
project-form-fields.tsx → ProjectFormFields.tsx (in projects/)
project-list.tsx → ProjectList.tsx (in projects/)
```

#### **Contexts → PascalCase (2 files)**
```
project-context.tsx → ProjectContext.tsx
search-context.tsx → SearchContext.tsx
```

#### **Pages → PascalCase (3 files)**
```
full-attempt-logs.tsx → FullAttemptLogs.tsx
project-tasks.tsx → ProjectTasks.tsx
projects.tsx → Projects.tsx
```

#### **Lib → camelCase (2 files)**
```
caret-position.ts → caretPosition.ts
mcp-strategies.ts → mcpStrategies.ts
```

#### **Utils → camelCase (3 files)**
```
companion-install-task.ts → companionInstallTask.ts
script-placeholders.ts → scriptPlaceholders.ts
status-labels.ts → statusLabels.ts
```

#### **UI (shadcn) → kebab-case (4 files)**
```
ActionsDropdown.tsx → actions-dropdown.tsx
ImageUploadSection.tsx → image-upload-section.tsx
TitleDescriptionEditor.tsx → title-description-editor.tsx
DataTable.tsx → data-table.tsx (in table/)
Table.tsx → table.tsx (in table/)
ImageChipNode.tsx → image-chip-node.tsx (in wysiwyg/)
imageChipMarkdown.ts → image-chip-markdown.ts (in wysiwyg/)
```

#### **Entry Point (special case - 1 file)**
```
main.tsx → can stay as main.tsx (entry point convention)
```

**Next steps:** Should I proceed with renaming these files using `git mv`?

* ##  Complete! File Naming Standardization Successful

### **Summary**

Successfully implemented and enforced file naming conventions for the frontend:

### **What Was Done:**

1.  **Installed** `eslint-plugin-check-file@^2.8.0`

2.  **Configured ESLint** with file naming rules:
   - **Components (.tsx)**: `PascalCase`
   - **Hooks (.ts)**: `camelCase` (with `use` prefix)
   - **Utils/Lib (.ts)**: `camelCase`
   - **Shadcn UI**: `kebab-case` (library convention)
   - **Entry points**: Excluded (`main.tsx`, `vite-env.d.ts`)

3.  **Renamed 28 files** using `git mv`:
   - 10 components → PascalCase
   - 2 contexts → PascalCase
   - 3 pages → PascalCase
   - 2 lib files → camelCase
   - 3 utils → camelCase
   - 7 UI components → kebab-case
   - 1 utils component → PascalCase

4.  **Fixed all imports** across the codebase (77 files modified)

5.  **Verified**:
   -  ESLint passes (no filename errors)
   -  TypeScript check passes (no errors)
   -  Build successful

### **Git Status:**
- 28 files renamed (with history preserved via `git mv`)
- 77 total files changed (renames + import updates)

### **Ready for commit!**

The codebase now has consistent, enforceable file naming conventions that will prevent future inconsistencies.

* Cleanup script changes for task attempt 11f8d7b9-99b5-41ce-934c-5ce75008a200
2025-11-18 17:05:18 +00:00

113 lines
3.4 KiB
TypeScript

import type { McpConfig, JsonValue } from 'shared/types';
type JsonObject = Record<string, JsonValue>;
function isJsonObject(v: unknown): v is JsonObject {
return typeof v === 'object' && v !== null && !Array.isArray(v);
}
export class McpConfigStrategyGeneral {
static createFullConfig(cfg: McpConfig): JsonObject {
const cloned: JsonValue = JSON.parse(JSON.stringify(cfg.template ?? {}));
const fullConfig: JsonObject = isJsonObject(cloned) ? cloned : {};
let current: JsonObject = fullConfig;
for (let i = 0; i < cfg.servers_path.length - 1; i++) {
const key = cfg.servers_path[i];
const next = isJsonObject(current[key])
? (current[key] as JsonObject)
: undefined;
if (!next) current[key] = {};
current = current[key] as JsonObject;
}
if (cfg.servers_path.length > 0) {
const lastKey = cfg.servers_path[cfg.servers_path.length - 1];
current[lastKey] = cfg.servers;
}
return fullConfig;
}
static validateFullConfig(
mcp_config: McpConfig,
full_config: JsonValue
): void {
let current: JsonValue = full_config;
for (const key of mcp_config.servers_path) {
if (!isJsonObject(current)) {
throw new Error(
`Expected object at path: ${mcp_config.servers_path.join('.')}`
);
}
current = current[key];
if (current === undefined) {
throw new Error(
`Missing required field at path: ${mcp_config.servers_path.join('.')}`
);
}
}
if (!isJsonObject(current)) {
throw new Error('Servers configuration must be an object');
}
}
static extractServersForApi(
mcp_config: McpConfig,
full_config: JsonValue
): JsonObject {
let current: JsonValue = full_config;
for (const key of mcp_config.servers_path) {
if (!isJsonObject(current)) {
throw new Error(
`Expected object at path: ${mcp_config.servers_path.join('.')}`
);
}
current = current[key];
if (current === undefined) {
throw new Error(
`Missing required field at path: ${mcp_config.servers_path.join('.')}`
);
}
}
if (!isJsonObject(current)) {
throw new Error('Servers configuration must be an object');
}
return current;
}
static addPreconfiguredToConfig(
mcp_config: McpConfig,
existingConfig: JsonValue,
serverKey: string
): JsonObject {
const preconfVal = mcp_config.preconfigured;
if (!isJsonObject(preconfVal) || !(serverKey in preconfVal)) {
throw new Error(`Unknown preconfigured server '${serverKey}'`);
}
const updatedVal: JsonValue = JSON.parse(
JSON.stringify(existingConfig ?? {})
);
const updated: JsonObject = isJsonObject(updatedVal) ? updatedVal : {};
let current: JsonObject = updated;
for (let i = 0; i < mcp_config.servers_path.length - 1; i++) {
const key = mcp_config.servers_path[i];
const next = isJsonObject(current[key])
? (current[key] as JsonObject)
: undefined;
if (!next) current[key] = {};
current = current[key] as JsonObject;
}
if (mcp_config.servers_path.length === 0) {
current[serverKey] = preconfVal[serverKey];
return updated;
}
const lastKey = mcp_config.servers_path[mcp_config.servers_path.length - 1];
if (!isJsonObject(current[lastKey])) current[lastKey] = {};
(current[lastKey] as JsonObject)[serverKey] = preconfVal[serverKey];
return updated;
}
}