mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-18 01:19:24 +00:00
TypeId
This commit is contained in:
parent
c0caf3bc6e
commit
6e553b23f6
@ -5,7 +5,7 @@ import rainbowStyles from '../../styles/rainbow.module.css';
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
import EditNoteIcon from "@mui/icons-material/EditNote";
|
||||
import FolderIcon from "@mui/icons-material/Folder";
|
||||
import { WorkbenchType, isValidWorkbench } from '../../types/navigation';
|
||||
import { WorkbenchType, isValidWorkbench } from '../../types/workbench';
|
||||
import { Tooltip } from "./Tooltip";
|
||||
|
||||
const viewOptionStyle = {
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
Modal
|
||||
} from '@mantine/core';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import { ToolRegistryEntry } from '../../../data/toolsTaxonomy';
|
||||
import { ToolRegistry } from '../../../data/toolsTaxonomy';
|
||||
import ToolConfigurationModal from './ToolConfigurationModal';
|
||||
import ToolList from './ToolList';
|
||||
import IconSelector from './IconSelector';
|
||||
@ -24,7 +24,7 @@ interface AutomationCreationProps {
|
||||
existingAutomation?: AutomationConfig;
|
||||
onBack: () => void;
|
||||
onComplete: (automation: AutomationConfig) => void;
|
||||
toolRegistry: Record<string, ToolRegistryEntry>;
|
||||
toolRegistry: ToolRegistry;
|
||||
}
|
||||
|
||||
export default function AutomationCreation({ mode, existingAutomation, onBack, onComplete, toolRegistry }: AutomationCreationProps) {
|
||||
|
@ -33,7 +33,7 @@ export default function AutomationRun({ automation, onComplete, automateOperatio
|
||||
React.useEffect(() => {
|
||||
if (automation?.operations) {
|
||||
const steps = automation.operations.map((op: any, index: number) => {
|
||||
const tool = toolRegistry[op.operation];
|
||||
const tool = toolRegistry[op.operation as keyof typeof toolRegistry];
|
||||
return {
|
||||
id: `${op.operation}-${index}`,
|
||||
operation: op.operation,
|
||||
|
@ -35,7 +35,7 @@ export default function ToolConfigurationModal({ opened, tool, onSave, onCancel,
|
||||
const [isValid, setIsValid] = useState(true);
|
||||
|
||||
// Get tool info from registry
|
||||
const toolInfo = toolRegistry[tool.operation];
|
||||
const toolInfo = toolRegistry[tool.operation as keyof ToolRegistry];
|
||||
const SettingsComponent = toolInfo?.settingsComponent;
|
||||
|
||||
// Initialize parameters from tool (which should contain defaults from registry)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { createContext, useContext, useReducer, useCallback } from 'react';
|
||||
import { WorkbenchType, ToolId, getDefaultWorkbench } from '../types/navigation';
|
||||
import { WorkbenchType, getDefaultWorkbench } from '../types/workbench';
|
||||
import { ToolId, isValidToolId } from '../types/toolId';
|
||||
import { useFlatToolRegistry } from '../data/useTranslatedToolRegistry';
|
||||
|
||||
/**
|
||||
@ -167,10 +168,13 @@ export const NavigationProvider: React.FC<{
|
||||
}
|
||||
|
||||
// Look up the tool in the registry to get its proper workbench
|
||||
const tool = toolRegistry[toolId];
|
||||
|
||||
const tool = isValidToolId(toolId)? toolRegistry[toolId] : null;
|
||||
const workbench = tool ? (tool.workbench || getDefaultWorkbench()) : getDefaultWorkbench();
|
||||
|
||||
dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId, workbench } });
|
||||
// Validate toolId and convert to ToolId type
|
||||
const validToolId = isValidToolId(toolId) ? toolId : null;
|
||||
dispatch({ type: 'SET_TOOL_AND_WORKBENCH', payload: { toolId: validToolId, workbench } });
|
||||
}, [toolRegistry])
|
||||
};
|
||||
|
||||
|
@ -6,10 +6,11 @@
|
||||
import React, { createContext, useContext, useReducer, useCallback, useMemo } from 'react';
|
||||
import { useToolManagement } from '../hooks/useToolManagement';
|
||||
import { PageEditorFunctions } from '../types/pageEditor';
|
||||
import { ToolRegistryEntry } from '../data/toolsTaxonomy';
|
||||
import { ToolRegistryEntry, ToolRegistry } from '../data/toolsTaxonomy';
|
||||
import { useNavigationActions, useNavigationState } from './NavigationContext';
|
||||
import { ToolId, isValidToolId } from '../types/toolId';
|
||||
import { useNavigationUrlSync } from '../hooks/useUrlSync';
|
||||
import { getDefaultWorkbench } from '../types/navigation';
|
||||
import { getDefaultWorkbench } from '../types/workbench';
|
||||
|
||||
// State interface
|
||||
interface ToolWorkflowState {
|
||||
@ -84,7 +85,7 @@ interface ToolWorkflowContextValue extends ToolWorkflowState {
|
||||
setSearchQuery: (query: string) => void;
|
||||
|
||||
// Tool Actions
|
||||
selectTool: (toolId: string) => void;
|
||||
selectTool: (toolId: ToolId | null) => void;
|
||||
clearToolSelection: () => void;
|
||||
|
||||
// Tool Reset Actions
|
||||
@ -174,7 +175,8 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
|
||||
// Workflow actions (compound actions that coordinate multiple state changes)
|
||||
const handleToolSelect = useCallback((toolId: string) => {
|
||||
// Set the selected tool and determine the appropriate workbench
|
||||
actions.setSelectedTool(toolId);
|
||||
const validToolId = isValidToolId(toolId) ? toolId : null;
|
||||
actions.setSelectedTool(validToolId);
|
||||
|
||||
// Get the tool from registry to determine workbench
|
||||
const tool = getSelectedTool(toolId);
|
||||
@ -229,7 +231,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
|
||||
navigationState.selectedTool,
|
||||
handleToolSelect,
|
||||
handleBackToTools,
|
||||
toolRegistry,
|
||||
toolRegistry as ToolRegistry,
|
||||
true
|
||||
);
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { type TFunction } from 'i18next';
|
||||
import React from 'react';
|
||||
import { ToolOperationHook, ToolOperationConfig } from '../hooks/tools/shared/useToolOperation';
|
||||
import { ToolOperationConfig } from '../hooks/tools/shared/useToolOperation';
|
||||
import { BaseToolProps } from '../types/tool';
|
||||
import { BaseParameters } from '../types/parameters';
|
||||
import { WorkbenchType } from '../types/navigation';
|
||||
import { WorkbenchType } from '../types/workbench';
|
||||
import { ToolId } from '../types/toolId';
|
||||
|
||||
export enum SubcategoryId {
|
||||
SIGNING = 'signing',
|
||||
@ -47,7 +47,7 @@ export type ToolRegistryEntry = {
|
||||
settingsComponent?: React.ComponentType<any>;
|
||||
}
|
||||
|
||||
export type ToolRegistry = Record<string /* FIX ME: Should be ToolId */, ToolRegistryEntry>;
|
||||
export type ToolRegistry = Record<ToolId, ToolRegistryEntry>;
|
||||
|
||||
export const SUBCATEGORY_ORDER: SubcategoryId[] = [
|
||||
SubcategoryId.SIGNING,
|
||||
|
@ -39,6 +39,7 @@ import AddWatermarkSingleStepSettings from "../components/tools/addWatermark/Add
|
||||
import OCRSettings from "../components/tools/ocr/OCRSettings";
|
||||
import ConvertSettings from "../components/tools/convert/ConvertSettings";
|
||||
import ChangePermissionsSettings from "../components/tools/changePermissions/ChangePermissionsSettings";
|
||||
import { ToolId } from "../types/toolId";
|
||||
|
||||
const showPlaceholderTools = true; // Show all tools; grey out unavailable ones in UI
|
||||
|
||||
@ -162,7 +163,7 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
operationConfig: addPasswordOperationConfig,
|
||||
settingsComponent: AddPasswordSettings,
|
||||
},
|
||||
watermark: {
|
||||
addWatermark: {
|
||||
icon: <LocalIcon icon="branding-watermark-outline-rounded" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.watermark.title", "Add Watermark"),
|
||||
component: AddWatermark,
|
||||
@ -258,7 +259,7 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
|
||||
// Document Review
|
||||
|
||||
read: {
|
||||
read: {
|
||||
icon: <LocalIcon icon="article-rounded" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.read.title", "Read"),
|
||||
component: null,
|
||||
@ -284,7 +285,6 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
icon: <LocalIcon icon="crop-rounded" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.crop.title", "Crop PDF"),
|
||||
component: null,
|
||||
|
||||
description: t("home.crop.desc", "Crop a PDF to reduce its size (maintains text!)"),
|
||||
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||
@ -293,16 +293,14 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
icon: <LocalIcon icon="rotate-right-rounded" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.rotate.title", "Rotate"),
|
||||
component: null,
|
||||
|
||||
description: t("home.rotate.desc", "Easily rotate your PDFs."),
|
||||
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||
},
|
||||
splitPdf: {
|
||||
split: {
|
||||
icon: <LocalIcon icon="content-cut-rounded" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.split.title", "Split"),
|
||||
component: SplitPdfPanel,
|
||||
|
||||
description: t("home.split.desc", "Split PDFs into multiple documents"),
|
||||
categoryId: ToolCategoryId.STANDARD_TOOLS,
|
||||
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||
@ -372,7 +370,7 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
|
||||
// Extraction
|
||||
|
||||
extractPages: {
|
||||
"extract-page": {
|
||||
icon: <LocalIcon icon="upload-rounded" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.extractPages.title", "Extract Pages"),
|
||||
component: null,
|
||||
@ -490,7 +488,7 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
|
||||
// Advanced Formatting
|
||||
|
||||
adjustContrast: {
|
||||
"adjust-contrast": {
|
||||
icon: <LocalIcon icon="palette" width="1.5rem" height="1.5rem" />,
|
||||
name: t("home.adjustContrast.title", "Adjust Colors/Contrast"),
|
||||
component: null,
|
||||
@ -700,9 +698,9 @@ export function useFlatToolRegistry(): ToolRegistry {
|
||||
return allTools;
|
||||
}
|
||||
const filteredTools = Object.keys(allTools)
|
||||
.filter((key) => allTools[key].component !== null || allTools[key].link)
|
||||
.filter((key) => allTools[key as ToolId].component !== null || allTools[key as ToolId].link)
|
||||
.reduce((obj, key) => {
|
||||
obj[key] = allTools[key];
|
||||
obj[key as ToolId] = allTools[key as ToolId];
|
||||
return obj;
|
||||
}, {} as ToolRegistry);
|
||||
return filteredTools;
|
||||
|
@ -2,12 +2,12 @@ import { useState, useEffect, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AutomationTool, AutomationConfig, AutomationMode } from '../../../types/automation';
|
||||
import { AUTOMATION_CONSTANTS } from '../../../constants/automation';
|
||||
import { ToolRegistryEntry } from '../../../data/toolsTaxonomy';
|
||||
import { ToolRegistry } from '../../../data/toolsTaxonomy';
|
||||
|
||||
interface UseAutomationFormProps {
|
||||
mode: AutomationMode;
|
||||
existingAutomation?: AutomationConfig;
|
||||
toolRegistry: Record<string, ToolRegistryEntry>;
|
||||
toolRegistry: ToolRegistry;
|
||||
}
|
||||
|
||||
export function useAutomationForm({ mode, existingAutomation, toolRegistry }: UseAutomationFormProps) {
|
||||
@ -19,12 +19,12 @@ export function useAutomationForm({ mode, existingAutomation, toolRegistry }: Us
|
||||
const [selectedTools, setSelectedTools] = useState<AutomationTool[]>([]);
|
||||
|
||||
const getToolName = useCallback((operation: string) => {
|
||||
const tool = toolRegistry?.[operation] as any;
|
||||
const tool = toolRegistry?.[operation as keyof ToolRegistry] as any;
|
||||
return tool?.name || t(`tools.${operation}.name`, operation);
|
||||
}, [toolRegistry, t]);
|
||||
|
||||
const getToolDefaultParameters = useCallback((operation: string): Record<string, any> => {
|
||||
const config = toolRegistry[operation]?.operationConfig;
|
||||
const config = toolRegistry[operation as keyof ToolRegistry]?.operationConfig;
|
||||
if (config?.defaultParameters) {
|
||||
return { ...config.defaultParameters };
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigationActions, useNavigationState } from '../contexts/NavigationContext';
|
||||
import { ToolId } from '../types/toolId';
|
||||
|
||||
// Material UI Icons
|
||||
import CompressIcon from '@mui/icons-material/Compress';
|
||||
@ -9,7 +10,7 @@ import CropIcon from '@mui/icons-material/Crop';
|
||||
import TextFieldsIcon from '@mui/icons-material/TextFields';
|
||||
|
||||
export interface SuggestedTool {
|
||||
id: string /* FIX ME: Should be ToolId */;
|
||||
id: ToolId;
|
||||
title: string;
|
||||
icon: React.ComponentType<any>;
|
||||
navigate: () => void;
|
||||
@ -32,7 +33,7 @@ const ALL_SUGGESTED_TOOLS: Omit<SuggestedTool, 'navigate'>[] = [
|
||||
icon: CleaningServicesIcon
|
||||
},
|
||||
{
|
||||
id: 'splitPdf',
|
||||
id: 'split',
|
||||
title: 'Split',
|
||||
icon: CropIcon
|
||||
},
|
||||
|
@ -35,7 +35,7 @@ export const useToolManagement = (): ToolManagementResult => {
|
||||
|
||||
const isToolAvailable = useCallback((toolKey: string): boolean => {
|
||||
if (endpointsLoading) return true;
|
||||
const endpoints = baseRegistry[toolKey]?.endpoints || [];
|
||||
const endpoints = baseRegistry[toolKey as keyof typeof baseRegistry]?.endpoints || [];
|
||||
return endpoints.length === 0 || endpoints.some((endpoint: string) => endpointStatus[endpoint] === true);
|
||||
}, [endpointsLoading, endpointStatus, baseRegistry]);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { useEffect, useCallback, useRef } from 'react';
|
||||
import { WorkbenchType, ToolId } from '../types/navigation';
|
||||
import { ToolId } from '../types/toolId';
|
||||
import { parseToolRoute, updateToolRoute, clearToolRoute } from '../utils/urlRouting';
|
||||
import { ToolRegistry } from '../data/toolsTaxonomy';
|
||||
import { firePixel } from '../utils/scarfTracking';
|
||||
|
@ -161,7 +161,7 @@ const Automate = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
|
||||
const filesPlaceholder = useMemo(() => {
|
||||
if (currentStep === AUTOMATION_STEPS.RUN && stepData.automation?.operations?.length) {
|
||||
const firstOperation = stepData.automation.operations[0];
|
||||
const toolConfig = toolRegistry[firstOperation.operation];
|
||||
const toolConfig = toolRegistry[firstOperation.operation as keyof typeof toolRegistry];
|
||||
|
||||
// Check if the tool has supportedFormats that include non-PDF formats
|
||||
if (toolConfig?.supportedFormats && toolConfig.supportedFormats.length > 1) {
|
||||
|
@ -2,14 +2,8 @@
|
||||
* Navigation types for workbench and tool separation
|
||||
*/
|
||||
|
||||
// Define workbench values once as source of truth
|
||||
const WORKBENCH_TYPES = ['viewer', 'pageEditor', 'fileEditor'] as const;
|
||||
|
||||
// Workbench types - how the user interacts with content
|
||||
export type WorkbenchType = typeof WORKBENCH_TYPES[number];
|
||||
|
||||
// Tool identity - what PDF operation we're performing (derived from registry)
|
||||
export type ToolId = string;
|
||||
import { WorkbenchType } from './workbench';
|
||||
import { ToolId } from './toolId';
|
||||
|
||||
// Navigation state
|
||||
export interface NavigationState {
|
||||
@ -17,12 +11,6 @@ export interface NavigationState {
|
||||
selectedTool: ToolId | null;
|
||||
}
|
||||
|
||||
export const getDefaultWorkbench = (): WorkbenchType => 'fileEditor';
|
||||
|
||||
// Type guard using the same source of truth - no duplication
|
||||
export const isValidWorkbench = (value: string): value is WorkbenchType => {
|
||||
return WORKBENCH_TYPES.includes(value as WorkbenchType);
|
||||
};
|
||||
|
||||
// Route parsing result
|
||||
export interface ToolRoute {
|
||||
|
@ -2,7 +2,8 @@
|
||||
* Navigation action interfaces to break circular dependencies
|
||||
*/
|
||||
|
||||
import { WorkbenchType, ToolId } from './navigation';
|
||||
import { WorkbenchType } from './workbench';
|
||||
import { ToolId } from './toolId';
|
||||
|
||||
export interface NavigationActions {
|
||||
setWorkbench: (workbench: WorkbenchType) => void;
|
||||
|
25
frontend/src/types/toolId.ts
Normal file
25
frontend/src/types/toolId.ts
Normal file
@ -0,0 +1,25 @@
|
||||
// Define all possible tool IDs as source of truth
|
||||
const TOOL_IDS = [
|
||||
'certSign', 'sign', 'addPassword', 'remove-password', 'removePages', 'remove-blank-pages', 'remove-annotations', 'remove-image',
|
||||
'change-permissions', 'addWatermark',
|
||||
'sanitize', 'auto-split-pages', 'auto-split-by-size-count', 'split', 'mergePdfs',
|
||||
'convert', 'ocr', 'add-image', 'rotate',
|
||||
'detect-split-scanned-photos',
|
||||
'edit-table-of-contents',
|
||||
'scanner-effect',
|
||||
'auto-rename-pdf-file', 'multi-page-layout', 'adjust-page-size-scale', 'adjust-contrast', 'cropPdf', 'single-large-page', 'multi-tool',
|
||||
'repair', 'compare', 'addPageNumbers', 'redact',
|
||||
'flatten', 'remove-certificate-sign',
|
||||
'unlock-pdf-forms', 'compress', 'extract-page', 'reorganize-pages', 'extract-images',
|
||||
'add-stamp', 'add-attachments', 'change-metadata', 'overlay-pdfs',
|
||||
'manage-certificates', 'get-all-info-on-pdf', 'validate-pdf-signature', 'read', 'automate', 'replace-and-invert-color',
|
||||
'show-javascript', 'dev-api', 'dev-folder-scanning', 'dev-sso-guide', 'dev-airgapped'
|
||||
] as const;
|
||||
|
||||
// Tool identity - what PDF operation we're performing (type-safe)
|
||||
export type ToolId = typeof TOOL_IDS[number];
|
||||
|
||||
// Type guard using the same source of truth
|
||||
export const isValidToolId = (value: string): value is ToolId => {
|
||||
return TOOL_IDS.includes(value as ToolId);
|
||||
};
|
12
frontend/src/types/workbench.ts
Normal file
12
frontend/src/types/workbench.ts
Normal file
@ -0,0 +1,12 @@
|
||||
// Define workbench values once as source of truth
|
||||
const WORKBENCH_TYPES = ['viewer', 'pageEditor', 'fileEditor'] as const;
|
||||
|
||||
// Workbench types - how the user interacts with content
|
||||
export type WorkbenchType = typeof WORKBENCH_TYPES[number];
|
||||
|
||||
export const getDefaultWorkbench = (): WorkbenchType => 'fileEditor';
|
||||
|
||||
// Type guard using the same source of truth
|
||||
export const isValidWorkbench = (value: string): value is WorkbenchType => {
|
||||
return WORKBENCH_TYPES.includes(value as WorkbenchType);
|
||||
};
|
@ -31,7 +31,7 @@ export const executeToolOperationWithPrefix = async (
|
||||
): Promise<File[]> => {
|
||||
console.log(`🔧 Executing tool: ${operationName}`, { parameters, fileCount: files.length });
|
||||
|
||||
const config = toolRegistry[operationName]?.operationConfig;
|
||||
const config = toolRegistry[operationName as keyof ToolRegistry]?.operationConfig;
|
||||
if (!config) {
|
||||
console.error(`❌ Tool operation not supported: ${operationName}`);
|
||||
throw new Error(`Tool operation not supported: ${operationName}`);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { ToolId } from '../types/navigation';
|
||||
import { ToolId } from '../types/toolId';
|
||||
|
||||
// Map URL paths to tool keys (multiple URLs can map to same tool)
|
||||
export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
|
||||
'/split-pdfs': 'split',
|
||||
'/split': 'split',
|
||||
'/merge-pdfs': 'merge',
|
||||
'/merge-pdfs': 'mergePdfs',
|
||||
'/compress-pdf': 'compress',
|
||||
'/convert': 'convert',
|
||||
'/convert-pdf': 'convert',
|
||||
@ -19,15 +19,15 @@ export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
|
||||
'/pdf-to-word': 'convert',
|
||||
'/pdf-to-xml': 'convert',
|
||||
'/add-password': 'addPassword',
|
||||
'/change-permissions': 'changePermissions',
|
||||
'/change-permissions': 'change-permissions',
|
||||
'/sanitize-pdf': 'sanitize',
|
||||
'/ocr': 'ocr',
|
||||
'/ocr-pdf': 'ocr',
|
||||
'/add-watermark': 'addWatermark',
|
||||
'/remove-password': 'removePassword',
|
||||
'/remove-password': 'remove-password',
|
||||
'/single-large-page': 'single-large-page',
|
||||
'/repair': 'repair',
|
||||
'/unlock-pdf-forms': 'unlockPdfForms',
|
||||
'/remove-certificate-sign': 'removeCertificateSign',
|
||||
'/remove-cert-sign': 'removeCertificateSign'
|
||||
'/unlock-pdf-forms': 'unlock-pdf-forms',
|
||||
'/remove-certificate-sign': 'remove-certificate-sign',
|
||||
'/remove-cert-sign': 'remove-certificate-sign'
|
||||
};
|
@ -2,12 +2,10 @@
|
||||
* URL routing utilities for tool navigation with registry support
|
||||
*/
|
||||
|
||||
import {
|
||||
ToolId,
|
||||
ToolRoute,
|
||||
getDefaultWorkbench
|
||||
} from '../types/navigation';
|
||||
import { ToolRegistry, getToolWorkbench, getToolUrlPath, isValidToolId } from '../data/toolsTaxonomy';
|
||||
import { ToolRoute } from '../types/navigation';
|
||||
import { ToolId, isValidToolId } from '../types/toolId';
|
||||
import { getDefaultWorkbench } from '../types/workbench';
|
||||
import { ToolRegistry, getToolWorkbench, getToolUrlPath } from '../data/toolsTaxonomy';
|
||||
import { firePixel } from './scarfTracking';
|
||||
import { URL_TO_TOOL_MAP } from './urlMapping';
|
||||
|
||||
@ -31,7 +29,7 @@ export function parseToolRoute(registry: ToolRegistry): ToolRoute {
|
||||
// Fallback: Try to find tool by primary URL path in registry
|
||||
for (const [toolId, tool] of Object.entries(registry)) {
|
||||
const toolUrlPath = getToolUrlPath(toolId, tool);
|
||||
if (path === toolUrlPath) {
|
||||
if (path === toolUrlPath && isValidToolId(toolId)) {
|
||||
return {
|
||||
workbench: getToolWorkbench(tool),
|
||||
toolId
|
||||
@ -41,7 +39,7 @@ export function parseToolRoute(registry: ToolRegistry): ToolRoute {
|
||||
|
||||
// Check for query parameter fallback (e.g., ?tool=split)
|
||||
const toolParam = searchParams.get('tool');
|
||||
if (toolParam && isValidToolId(toolParam, registry)) {
|
||||
if (toolParam && isValidToolId(toolParam) && registry[toolParam]) {
|
||||
const tool = registry[toolParam];
|
||||
return {
|
||||
workbench: getToolWorkbench(tool),
|
||||
|
Loading…
x
Reference in New Issue
Block a user