### Initialize and Setup Project Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/02-setup-and-workflow.md Commands to clone the repository and install dependencies using npm ci. This ensures a clean installation based on the lockfile. ```bash git clone git@github.com:AllenInstitute/biofile-finder.git cd biofile-finder npm ci ``` -------------------------------- ### Manage Subpackage Dependencies Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/02-setup-and-workflow.md Examples of adding dependencies to specific workspaces or the root project. Using the --workspace flag targets individual subpackages. ```bash npm install --save --workspace packages/desktop lolcatjs npm install --save lolcatjs ``` -------------------------------- ### Redux Module Index File Example (TypeScript) Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/core/state/README.md Shows how to bundle actions, reducers, selectors, and logic for a specific state branch in TypeScript. This follows the Ducks modular pattern for Redux. ```typescript import * as actions from "./actions"; import * as logics from "./logics"; import reducer from "./reducer"; import * as selectors from "./selectors"; export default { actions, logics, reducer, selectors, }; ``` -------------------------------- ### Get Manifest File Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Retrieves a manifest file for a given selection of files and desired format. ```APIDOC ## POST /files/manifest ### Description Retrieves a manifest file that lists the selected files and their associated metadata. The manifest can be generated in CSV, JSON, or Parquet format. ### Method POST ### Endpoint /files/manifest ### Request Body - **annotations** (array of strings) - Required - Specifies which annotations (columns) to include in the manifest file. - **selections** (array of objects) - Required - Defines the specific files and criteria for the manifest. Each object should conform to the `Selection` structure. - **format** (string) - Required - The desired output format for the manifest file. Must be one of: "csv", "json", "parquet". ### Request Example ```json { "annotations": ["File ID", "Creation Date"], "selections": [ { "filters": { "Gene": ["LMNB1"] } } ], "format": "json" } ``` ### Response #### Success Response (200) - **file** (object) - Represents the manifest file, containing its content and metadata. #### Response Example ```json { "file": { "name": "manifest.json", "content": "{\"fileId\": \"file-abc\", \"creationDate\": \"2023-01-01T10:00:00Z\"}", "format": "json" } } ``` ``` -------------------------------- ### Get Files Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Retrieves a paginated list of files based on specified criteria. ```APIDOC ## GET /files ### Description Retrieves a paginated list of files matching the provided `fileSet` criteria. Supports offset-based pagination. ### Method GET ### Endpoint /files ### Query Parameters - **from** (integer) - Optional - The offset for pagination (e.g., 0 for the first page). - **limit** (integer) - Optional - The maximum number of files to return per page. - **fileSet** (object) - Required - Defines the filters, index ranges, sorting, and other criteria for selecting files. See `Selection` structure for details. ### Request Example ```json { "from": 0, "limit": 50, "fileSet": { "filters": { "Cell Line": ["AICS-10", "AICS-12"], "Gene": ["LMNB1"] }, "indexRanges": [ { "start": 0, "end": 49 }, { "start": 100, "end": 149 } ], "sort": { "annotationName": "File Name", "ascending": true }, "fuzzy": ["File Name"], "exclude": ["Thumbnail"], "include": ["Gene"] } } ``` ### Response #### Success Response (200) - **files** (array) - An array of file detail objects. - **FileDetail** (object) - Contains details for each file, including metadata and properties. #### Response Example ```json { "files": [ { "id": "file-123", "name": "example_file.csv", "size": 1024, "creationDate": "2023-01-01T10:00:00Z", "annotations": { "Cell Line": "AICS-10", "Gene": "LMNB1" } } ] } ``` ``` -------------------------------- ### Define CSS Custom Properties Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/core/styles/README.md Example of defining global CSS variables in a root stylesheet to be used across the application. ```css :root { --typeface: 'Raleway', sans-serif; --fontColor: rgb(102, 102, 102); } ``` -------------------------------- ### GET /state/selectors Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Retrieves various pieces of the application state using the selection selectors module. ```APIDOC ## GET /state/selectors ### Description Provides access to the current application state including filters, sorting, and file selection data. ### Method GET ### Endpoint @biofile-finder/core/state/selection ### Parameters #### Path Parameters - **state** (object) - Required - The current Redux store state. ### Request Example const state = store.getState(); ### Response #### Success Response (200) - **getFileFilters** (FileFilter[]) - Returns active file filters. - **getSortColumn** (FileSort | undefined) - Returns the current sort configuration. - **getFileSelection** (FileSelection) - Returns the currently selected files. - **getColumns** (Column[]) - Returns display column configuration. - **getAnnotationHierarchy** (string[]) - Returns the annotation structure. - **getDataSources** (Source[]) - Returns configured data sources. - **getQueries** (Query[]) - Returns saved user queries. ``` -------------------------------- ### Redux Action Creator Example (TypeScript) Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/core/state/README.md Demonstrates how to create an action object with a type and payload using TypeScript. This function is used to dispatch data updates to the Redux store. ```typescript import { RECEIVE_DATA } from "./constants"; interface Datum { id: number; value: number; } interface Action { type: string; payload: Datum[]; } function receiveListOfData(data: Datum[]): Action { return { type: RECEIVE_DATA, payload: data, }; } ``` -------------------------------- ### Get Count of Matching Files Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Retrieves the total count of files that match a given `FileSet`. ```APIDOC ## GET /files/count ### Description Returns the total number of files that satisfy the criteria defined in the `fileSet`. ### Method GET ### Endpoint /files/count ### Query Parameters - **fileSet** (object) - Required - Defines the filters, index ranges, sorting, and other criteria for selecting files. See `Selection` structure for details. ### Request Example ```json { "fileSet": { "filters": { "Cell Line": ["AICS-10", "AICS-12"] } } } ``` ### Response #### Success Response (200) - **count** (integer) - The total number of files matching the `fileSet`. #### Response Example ```json { "count": 500 } ``` ``` -------------------------------- ### Create and Use FileDetail Objects in TypeScript Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Illustrates how to create a FileDetail object from raw file data, access its core properties, check if a file is local or remote, retrieve annotation values, get thumbnail paths, and map link-type annotations. ```typescript import FileDetail, { FmsFile } from "@biofile-finder/core/entity/FileDetail"; import { Environment } from "@biofile-finder/core/constants"; // Create a FileDetail from raw file data const fmsFile: FmsFile = { file_id: "26aa7881b8004dd0bcec857baf9a2f0a", file_name: "experiment_001.ome.zarr", file_path: "production.files.allencell.org/path/to/file.zarr", file_size: 1048576, uploaded: "2024-01-15 13:50:24", thumbnail: "/allen/programs/allencell/data/thumbnails/thumb.png", annotations: [ { name: "Cell Line", values: ["AICS-10", "AICS-12"] }, { name: "Gene", values: ["LMNB1"] }, { name: "Is Quality Controlled", values: [true] } ] }; const fileDetail = new FileDetail(fmsFile, Environment.PRODUCTION); // Access core file properties console.log(fileDetail.id); // "26aa7881b8004dd0bcec857baf9a2f0a" console.log(fileDetail.name); // "experiment_001.ome.zarr" console.log(fileDetail.path); // "https://s3.us-west-2.amazonaws.com/production.files.allencell.org/path/to/file.zarr" console.log(fileDetail.size); // 1048576 console.log(fileDetail.uid); // Unique identifier for the file row // Check if file is local or remote console.log(fileDetail.isLikelyLocalFile); // false (starts with http/s3) // Get annotation values const cellLine = fileDetail.getFirstAnnotationValue("Cell Line"); // Returns: "AICS-10" const geneAnnotation = fileDetail.getAnnotation("Gene"); // Returns: { name: "Gene", values: ["LMNB1"] } // Get thumbnail path (handles zarr rendering, local paths, S3 URLs) const thumbnailUrl = await fileDetail.getPathToThumbnail(256); // Returns rendered thumbnail URL or path // Get all link-type annotations (URLs) const links = fileDetail.getAnnotationNameToLinkMap(); // Returns: { "External Link": "https://example.com/data" } ``` -------------------------------- ### Get Aggregate Information Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Calculates and returns aggregate information (count and total size) for a specified file selection. ```APIDOC ## POST /files/aggregate ### Description Calculates and returns the total count and optionally the total size of files within a given `fileSelection`. ### Method POST ### Endpoint /files/aggregate ### Request Body - **fileSelection** (object) - Required - Defines the set of files for which to calculate aggregate information. See `Selection` structure for details. ### Request Example ```json { "fileSelection": { "filters": { "Gene": ["LMNB1"] } } } ``` ### Response #### Success Response (200) - **count** (integer) - The total number of files in the selection. - **size** (integer) - Optional - The total size in bytes of the files in the selection. #### Response Example ```json { "count": 150, "size": 1073741824 } ``` ``` -------------------------------- ### Initialize and Use DuckDB with DatabaseService Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Demonstrates how to initialize DuckDB, create a DatabaseService instance, prepare data sources (CSV, Parquet), execute raw SQL, perform queries, save results, and manage annotations. It covers initializing the database, adding data, checking existence, executing commands, fetching data, saving query outputs, retrieving column metadata, and preparing source metadata. ```typescript import DatabaseService, { initializeDuckDB } from "@biofile-finder/core/services/DatabaseService"; import * as duckdb from "@duckdb/duckdb-wasm"; // Initialize DuckDB (call once at application start) const db = await initializeDuckDB(duckdb.LogLevel.WARNING); // In a concrete implementation (e.g., DatabaseServiceWeb) class MyDatabaseService extends DatabaseService { async initialize() { this.database = await initializeDuckDB(duckdb.LogLevel.WARNING); } } const databaseService = new MyDatabaseService(); await databaseService.initialize(); // Prepare data sources (CSV, JSON, or Parquet) await databaseService.prepareDataSources([ { name: "experiment_data", type: "csv", uri: "https://example.com/data.csv", }, { name: "metadata", type: "parquet", uri: new File(["..."], "data.parquet"), }, ]); // Check if a data source exists const exists = databaseService.hasDataSource("experiment_data"); // Execute raw SQL (no return value) await databaseService.execute('ALTER TABLE "experiment_data" ADD COLUMN "new_col" VARCHAR'); // Query with results const result = databaseService.query('SELECT * FROM "experiment_data" LIMIT 10'); const rows = await result.promise; // Returns: [{ "File Name": "file1.tiff", "Cell Line": "AICS-10" }, ...] // Save query results to file const buffer = await databaseService.saveQuery( "export", 'SELECT * FROM "experiment_data"', "parquet" // or "csv" or "json" ); // Returns: Uint8Array of file contents // Fetch annotations (column metadata) const annotations = await databaseService.fetchAnnotations(["experiment_data"]); // Returns: Annotation[] with column names, types, descriptions // Fetch annotation types from metadata table const types = await databaseService.fetchAnnotationTypes(); // Returns: { "Cell Line": "STRING", "File Size": "NUMBER" } // Prepare source metadata (descriptions for annotations) await databaseService.prepareSourceMetadata({ name: "metadata_definitions", type: "csv", uri: "https://example.com/metadata.csv", }); // Process provenance data for file relationships const edges = await databaseService.processProvenance({ name: "provenance", type: "csv", uri: provenanceFile, }); // Returns: EdgeDefinition[] for graph visualization // Add a new column to a data source await databaseService.addNewColumn( "experiment_data", "Custom Annotation", "Description of the annotation" ); // Close the database connection databaseService.close(); ``` -------------------------------- ### Initializing Desktop Application (Electron) Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Configures the Redux store with Electron-specific services, sets up state persistence, and renders the React application within an Electron environment. ```typescript import { render } from "react-dom"; import { Provider } from "react-redux"; import FmsFileExplorer from "@biofile-finder/core/App"; import { createReduxStore } from "@biofile-finder/core/state"; import DatabaseServiceElectron from "./services/DatabaseServiceElectron"; const databaseService = new DatabaseServiceElectron(); await databaseService.initialize(); const store = createReduxStore({ middleware: [analyticsMiddleware], persistedConfig: persistentConfigService.getAll(), platformDependentServices: { databaseService, fileDownloadService: new FileDownloadServiceElectron(s3StorageService), fileViewerService: new FileViewerServiceElectron(notificationService), executionEnvService: new ExecutionEnvServiceElectron(notificationService), applicationInfoService: new ApplicationInfoServiceElectron(), notificationService, }, }); store.subscribe(() => { const state = store.getState(); persistentConfigService.persist({ columns: selection.selectors.getColumns(state), queries: selection.selectors.getQueries(state), }); }); render( , document.getElementById("fms-file-explorer") ); ``` -------------------------------- ### Initializing Web Application Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Configures the Redux store with web-specific services and sets up React Router for navigation within a browser-based environment. ```typescript import { render } from "react-dom"; import { Provider } from "react-redux"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import FmsFileExplorer from "@biofile-finder/core/App"; import { createReduxStore } from "@biofile-finder/core/state"; import DatabaseServiceWeb from "./services/DatabaseServiceWeb"; const databaseService = new DatabaseServiceWeb(); await databaseService.initialize(); const store = createReduxStore({ isOnWeb: true, platformDependentServices: { databaseService, notificationService: new NotificationServiceWeb(), executionEnvService: new ExecutionEnvServiceWeb(), applicationInfoService: new ApplicationInfoServiceWeb(), fileViewerService: new FileViewerServiceWeb(), fileDownloadService: new FileDownloadServiceWeb(new S3StorageService()), }, }); const router = createBrowserRouter([ { element: , children: [ { path: "/", element: }, { path: "app", element: }, { path: "datasets", element: }, { path: "learn", element: }, ], }, ]); render( , document.getElementById("biofile-finder") ); ``` -------------------------------- ### Prepare Local Environment for Desktop Release Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/04-versioning-and-deployment.md Ensures the local repository is synchronized with the main branch before initiating a release process. This prevents conflicts by cleaning the workspace. ```bash git checkout main git stash git pull ``` -------------------------------- ### Identify Runner Environments for Manual Builds Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/04-versioning-and-deployment.md Lists the required runner environment strings for triggering manual desktop builds via GitHub Actions for specific operating systems. ```text ubuntu-latest for Linux builds windows-latest for Windows builds macOS-latest for ARM builds macOS-13 for x86 builds ``` -------------------------------- ### Configure file sorting with FileSort Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Shows how to create sort configurations, convert them to query strings or SQL clauses, and serialize them to JSON. ```typescript import FileSort, { SortOrder } from "@biofile-finder/core/entity/FileSort"; import SQLBuilder from "@biofile-finder/core/entity/SQLBuilder"; const ascSort = new FileSort("File Name", SortOrder.ASC); const descSort = new FileSort("uploaded", SortOrder.DESC); console.log(ascSort.toQueryString()); const sqlBuilder = ascSort.toQuerySQLBuilder(); const sql = sqlBuilder.select("*").from("files").toSQL(); const json = ascSort.toJSON(); console.log(ascSort.equals(descSort)); ``` -------------------------------- ### Compose and Apply CSS Classes Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/core/styles/README.md Demonstrates how to use the 'composes' keyword to inherit styles from shared files and apply local variables. ```css .container { composes: flexParent from "relative/path/to/styles/layout.css"; } .button { color: var(--fontColor); } ``` -------------------------------- ### Manage file selections with FileSelection Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Demonstrates how to initialize, modify, and query file selections. It covers single and range selections, focus navigation, and metadata retrieval. ```typescript import FileSelection, { FocusDirective } from "@biofile-finder/core/entity/FileSelection"; import FileSet from "@biofile-finder/core/entity/FileSet"; import NumericRange from "@biofile-finder/core/entity/NumericRange"; let selection = new FileSelection(); selection = selection.select({ fileSet: myFileSet, index: 5, sortOrder: 0 }); selection = selection.select({ fileSet: myFileSet, index: new NumericRange(10, 20), sortOrder: 0, indexToFocus: 15 }); const isSelected = selection.isSelected(myFileSet, 15); const isFocused = selection.isFocused(myFileSet, 15); const count = selection.count(); selection = selection.focus(FocusDirective.NEXT); const focusedFile = await selection.fetchFocusedItemDetails(); const grouped = selection.groupByFileSet(); ``` -------------------------------- ### Create Redux Store for State Management in TypeScript Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Illustrates how to create a Redux store for the Biofile Finder application using the `createReduxStore` function. It configures the store with platform-specific services, middleware, and persisted configuration, and shows how to access the application state. ```typescript import { createReduxStore, State } from "@biofile-finder/core/state"; import { PlatformDependentServices } from "@biofile-finder/core/services"; // Create store with platform-specific services const store = createReduxStore({ isOnWeb: true, // false for desktop middleware: [customMiddleware], persistedConfig: { columns: [{ name: "File Name", width: 0.3 }], queries: [], hasUsedApplicationBefore: true, }, platformDependentServices: { databaseService, fileDownloadService, fileViewerService, notificationService, executionEnvService, applicationInfoService, }, }); // Access state const state: State = store.getState(); // state.interaction - UI state (modals, context menus, downloads) // state.metadata - Cached annotations and data // state.selection - Current filters, sort, selections ``` -------------------------------- ### FileFilter Class: Create and Use Filters (TypeScript) Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Demonstrates the creation and usage of the FileFilter class for defining various filter types such as default equality, fuzzy matching, exclusion, and inclusion. It also shows how to convert these filters into URL query strings and SQL WHERE clauses, compare filters, and serialize them to JSON. ```typescript import FileFilter, { FilterType } from "@biofile-finder/core/entity/FileFilter"; // Create a standard equality filter const cellLineFilter = new FileFilter("Cell Line", "AICS-10"); console.log(cellLineFilter.name); // "Cell Line" console.log(cellLineFilter.value); // "AICS-10" console.log(cellLineFilter.type); // FilterType.DEFAULT // Create a fuzzy (partial match) filter const fuzzyFilter = new FileFilter("File Name", "experiment", FilterType.FUZZY); // Create an exclude filter (files missing this annotation) const excludeFilter = new FileFilter("Gene", null, FilterType.EXCLUDE); // Create an include/any filter (files having any value for annotation) const includeFilter = new FileFilter("Gene", null, FilterType.ANY); // Convert filter to URL query string console.log(cellLineFilter.toQueryString()); // Returns: "Cell Line=AICS-10" console.log(fuzzyFilter.toQueryString()); // Returns: "File Name=experiment&fuzzy=File Name" console.log(excludeFilter.toQueryString()); // Returns: "exclude=Gene" console.log(includeFilter.toQueryString()); // Returns: "include=Gene" // Convert filter to SQL WHERE clause console.log(cellLineFilter.toSQLWhereString()); // Returns: REGEXP_MATCHES(CAST("Cell Line" AS VARCHAR), '...') console.log(excludeFilter.toSQLWhereString()); // Returns: "Gene" IS NULL // Compare filters const sameFilter = new FileFilter("Cell Line", "AICS-10"); console.log(cellLineFilter.equals(sameFilter)); // true // Serialize to JSON const json = cellLineFilter.toJSON(); // Returns: { name: "Cell Line", value: "AICS-10", type: "default" } ``` -------------------------------- ### Create and Use Annotation Objects in TypeScript Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Demonstrates how to create an Annotation object from API response, access its properties, extract values from files, and format them for display. It also shows how to sort annotations. ```typescript import Annotation, { AnnotationResponse } from "@biofile-finder/core/entity/Annotation"; import { AnnotationType } from "@biofile-finder/core/entity/AnnotationFormatter"; // Create an annotation from API response const annotationResponse: AnnotationResponse = { annotationId: 1, annotationDisplayName: "Cell Line", annotationName: "cell_line", description: "The cell line used in the experiment", type: AnnotationType.STRING, units: undefined, }; const cellLineAnnotation = new Annotation(annotationResponse); // Access annotation properties console.log(cellLineAnnotation.name); // "cell_line" console.log(cellLineAnnotation.displayName); // "Cell Line" console.log(cellLineAnnotation.description); // "The cell line used in the experiment" console.log(cellLineAnnotation.type); // "STRING" console.log(cellLineAnnotation.isImmutable); // false // Extract annotation value from a file const displayValue = cellLineAnnotation.extractFromFile(fileDetail); // Returns: "AICS-10, AICS-12" (comma-separated if multiple values) // Format a value for display const formatted = cellLineAnnotation.getDisplayValue("AICS-10"); // Returns: "AICS-10" // Sort annotations alphabetically with special handling const sortedAnnotations = Annotation.sort([annotation1, annotation2, annotation3]); // File Name annotation is prioritized to appear first ``` -------------------------------- ### Download Files Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Initiates the download of selected files in a specified format. ```APIDOC ## POST /files/download ### Description Initiates a file download for a specified selection of files. The files can be returned in CSV, JSON, or Parquet format. ### Method POST ### Endpoint /files/download ### Request Body - **annotations** (array of strings) - Required - Specifies which annotations (columns) to include in the downloaded files. - **selections** (array of objects) - Required - Defines the specific files and criteria for download. Each object should conform to the `Selection` structure. - **format** (string) - Required - The desired output format for the downloaded files. Must be one of: "csv", "json", "parquet". ### Request Example ```json { "annotations": ["File Name", "Gene"], "selections": [ { "filters": { "Cell Line": ["AICS-10"] } } ], "format": "csv" } ``` ### Response #### Success Response (200) - **resolution** (string) - Indicates the status of the download request. Expected value: "SUCCESS". #### Response Example ```json { "resolution": "SUCCESS" } ``` ``` -------------------------------- ### Execute Desktop Version Bump Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/04-versioning-and-deployment.md Uses npm to increment the version of the desktop package and create a git tag. This command skips commit hooks for speed and applies the version change to the workspace. ```bash npm --no-commit-hooks version --workspace packages/desktop $VERSION_BUMP_TYPE -m "v%s" ``` -------------------------------- ### FileSet Class: Manage File Collections and Metadata (TypeScript) Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Illustrates the functionality of the FileSet class for creating and managing collections of files based on filters and sort order. It covers lazy loading of metadata with caching and pagination, fetching total counts, retrieving specific file details, and converting the FileSet configuration into query strings and SQL query builders. ```typescript import FileSet from "@biofile-finder/core/entity/FileSet"; import FileFilter from "@biofile-finder/core/entity/FileFilter"; import FileSort, { SortOrder } from "@biofile-finder/core/entity/FileSort"; import FileService from "@biofile-finder/core/services/FileService"; // Create a FileSet with filters and sorting const fileSet = new FileSet({ fileService: myFileService, filters: [ new FileFilter("Cell Line", "AICS-10"), new FileFilter("Gene", "LMNB1"), ], sort: new FileSort("File Name", SortOrder.ASC), maxCacheSize: 1000, // LRU cache size }); // Get total count of matching files const totalCount = await fileSet.fetchTotalCount(); console.log(`Found ${totalCount} matching files`); // Fetch a range of file metadata (lazy loading with pagination) const files = await fileSet.fetchFileRange(0, 49); // Returns: FileDetail[] for indices 0-49 // Check if metadata is already loaded for an index const isLoaded = fileSet.isFileMetadataLoaded(25); // Get cached file by index const cachedFile = fileSet.getFileByIndex(25); // Check if FileSet matches certain filters const hasFilters = fileSet.matches([ new FileFilter("Cell Line", "AICS-10") ]); // Returns: true // Convert to query string for API requests const queryString = fileSet.toQueryString(); // Returns: "Cell Line=AICS-10&Gene=LMNB1&sort=File Name(ASC)" // Convert to SQL query builder const sqlBuilder = fileSet.toQuerySQLBuilder(); const sql = sqlBuilder.select("*").from("my_table").toSQL(); // Compare FileSets const otherFileSet = new FileSet({ /* same config */ }); console.log(fileSet.equals(otherFileSet)); // true // Unique instance ID for React key usage console.log(fileSet.instanceId); // "FileSet123" // Hash for caching purposes console.log(fileSet.hash); // "Cell Line=AICS-10&Gene=LMNB1&sort=...:baseUrl" ``` -------------------------------- ### DatabaseService Operations Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Methods for initializing the database, managing data sources, executing queries, and handling metadata. ```APIDOC ## POST /database/initialize ### Description Initializes the DuckDB instance for the application. ### Method POST ### Endpoint /database/initialize ### Parameters #### Request Body - **logLevel** (string) - Optional - The logging level for DuckDB (e.g., WARNING, INFO). ### Response #### Success Response (200) - **db** (Object) - The initialized database instance. --- ## POST /database/data-sources ### Description Registers new data sources (CSV, JSON, or Parquet) for querying. ### Method POST ### Endpoint /database/data-sources ### Parameters #### Request Body - **sources** (Array) - Required - List of objects containing name, type, and uri. --- ## POST /database/query ### Description Executes a SQL query against the loaded data sources. ### Method POST ### Endpoint /database/query ### Parameters #### Request Body - **sql** (string) - Required - The SQL query to execute. ### Response #### Success Response (200) - **rows** (Array) - The result set of the query. --- ## GET /database/annotations ### Description Fetches column metadata and annotations for specified data sources. ### Method GET ### Endpoint /database/annotations ### Parameters #### Query Parameters - **sources** (Array) - Required - List of data source names to fetch annotations for. ``` -------------------------------- ### Refresh Workspace Environment Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/02-setup-and-workflow.md Commands to synchronize the local repository with the remote and clean untracked files. This is recommended for periodic maintenance. ```bash git pull git clean -Xfd npm ci ``` -------------------------------- ### Manage UI Interactions and File Operations with TypeScript Source: https://context7.com/alleninstitute/biofile-finder/llms.txt This snippet illustrates how to manage various UI interactions and file operations within the Biofile Finder application. It covers initializing the app, controlling modal visibility, displaying context menus, initiating and managing file downloads, opening files with external applications, editing and deleting file metadata, handling status notifications, refreshing data, prompting for data sources, and performing graph/provenance operations. Dependencies include core state and component modules. ```typescript import { interaction } from "@biofile-finder/core/state"; import { ModalType } from "@biofile-finder/core/components/Modal"; const { actions } = interaction; // Initialize application store.dispatch(actions.initializeApp({ environment: "PRODUCTION" })); // Show/hide modals store.dispatch(actions.setVisibleModal(ModalType.MetadataManifest)); store.dispatch(actions.hideVisibleModal()); // Show context menu store.dispatch(actions.showContextMenu( [ { label: "Open", onClick: () => {} }, { label: "Download", onClick: () => {} }, ], { x: 100, y: 200 }, // Position () => console.log("Menu dismissed") )); store.dispatch(actions.hideContextMenu()); // Download operations store.dispatch(actions.downloadFiles([fileInfo1, fileInfo2])); store.dispatch(actions.downloadManifest(["File Name", "Cell Line"], "csv")); store.dispatch(actions.cancelFileDownload(processId)); // Open files with applications store.dispatch(actions.openWithDefault(filters, files)); store.dispatch(actions.openWith(selectedApp, filters, files)); // Edit file metadata store.dispatch(actions.editFiles( { "Cell Line": ["AICS-10"], "Gene": ["LMNB1"] }, filters, "username" )); // Delete metadata from files store.dispatch(actions.deleteMetadata("Custom Annotation", "username")); // Status/progress notifications store.dispatch(actions.processStart(processId, "Downloading files...")); store.dispatch(actions.processProgress(processId, 0.5, "50% complete", cancelFn)); store.dispatch(actions.processSuccess(processId, "Download complete")); store.dispatch(actions.processError(processId, "Download failed")); store.dispatch(actions.removeStatus(processId)); // Refresh data store.dispatch(actions.refresh()); // Prompt for data source store.dispatch(actions.promptForDataSource({ sourceType: DataSourceType.FILE, })); // Graph/provenance operations store.dispatch(actions.setOriginForProvenance(fileDetail)); store.dispatch(actions.expandGraph(fileDetail)); store.dispatch(actions.refreshGraph()); ``` -------------------------------- ### Manage File Selection and Filtering with TypeScript Source: https://context7.com/alleninstitute/biofile-finder/llms.txt This snippet demonstrates how to manage file selection, filtering, and sorting using the Biofile Finder's state management system. It covers adding, removing, and changing filters, setting sort orders, selecting individual files or ranges, and configuring display columns and annotation hierarchies. Dependencies include core state, entity, and component modules. ```typescript import { selection } from "@biofile-finder/core/state"; import FileFilter, { FilterType } from "@biofile-finder/core/entity/FileFilter"; import FileSort, { SortOrder } from "@biofile-finder/core/entity/FileSort"; import FileSet from "@biofile-finder/core/entity/FileSet"; import NumericRange from "@biofile-finder/core/entity/NumericRange"; const { actions } = selection; // Add a file filter store.dispatch(actions.addFileFilter( new FileFilter("Cell Line", "AICS-10") )); // Add multiple filters store.dispatch(actions.addFileFilter([ new FileFilter("Cell Line", "AICS-10"), new FileFilter("Gene", "LMNB1"), ])); // Remove a filter store.dispatch(actions.removeFileFilter( new FileFilter("Cell Line", "AICS-10") )); // Change filter type store.dispatch(actions.changeFileFilterType("Gene", FilterType.FUZZY)); // Set sort column (toggles ASC/DESC on same column) store.dispatch(actions.sortColumn("File Name")); // Set specific sort store.dispatch(actions.setSortColumn( new FileSort("File Name", SortOrder.DESC) )); // Select a file store.dispatch(actions.selectFile({ fileSet: myFileSet, index: 5, sortOrder: 0, updateExistingSelection: false, // Replace selection })); // Select range of files (shift-click behavior) store.dispatch(actions.selectFile({ fileSet: myFileSet, index: new NumericRange(10, 20), sortOrder: 0, updateExistingSelection: true, // Add to selection })); // Select nearby file (arrow key navigation) store.dispatch(actions.selectNearbyFile("down", false)); store.dispatch(actions.selectNearbyFile("up", true)); // Extend selection // Set display columns store.dispatch(actions.setColumns([ { name: "File Name", width: 0.3 }, { name: "Cell Line", width: 0.2 }, { name: "File Size", width: 0.15 }, ])); // Resize a column store.dispatch(actions.resizeColumn({ name: "File Name", width: 0.4 })); // Set annotation hierarchy for grouping store.dispatch(actions.setAnnotationHierarchy(["Cell Line", "Gene", "Plate"])); // Reorder hierarchy store.dispatch(actions.reorderAnnotationHierarchy("Gene", 0)); // Move to first // Change data sources store.dispatch(actions.changeDataSources([ { name: "experiment_1", type: "csv", uri: "https://..." }, { name: "experiment_2", type: "parquet", uri: file }, ])); // Add a saved query store.dispatch(actions.addQuery({ name: "My Saved View", parts: { filters: [new FileFilter("Cell Line", "AICS-10")], sortColumn: new FileSort("File Name", SortOrder.ASC), hierarchy: ["Cell Line"], }, })); // Switch to a saved query store.dispatch(actions.changeQuery(savedQuery)); ``` -------------------------------- ### Accessing Selection State Selectors Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Demonstrates how to import and utilize selection selectors to retrieve various pieces of application state, such as filters, sorting, columns, and query information from the Redux store. ```typescript import { selection } from "@biofile-finder/core/state"; const { selectors } = selection; const state = store.getState(); const filters = selectors.getFileFilters(state); const sort = selectors.getSortColumn(state); const fileSelection = selectors.getFileSelection(state); const columns = selectors.getColumns(state); const hierarchy = selectors.getAnnotationHierarchy(state); const dataSources = selectors.getDataSources(state); const queries = selectors.getQueries(state); const currentQuery = selectors.getCurrentQuery(state); const smallFont = selectors.getShouldDisplaySmallFont(state); ``` -------------------------------- ### Implement AnnotationService Interface in TypeScript Source: https://context7.com/alleninstitute/biofile-finder/llms.txt Demonstrates an implementation of the AnnotationService interface, providing methods to fetch, validate, and create annotations. It includes functions for retrieving annotation values, details, and hierarchical data, along with validation and creation capabilities. ```typescript import AnnotationService, { AnnotationValue, AnnotationDetails } from "@biofile-finder/core/services/AnnotationService"; import { AnnotationType } from "@biofile-finder/core/entity/AnnotationFormatter"; // AnnotationService interface implementation class MyAnnotationService implements AnnotationService { // Fetch all available annotations async fetchAnnotations(): Promise { return [ new Annotation({ annotationName: "Cell Line", annotationDisplayName: "Cell Line", description: "The cell line used", type: AnnotationType.STRING, }), // ... more annotations ]; } // Fetch all values for a specific annotation async fetchValues(annotation: string): Promise { // Returns: ["AICS-10", "AICS-12", "AICS-13", ...] return values; } // Get detailed information about an annotation async fetchAnnotationDetails(name: string): Promise { return { type: AnnotationType.STRING, dropdownOptions: ["AICS-10", "AICS-12", "AICS-13"], }; } // Fetch root values for hierarchical grouping async fetchRootHierarchyValues( hierarchy: string[], // Annotation names in hierarchy filters: FileFilter[] // Current filters ): Promise { // Returns unique values for first annotation in hierarchy return rootValues; } // Fetch child values under a hierarchy path async fetchHierarchyValuesUnderPath( hierarchy: string[], path: string[], // Current path in hierarchy filters: FileFilter[] ): Promise { // Returns values for next level given current path return childValues; } // Get annotations available for hierarchy given current selection async fetchAvailableAnnotationsForHierarchy( annotations: string[] ): Promise { return availableAnnotations; } // Validate values for an annotation async validateAnnotationValues( name: string, values: AnnotationValue[] ): Promise { return isValid; } // Create a new annotation async createAnnotation( annotation: Annotation, annotationOptions?: string[], user?: string ): Promise { // Create annotation in backend } } ``` -------------------------------- ### Import and Apply CSS Modules in React Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/core/styles/README.md Shows how to import a CSS module into a React component and apply the generated class names to elements. ```typescript import * as React from "react"; import styles from "./style.css"; const button = (props) => { return (
); } ``` -------------------------------- ### Implement FileService for File Operations Source: https://context7.com/alleninstitute/biofile-finder/llms.txt This TypeScript class implements the FileService interface, providing concrete methods for file operations such as fetching paginated lists of files, counting matching files, retrieving aggregate information, downloading files in various formats, and editing file annotations. It utilizes an API base URL for service communication. ```typescript import FileService, { GetFilesRequest, Selection } from "@biofile-finder/core/services/FileService"; // FileService interface implementation class MyFileService implements FileService { fileExplorerServiceBaseUrl = "https://api.example.com"; // Get paginated list of files async getFiles(request: GetFilesRequest): Promise { const { from, limit, fileSet } = request; // Fetch files matching fileSet filters with pagination // from = page offset, limit = page size return fetchedFiles; } // Get count of files matching a FileSet async getCountOfMatchingFiles(fileSet: FileSet): Promise { return totalCount; } // Get aggregate info (count and total size) for a selection async getAggregateInformation(fileSelection: FileSelection): Promise<{ count: number; size?: number; }> { return { count: 150, size: 1073741824 }; } // Download files in specified format async download( annotations: string[], // Columns to include selections: Selection[], // File selections format: "csv" | "json" | "parquet" ): Promise { return { resolution: DownloadResolution.SUCCESS }; } // Get manifest file async getManifest( annotations: string[], selections: Selection[], format: "csv" | "json" | "parquet" ): Promise { return manifestFile; } // Edit file annotations async editFile( fileId: string, annotations: { [name: string]: AnnotationValue[] }, annotationMap?: Record, user?: string ): Promise { // Update file metadata } } // Example Selection structure for API calls const selection: Selection = { filters: { "Cell Line": ["AICS-10", "AICS-12"], "Gene": ["LMNB1"], }, indexRanges: [ { start: 0, end: 49 }, { start: 100, end: 149 }, ], sort: { annotationName: "File Name", ascending: true, }, fuzzy: ["File Name"], // Columns with fuzzy matching exclude: ["Thumbnail"], // Columns to exclude nulls include: ["Gene"], // Columns requiring any value }; ``` -------------------------------- ### Initialize Google Tag Manager Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/web/webpack/index.html This JavaScript snippet initializes the Google Tag Manager container. It creates a data layer and injects the GTM script tag into the document head to enable tracking. ```javascript (function (w, d, s, l, i) { w[l] = w[l] || []; w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); })(window, document, 'script', 'dataLayer', 'GTM-KCCN6L4X'); ``` -------------------------------- ### SQLBuilder Class: Fluent SQL Query Construction for DuckDB Source: https://context7.com/alleninstitute/biofile-finder/llms.txt The SQLBuilder class offers a fluent interface for programmatically generating SQL queries, specifically tailored for use with DuckDB. It supports building SELECT, WHERE, ORDER BY, LIMIT, and OFFSET clauses, along with utility methods for regex matching and table description. ```typescript import SQLBuilder from "@biofile-finder/core/entity/SQLBuilder"; // Build a simple SELECT query const query = new SQLBuilder() .select("*") .from("files") .toSQL(); // Returns: SELECT * FROM "files" // Build a query with WHERE clauses const filteredQuery = new SQLBuilder() .select('"File Name", "File Path", "Cell Line"') .from("experiment_data") .where('"Cell Line" = \'AICS-10\'') .where('"Gene" IS NOT NULL') .toSQL(); // Returns: SELECT "File Name", "File Path", "Cell Line" // FROM "experiment_data" // WHERE ("Cell Line" = 'AICS-10') AND ("Gene" IS NOT NULL) // Build a query with ORDER BY, LIMIT, and OFFSET const paginatedQuery = new SQLBuilder() .select("*") .from("files") .orderBy('"File Name" ASC') .limit(50) .offset(100) .toSQL(); // Returns: SELECT * FROM "files" ORDER BY "File Name" ASC LIMIT 50 OFFSET 100 // Use regex matching for list values const regexClause = SQLBuilder.regexMatchValueInList("Cell Line", "AICS-10"); // Returns regex pattern that matches value at start, middle, end, or as only value // in a comma-separated list const regexQuery = new SQLBuilder() .select("*") .from("files") .where(regexClause) .toSQL(); // Describe a table structure const describeQuery = new SQLBuilder() .describe() .select("*") .from("files") .toSQL(); // Returns: DESCRIBE SELECT * FROM "files" // Remove ORDER BY clause const builderWithSort = new SQLBuilder() .select("*") .from("files") .orderBy('"File Name" ASC'); const builderWithoutSort = builderWithSort.removeOrderBy(); ``` -------------------------------- ### Configure Version Bump Type Source: https://github.com/alleninstitute/biofile-finder/blob/main/dev-docs/04-versioning-and-deployment.md Sets the environment variable required to determine the semantic versioning increment level. The user must specify either patch, minor, or major. ```bash export VERSION_BUMP_TYPE= ``` -------------------------------- ### Define Enums and Constants in TypeScript Source: https://github.com/alleninstitute/biofile-finder/blob/main/packages/core/constants/README.md Demonstrates the project standard for defining enums and global constant variables. Enums should use PascalCase, while constant variables should use UPPER_SNAKE_CASE. ```typescript export enum Color { Blue = "rgb(0,0,255)", Yellow = "rgb(255,255,0)" } export const BASE_API_URL = "/api/v1"; ``` -------------------------------- ### FileSort Class API Source: https://context7.com/alleninstitute/biofile-finder/llms.txt The FileSort class provides utilities for defining and converting sort orders for file sets into query strings or SQL clauses. ```APIDOC ## FileSort Class ### Description Represents a sort order applied to a file set, supporting both ascending and descending orders. ### Methods - **toQueryString()**: Converts the sort configuration into a URL-friendly query string. - **toQuerySQLBuilder()**: Generates a SQLBuilder instance for database queries. - **toJSON()**: Serializes the sort configuration into a JSON object. ### Request Example const ascSort = new FileSort("File Name", SortOrder.ASC); ### Response - **JSON Output** (Object) - { "annotationName": "File Name", "order": "ASC" } ```