UNPKG

hyperformula

Version:

HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas

115 lines 6.35 kB
/** * @license * Copyright (c) 2025 Handsoncode. All rights reserved. */ import { ArraySizePredictor } from "./ArraySize.mjs"; import { CellContentParser } from "./CellContentParser.mjs"; import { ClipboardOperations } from "./ClipboardOperations.mjs"; import { Config } from "./Config.mjs"; import { CrudOperations } from "./CrudOperations.mjs"; import { DateTimeHelper } from "./DateTimeHelper.mjs"; import { DependencyGraph } from "./DependencyGraph/index.mjs"; import { SheetSizeLimitExceededError } from "./errors.mjs"; import { Evaluator } from "./Evaluator.mjs"; import { Exporter } from "./Exporter.mjs"; import { GraphBuilder } from "./GraphBuilder.mjs"; import { UIElement } from "./i18n/index.mjs"; import { ArithmeticHelper } from "./interpreter/ArithmeticHelper.mjs"; import { FunctionRegistry } from "./interpreter/FunctionRegistry.mjs"; import { Interpreter } from "./interpreter/Interpreter.mjs"; import { LazilyTransformingAstService } from "./LazilyTransformingAstService.mjs"; import { buildColumnSearchStrategy } from "./Lookup/SearchStrategy.mjs"; import { NamedExpressions } from "./NamedExpressions.mjs"; import { NumberLiteralHelper } from "./NumberLiteralHelper.mjs"; import { Operations } from "./Operations.mjs"; import { ParserWithCaching, Unparser } from "./parser/index.mjs"; import { Serialization } from "./Serialization.mjs"; import { findBoundaries, validateAsSheet } from "./Sheet.mjs"; import { EmptyStatistics, Statistics, StatType } from "./statistics/index.mjs"; import { UndoRedo } from "./UndoRedo.mjs"; export class BuildEngineFactory { static buildFromSheets(sheets, configInput = {}, namedExpressions = []) { const config = new Config(configInput); return this.buildEngine(config, sheets, namedExpressions); } static buildFromSheet(sheet, configInput = {}, namedExpressions = []) { const config = new Config(configInput); const newsheetprefix = config.translationPackage.getUITranslation(UIElement.NEW_SHEET_PREFIX) + '1'; return this.buildEngine(config, { [newsheetprefix]: sheet }, namedExpressions); } static buildEmpty(configInput = {}, namedExpressions = []) { return this.buildEngine(new Config(configInput), {}, namedExpressions); } static rebuildWithConfig(config, sheets, namedExpressions, stats) { return this.buildEngine(config, sheets, namedExpressions, stats); } static buildEngine(config, sheets = {}, inputNamedExpressions = [], stats = config.useStats ? new Statistics() : new EmptyStatistics()) { stats.start(StatType.BUILD_ENGINE_TOTAL); const namedExpressions = new NamedExpressions(); const functionRegistry = new FunctionRegistry(config); const lazilyTransformingAstService = new LazilyTransformingAstService(stats); const dependencyGraph = DependencyGraph.buildEmpty(lazilyTransformingAstService, config, functionRegistry, namedExpressions, stats); const columnSearch = buildColumnSearchStrategy(dependencyGraph, config, stats); const sheetMapping = dependencyGraph.sheetMapping; const addressMapping = dependencyGraph.addressMapping; for (const sheetName in sheets) { if (Object.prototype.hasOwnProperty.call(sheets, sheetName)) { const sheet = sheets[sheetName]; validateAsSheet(sheet); const boundaries = findBoundaries(sheet); if (boundaries.height > config.maxRows || boundaries.width > config.maxColumns) { throw new SheetSizeLimitExceededError(); } const sheetId = sheetMapping.addSheet(sheetName); addressMapping.addSheetAndSetStrategyBasedOnBoundaries(sheetId, boundaries, { throwIfSheetAlreadyExists: true }); } } const parser = new ParserWithCaching(config, functionRegistry, dependencyGraph.sheetReferenceRegistrar.ensureSheetRegistered.bind(dependencyGraph.sheetReferenceRegistrar)); lazilyTransformingAstService.parser = parser; const unparser = new Unparser(config, sheetMapping, namedExpressions); const dateTimeHelper = new DateTimeHelper(config); const numberLiteralHelper = new NumberLiteralHelper(config); const arithmeticHelper = new ArithmeticHelper(config, dateTimeHelper, numberLiteralHelper); const cellContentParser = new CellContentParser(config, dateTimeHelper, numberLiteralHelper); const arraySizePredictor = new ArraySizePredictor(config, functionRegistry); const operations = new Operations(config, dependencyGraph, columnSearch, cellContentParser, parser, stats, lazilyTransformingAstService, namedExpressions, arraySizePredictor); const undoRedo = new UndoRedo(config, operations); lazilyTransformingAstService.undoRedo = undoRedo; const clipboardOperations = new ClipboardOperations(config, dependencyGraph, operations); const crudOperations = new CrudOperations(config, operations, undoRedo, clipboardOperations, dependencyGraph, columnSearch, parser, cellContentParser, lazilyTransformingAstService, namedExpressions); const exporter = new Exporter(config, namedExpressions, sheetMapping, lazilyTransformingAstService); const serialization = new Serialization(dependencyGraph, unparser, exporter); const interpreter = new Interpreter(config, dependencyGraph, columnSearch, stats, arithmeticHelper, functionRegistry, namedExpressions, serialization, arraySizePredictor, dateTimeHelper); stats.measure(StatType.GRAPH_BUILD, () => { const graphBuilder = new GraphBuilder(dependencyGraph, columnSearch, parser, cellContentParser, stats, arraySizePredictor); graphBuilder.buildGraph(sheets, stats); }); inputNamedExpressions.forEach(entry => { crudOperations.ensureItIsPossibleToAddNamedExpression(entry.name, entry.expression, entry.scope); crudOperations.operations.addNamedExpression(entry.name, entry.expression, entry.scope, entry.options); }); const evaluator = new Evaluator(config, stats, interpreter, lazilyTransformingAstService, dependencyGraph, columnSearch); evaluator.run(); stats.end(StatType.BUILD_ENGINE_TOTAL); return { config, stats, dependencyGraph, columnSearch, parser, unparser, cellContentParser, evaluator, lazilyTransformingAstService, crudOperations, exporter, namedExpressions, serialization, functionRegistry }; } }