mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-25 23:35:43 +00:00
chore: apply low-risk lint cleanup
This commit is contained in:
+1
-8
@@ -93,14 +93,7 @@
|
||||
"useGetterReturn": "error"
|
||||
}
|
||||
},
|
||||
"includes": [
|
||||
"**",
|
||||
"**/dist",
|
||||
"**/.eslintrc.cjs",
|
||||
"**",
|
||||
"**/dist",
|
||||
"**/.eslintrc.cjs"
|
||||
]
|
||||
"includes": ["**", "**/dist", "**/.eslintrc.cjs", "**", "**/dist", "**/.eslintrc.cjs"]
|
||||
},
|
||||
"javascript": { "formatter": { "quoteStyle": "double" } },
|
||||
"overrides": [
|
||||
|
||||
+20
-21
@@ -1,23 +1,22 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.cjs",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "stone",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"registries": {}
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.cjs",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "stone",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"registries": {}
|
||||
}
|
||||
|
||||
|
||||
+153
-122
@@ -5,37 +5,37 @@
|
||||
* uninstall, enable/disable) and exposes them to the renderer via preload.
|
||||
*/
|
||||
|
||||
import { BrowserWindow, ipcMain, dialog, shell } from 'electron';
|
||||
import { BrowserWindow, dialog, ipcMain, shell } from "electron";
|
||||
import {
|
||||
discoverExtensions,
|
||||
getRegisteredExtensions,
|
||||
getExtension,
|
||||
setExtensionStatus,
|
||||
installExtensionFromPath,
|
||||
uninstallExtension,
|
||||
getExtensionsDirectory,
|
||||
} from './extensionLoader';
|
||||
discoverExtensions,
|
||||
getExtension,
|
||||
getExtensionsDirectory,
|
||||
getRegisteredExtensions,
|
||||
installExtensionFromPath,
|
||||
setExtensionStatus,
|
||||
uninstallExtension,
|
||||
} from "./extensionLoader";
|
||||
import {
|
||||
searchMarketplace,
|
||||
getMarketplaceExtension,
|
||||
downloadAndInstallExtension,
|
||||
fetchPendingReviews,
|
||||
updateReviewStatus,
|
||||
submitExtensionForReview,
|
||||
} from './extensionMarketplace';
|
||||
import type { ExtensionInfo, MarketplaceReviewStatus } from './extensionTypes';
|
||||
downloadAndInstallExtension,
|
||||
fetchPendingReviews,
|
||||
getMarketplaceExtension,
|
||||
searchMarketplace,
|
||||
submitExtensionForReview,
|
||||
updateReviewStatus,
|
||||
} from "./extensionMarketplace";
|
||||
import type { ExtensionInfo, MarketplaceReviewStatus } from "./extensionTypes";
|
||||
|
||||
/**
|
||||
* Serialize extension info for IPC transfer (strip non-serializable fields).
|
||||
*/
|
||||
function serializeExtensionInfo(info: ExtensionInfo) {
|
||||
return {
|
||||
manifest: info.manifest,
|
||||
status: info.status,
|
||||
path: info.path,
|
||||
error: info.error,
|
||||
builtin: info.builtin ?? false,
|
||||
};
|
||||
return {
|
||||
manifest: info.manifest,
|
||||
status: info.status,
|
||||
path: info.path,
|
||||
error: info.error,
|
||||
builtin: info.builtin ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,121 +43,152 @@ function serializeExtensionInfo(info: ExtensionInfo) {
|
||||
* Call this once during app initialization (in main.ts).
|
||||
*/
|
||||
export function registerExtensionIpcHandlers(): void {
|
||||
// Discover all extensions (builtin + user-installed)
|
||||
ipcMain.handle('extensions:discover', async () => {
|
||||
const extensions = await discoverExtensions();
|
||||
return extensions.map(serializeExtensionInfo);
|
||||
});
|
||||
// Discover all extensions (builtin + user-installed)
|
||||
ipcMain.handle("extensions:discover", async () => {
|
||||
const extensions = await discoverExtensions();
|
||||
return extensions.map(serializeExtensionInfo);
|
||||
});
|
||||
|
||||
// List currently registered extensions
|
||||
ipcMain.handle('extensions:list', () => {
|
||||
return getRegisteredExtensions().map(serializeExtensionInfo);
|
||||
});
|
||||
// List currently registered extensions
|
||||
ipcMain.handle("extensions:list", () => {
|
||||
return getRegisteredExtensions().map(serializeExtensionInfo);
|
||||
});
|
||||
|
||||
// Get a specific extension by ID
|
||||
ipcMain.handle('extensions:get', (_event, id: string) => {
|
||||
const ext = getExtension(id);
|
||||
return ext ? serializeExtensionInfo(ext) : null;
|
||||
});
|
||||
// Get a specific extension by ID
|
||||
ipcMain.handle("extensions:get", (_event, id: string) => {
|
||||
const ext = getExtension(id);
|
||||
return ext ? serializeExtensionInfo(ext) : null;
|
||||
});
|
||||
|
||||
// Enable an extension
|
||||
ipcMain.handle('extensions:enable', async (_event, id: string) => {
|
||||
return setExtensionStatus(id, 'active');
|
||||
});
|
||||
// Enable an extension
|
||||
ipcMain.handle("extensions:enable", async (_event, id: string) => {
|
||||
return setExtensionStatus(id, "active");
|
||||
});
|
||||
|
||||
// Disable an extension
|
||||
ipcMain.handle('extensions:disable', async (_event, id: string) => {
|
||||
return setExtensionStatus(id, 'disabled');
|
||||
});
|
||||
// Disable an extension
|
||||
ipcMain.handle("extensions:disable", async (_event, id: string) => {
|
||||
return setExtensionStatus(id, "disabled");
|
||||
});
|
||||
|
||||
// Install an extension from a folder picker
|
||||
ipcMain.handle('extensions:install-from-folder', async (event) => {
|
||||
const window = BrowserWindow.fromWebContents(event.sender);
|
||||
const result = await dialog.showOpenDialog(window!, {
|
||||
title: 'Select Extension Folder',
|
||||
properties: ['openDirectory'],
|
||||
message: 'Select a folder containing a recordly-extension.json manifest',
|
||||
});
|
||||
// Install an extension from a folder picker
|
||||
ipcMain.handle("extensions:install-from-folder", async (event) => {
|
||||
const window = BrowserWindow.fromWebContents(event.sender);
|
||||
const result = await dialog.showOpenDialog(window!, {
|
||||
title: "Select Extension Folder",
|
||||
properties: ["openDirectory"],
|
||||
message: "Select a folder containing a recordly-extension.json manifest",
|
||||
});
|
||||
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
return { success: false, reason: 'cancelled' };
|
||||
}
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
return { success: false, reason: "cancelled" };
|
||||
}
|
||||
|
||||
const info = await installExtensionFromPath(result.filePaths[0]);
|
||||
if (!info) {
|
||||
return { success: false, reason: 'Invalid extension: missing or invalid recordly-extension.json' };
|
||||
}
|
||||
const info = await installExtensionFromPath(result.filePaths[0]);
|
||||
if (!info) {
|
||||
return {
|
||||
success: false,
|
||||
reason: "Invalid extension: missing or invalid recordly-extension.json",
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true, extension: serializeExtensionInfo(info) };
|
||||
});
|
||||
return { success: true, extension: serializeExtensionInfo(info) };
|
||||
});
|
||||
|
||||
// Uninstall an extension
|
||||
ipcMain.handle('extensions:uninstall', async (_event, id: string) => {
|
||||
const success = await uninstallExtension(id);
|
||||
return { success };
|
||||
});
|
||||
// Uninstall an extension
|
||||
ipcMain.handle("extensions:uninstall", async (_event, id: string) => {
|
||||
const success = await uninstallExtension(id);
|
||||
return { success };
|
||||
});
|
||||
|
||||
// Get extensions directory path
|
||||
ipcMain.handle('extensions:get-directory', () => {
|
||||
return getExtensionsDirectory();
|
||||
});
|
||||
// Get extensions directory path
|
||||
ipcMain.handle("extensions:get-directory", () => {
|
||||
return getExtensionsDirectory();
|
||||
});
|
||||
|
||||
// Open extensions directory in file manager
|
||||
ipcMain.handle('extensions:open-directory', async () => {
|
||||
const dir = getExtensionsDirectory();
|
||||
await shell.openPath(dir);
|
||||
return { success: true };
|
||||
});
|
||||
// Open extensions directory in file manager
|
||||
ipcMain.handle("extensions:open-directory", async () => {
|
||||
const dir = getExtensionsDirectory();
|
||||
await shell.openPath(dir);
|
||||
return { success: true };
|
||||
});
|
||||
|
||||
// ── Marketplace ─────────────────────────────────────────────────────
|
||||
// ── Marketplace ─────────────────────────────────────────────────────
|
||||
|
||||
// Search/browse marketplace
|
||||
ipcMain.handle('extensions:marketplace-search', async (_event, params: {
|
||||
query?: string;
|
||||
tags?: string[];
|
||||
sort?: 'popular' | 'recent' | 'rating';
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}) => {
|
||||
try {
|
||||
return await searchMarketplace(params);
|
||||
} catch (err: any) {
|
||||
return { extensions: [], total: 0, page: 1, pageSize: 20, error: err.message };
|
||||
}
|
||||
});
|
||||
// Search/browse marketplace
|
||||
ipcMain.handle(
|
||||
"extensions:marketplace-search",
|
||||
async (
|
||||
_event,
|
||||
params: {
|
||||
query?: string;
|
||||
tags?: string[];
|
||||
sort?: "popular" | "recent" | "rating";
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
},
|
||||
) => {
|
||||
try {
|
||||
return await searchMarketplace(params);
|
||||
} catch (err: unknown) {
|
||||
return {
|
||||
extensions: [],
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Get a specific marketplace extension
|
||||
ipcMain.handle('extensions:marketplace-get', async (_event, id: string) => {
|
||||
return getMarketplaceExtension(id);
|
||||
});
|
||||
// Get a specific marketplace extension
|
||||
ipcMain.handle("extensions:marketplace-get", async (_event, id: string) => {
|
||||
return getMarketplaceExtension(id);
|
||||
});
|
||||
|
||||
// Download and install a marketplace extension
|
||||
ipcMain.handle('extensions:marketplace-install', async (_event, extensionId: string, downloadUrl: string) => {
|
||||
return downloadAndInstallExtension(extensionId, downloadUrl);
|
||||
});
|
||||
// Download and install a marketplace extension
|
||||
ipcMain.handle(
|
||||
"extensions:marketplace-install",
|
||||
async (_event, extensionId: string, downloadUrl: string) => {
|
||||
return downloadAndInstallExtension(extensionId, downloadUrl);
|
||||
},
|
||||
);
|
||||
|
||||
// Submit an extension for marketplace review
|
||||
ipcMain.handle('extensions:marketplace-submit', async (_event, extensionId: string) => {
|
||||
return submitExtensionForReview(extensionId);
|
||||
});
|
||||
// Submit an extension for marketplace review
|
||||
ipcMain.handle("extensions:marketplace-submit", async (_event, extensionId: string) => {
|
||||
return submitExtensionForReview(extensionId);
|
||||
});
|
||||
|
||||
// ── Admin Review System ─────────────────────────────────────────────
|
||||
// ── Admin Review System ─────────────────────────────────────────────
|
||||
|
||||
// Fetch pending reviews (admin only)
|
||||
ipcMain.handle('extensions:reviews-list', async (_event, params: {
|
||||
status?: MarketplaceReviewStatus;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}) => {
|
||||
try {
|
||||
return await fetchPendingReviews(params);
|
||||
} catch (err: any) {
|
||||
return { reviews: [], total: 0, error: err.message };
|
||||
}
|
||||
});
|
||||
// Fetch pending reviews (admin only)
|
||||
ipcMain.handle(
|
||||
"extensions:reviews-list",
|
||||
async (
|
||||
_event,
|
||||
params: {
|
||||
status?: MarketplaceReviewStatus;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
},
|
||||
) => {
|
||||
try {
|
||||
return await fetchPendingReviews(params);
|
||||
} catch (err: unknown) {
|
||||
return {
|
||||
reviews: [],
|
||||
total: 0,
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Update review status (admin only)
|
||||
ipcMain.handle('extensions:review-update', async (_event, reviewId: string, status: MarketplaceReviewStatus, notes?: string) => {
|
||||
return updateReviewStatus(reviewId, status, notes);
|
||||
});
|
||||
// Update review status (admin only)
|
||||
ipcMain.handle(
|
||||
"extensions:review-update",
|
||||
async (_event, reviewId: string, status: MarketplaceReviewStatus, notes?: string) => {
|
||||
return updateReviewStatus(reviewId, status, notes);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
+29
-30
@@ -1,31 +1,30 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src", "electron"],
|
||||
"exclude": ["**/*.test.ts", "**/*.test.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src", "electron"],
|
||||
"exclude": ["**/*.test.ts", "**/*.test.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
+16
-17
@@ -1,19 +1,18 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import path from 'node:path'
|
||||
import path from "node:path";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: [
|
||||
'src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}',
|
||||
'electron/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}',
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "node",
|
||||
include: [
|
||||
"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}",
|
||||
"electron/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}",
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "src"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user