From bd733c9597902bec1c2ab6fcbc41682ddc67dc52 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Sat, 6 Jun 2026 02:48:04 +0300 Subject: [PATCH 01/12] update: add subworkflow error unit --- dist/js/Subworkflow.d.ts | 54 +- .../context/mixins/MaterialContextMixin.d.ts | 2 +- dist/js/enums.d.ts | 4 +- dist/js/enums.js | 2 + dist/js/generated/ErrorUnitSchemaMixin.d.ts | 5 + dist/js/generated/ErrorUnitSchemaMixin.js | 27 + dist/js/index.d.ts | 4 +- dist/js/index.js | 3 +- dist/js/units/ErrorUnit.d.ts | 16 + dist/js/units/ErrorUnit.js | 32 + dist/js/units/factory.d.ts | 10 +- dist/js/units/factory.js | 3 + dist/js/units/index.d.ts | 3 +- dist/js/units/index.js | 4 +- package-lock.json | 1121 ++++++++++------- package.json | 2 +- scripts/generate-mixins.ts | 1 + src/js/context/mixins/MaterialContextMixin.ts | 2 +- src/js/enums.ts | 2 + src/js/generated/ErrorUnitSchemaMixin.ts | 34 + src/js/index.ts | 2 + src/js/units/ErrorUnit.ts | 43 + src/js/units/factory.ts | 19 +- src/js/units/index.ts | 2 + 24 files changed, 905 insertions(+), 492 deletions(-) create mode 100644 dist/js/generated/ErrorUnitSchemaMixin.d.ts create mode 100644 dist/js/generated/ErrorUnitSchemaMixin.js create mode 100644 dist/js/units/ErrorUnit.d.ts create mode 100644 dist/js/units/ErrorUnit.js create mode 100644 src/js/generated/ErrorUnitSchemaMixin.ts create mode 100644 src/js/units/ErrorUnit.ts diff --git a/dist/js/Subworkflow.d.ts b/dist/js/Subworkflow.d.ts index 56cfcea6..0811cc5d 100644 --- a/dist/js/Subworkflow.d.ts +++ b/dist/js/Subworkflow.d.ts @@ -461,7 +461,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { contextProviderName: "vasp-neb"; }; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; } | { @@ -483,7 +483,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { preferGridMetric?: boolean; }; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; } | { @@ -496,7 +496,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { steps: number; }[]]; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; } | { @@ -522,7 +522,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { hubbardUValue?: number; }[]; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; } | { @@ -575,7 +575,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { targetFermiEnergy?: number; }; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; } | { @@ -615,7 +615,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { totalMagnetization: number; }; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; } | { @@ -650,7 +650,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { }; }; extraData: { - materialHash: string; + materialHash?: string; }; isEdited: boolean; })[]; @@ -697,6 +697,46 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { }[]; operand: string; value: string | boolean | number; + } | { + _id?: string; + slug?: string; + systemName?: string; + schemaVersion?: string; + name: string; + isDefault?: boolean; + preProcessors: { + name: string; + [k: string]: unknown; + }[]; + postProcessors: { + name: string; + [k: string]: unknown; + }[]; + monitors: { + name: string; + [k: string]: unknown; + }[]; + results: { + name: string; + [k: string]: unknown; + }[]; + tags?: string[]; + status?: "idle" | "active" | "warning" | "error" | "finished"; + statusTrack?: { + trackedAt: number; + status: string; + repetition?: number; + }[]; + isDraft?: boolean; + type: "error"; + head?: boolean; + flowchartId: string; + next?: string; + enableRender?: boolean; + originalUnit: { + [k: string]: unknown; + }; + reason: string; } | undefined; findUnitKeyById(id: string): string; private findUnitWithTag; diff --git a/dist/js/context/mixins/MaterialContextMixin.d.ts b/dist/js/context/mixins/MaterialContextMixin.d.ts index d22f2b79..6f72d98a 100644 --- a/dist/js/context/mixins/MaterialContextMixin.d.ts +++ b/dist/js/context/mixins/MaterialContextMixin.d.ts @@ -7,7 +7,7 @@ export type MaterialContextMixin = { readonly isMaterialUpdated: boolean; material: OrderedMaterial; extraData?: { - materialHash: string; + materialHash?: string; }; initMaterialContextMixin(externalContext: MaterialExternalContext): void; updateMaterialHash(): void; diff --git a/dist/js/enums.d.ts b/dist/js/enums.d.ts index da08eaf7..0fd809b2 100644 --- a/dist/js/enums.d.ts +++ b/dist/js/enums.d.ts @@ -9,6 +9,7 @@ export declare const UNIT_TYPES: { readonly subworkflow: "subworkflow"; readonly io: "io"; readonly assertion: "assertion"; + readonly error: "error"; }; export declare enum UnitType { convergence = "convergence", @@ -20,7 +21,8 @@ export declare enum UnitType { condition = "condition", subworkflow = "subworkflow", io = "io", - assertion = "assertion" + assertion = "assertion", + error = "error" } export declare enum UnitTag { hasConvergenceParam = "hasConvergenceParam", diff --git a/dist/js/enums.js b/dist/js/enums.js index 180edf9a..61ebebad 100644 --- a/dist/js/enums.js +++ b/dist/js/enums.js @@ -14,6 +14,7 @@ exports.UNIT_TYPES = { subworkflow: "subworkflow", io: "io", assertion: "assertion", + error: "error", }; var UnitType; (function (UnitType) { @@ -27,6 +28,7 @@ var UnitType; UnitType["subworkflow"] = "subworkflow"; UnitType["io"] = "io"; UnitType["assertion"] = "assertion"; + UnitType["error"] = "error"; })(UnitType || (exports.UnitType = UnitType = {})); var UnitTag; (function (UnitTag) { diff --git a/dist/js/generated/ErrorUnitSchemaMixin.d.ts b/dist/js/generated/ErrorUnitSchemaMixin.d.ts new file mode 100644 index 00000000..fe9644c4 --- /dev/null +++ b/dist/js/generated/ErrorUnitSchemaMixin.d.ts @@ -0,0 +1,5 @@ +import type { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import type { ErrorUnitMixinSchema } from "@mat3ra/esse/dist/js/types"; +export type ErrorUnitSchemaMixin = ErrorUnitMixinSchema; +export type ErrorUnitInMemoryEntity = InMemoryEntity & ErrorUnitSchemaMixin; +export declare function errorUnitSchemaMixin(item: InMemoryEntity): asserts item is T & ErrorUnitSchemaMixin; diff --git a/dist/js/generated/ErrorUnitSchemaMixin.js b/dist/js/generated/ErrorUnitSchemaMixin.js new file mode 100644 index 00000000..050ea373 --- /dev/null +++ b/dist/js/generated/ErrorUnitSchemaMixin.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.errorUnitSchemaMixin = errorUnitSchemaMixin; +function errorUnitSchemaMixin(item) { + // @ts-expect-error + const properties = { + get type() { + return this.prop("type"); + }, + set type(value) { + this.setProp("type", value); + }, + get originalUnit() { + return this.requiredProp("originalUnit"); + }, + set originalUnit(value) { + this.setProp("originalUnit", value); + }, + get reason() { + return this.requiredProp("reason"); + }, + set reason(value) { + this.setProp("reason", value); + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} diff --git a/dist/js/index.d.ts b/dist/js/index.d.ts index 10b9b327..331547d5 100644 --- a/dist/js/index.d.ts +++ b/dist/js/index.d.ts @@ -2,7 +2,7 @@ import PointsPathFormDataProvider from "./context/providers/PointsPath/PointsPat import { globalSettings } from "./context/providers/settings"; import { TAB_NAVIGATION_CONFIG, UNIT_NAME_INVALID_CHARS, WORKFLOW_STATUSES } from "./enums"; import Subworkflow from "./Subworkflow"; -import { AssertionUnit, AssignmentUnit, BaseUnit, ConditionUnit, ExecutionUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit } from "./units"; +import { AssertionUnit, AssignmentUnit, BaseUnit, ConditionUnit, ErrorUnit, ExecutionUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit } from "./units"; import { UnitFactory } from "./units/factory"; import { defaultMapConfig } from "./units/MapUnit"; import * as utils from "./utils"; @@ -10,4 +10,4 @@ import Workflow from "./Workflow"; export type { OrderedMaterial } from "./context/mixins/MaterialContextMixin"; export type { MaterialsSet } from "./context/mixins/MaterialsSetContextMixin"; export type { AnySubworkflowUnit, DefaultSubworkflowUnitType } from "./units/factory"; -export { Subworkflow, Workflow, UnitFactory, TAB_NAVIGATION_CONFIG, UNIT_NAME_INVALID_CHARS, WORKFLOW_STATUSES, BaseUnit, ExecutionUnit, AssertionUnit, AssignmentUnit, ConditionUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit, defaultMapConfig, PointsPathFormDataProvider, globalSettings, utils, }; +export { Subworkflow, Workflow, UnitFactory, TAB_NAVIGATION_CONFIG, UNIT_NAME_INVALID_CHARS, WORKFLOW_STATUSES, BaseUnit, ExecutionUnit, AssertionUnit, AssignmentUnit, ConditionUnit, ErrorUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit, defaultMapConfig, PointsPathFormDataProvider, globalSettings, utils, }; diff --git a/dist/js/index.js b/dist/js/index.js index d88df78b..eb344d0e 100644 --- a/dist/js/index.js +++ b/dist/js/index.js @@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.utils = exports.globalSettings = exports.PointsPathFormDataProvider = exports.defaultMapConfig = exports.SubworkflowUnit = exports.ReduceUnit = exports.MapUnit = exports.IOUnit = exports.ConditionUnit = exports.AssignmentUnit = exports.AssertionUnit = exports.ExecutionUnit = exports.BaseUnit = exports.WORKFLOW_STATUSES = exports.UNIT_NAME_INVALID_CHARS = exports.TAB_NAVIGATION_CONFIG = exports.UnitFactory = exports.Workflow = exports.Subworkflow = void 0; +exports.utils = exports.globalSettings = exports.PointsPathFormDataProvider = exports.defaultMapConfig = exports.SubworkflowUnit = exports.ReduceUnit = exports.MapUnit = exports.IOUnit = exports.ErrorUnit = exports.ConditionUnit = exports.AssignmentUnit = exports.AssertionUnit = exports.ExecutionUnit = exports.BaseUnit = exports.WORKFLOW_STATUSES = exports.UNIT_NAME_INVALID_CHARS = exports.TAB_NAVIGATION_CONFIG = exports.UnitFactory = exports.Workflow = exports.Subworkflow = void 0; const PointsPathFormDataProvider_1 = __importDefault(require("./context/providers/PointsPath/PointsPathFormDataProvider")); exports.PointsPathFormDataProvider = PointsPathFormDataProvider_1.default; const settings_1 = require("./context/providers/settings"); @@ -52,6 +52,7 @@ Object.defineProperty(exports, "AssertionUnit", { enumerable: true, get: functio Object.defineProperty(exports, "AssignmentUnit", { enumerable: true, get: function () { return units_1.AssignmentUnit; } }); Object.defineProperty(exports, "BaseUnit", { enumerable: true, get: function () { return units_1.BaseUnit; } }); Object.defineProperty(exports, "ConditionUnit", { enumerable: true, get: function () { return units_1.ConditionUnit; } }); +Object.defineProperty(exports, "ErrorUnit", { enumerable: true, get: function () { return units_1.ErrorUnit; } }); Object.defineProperty(exports, "ExecutionUnit", { enumerable: true, get: function () { return units_1.ExecutionUnit; } }); Object.defineProperty(exports, "IOUnit", { enumerable: true, get: function () { return units_1.IOUnit; } }); Object.defineProperty(exports, "MapUnit", { enumerable: true, get: function () { return units_1.MapUnit; } }); diff --git a/dist/js/units/ErrorUnit.d.ts b/dist/js/units/ErrorUnit.d.ts new file mode 100644 index 00000000..e56278af --- /dev/null +++ b/dist/js/units/ErrorUnit.d.ts @@ -0,0 +1,16 @@ +import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; +import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; +import type { ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; +import { type ErrorUnitSchemaMixin } from "../generated/ErrorUnitSchemaMixin"; +import BaseUnit from "./BaseUnit"; +type Schema = ErrorUnitSchema; +type Base = typeof BaseUnit & Constructor; +export type ErrorUnitConfig = Partial; +declare const ErrorUnit_base: Base; +declare class ErrorUnit extends ErrorUnit_base implements Schema { + toJSON: () => Schema & AnyObject; + _json: Schema & AnyObject; + static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; + constructor(config: ErrorUnitConfig); +} +export default ErrorUnit; diff --git a/dist/js/units/ErrorUnit.js b/dist/js/units/ErrorUnit.js new file mode 100644 index 00000000..63d12a7f --- /dev/null +++ b/dist/js/units/ErrorUnit.js @@ -0,0 +1,32 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const JSONSchemasInterface_1 = __importDefault(require("@mat3ra/esse/dist/js/esse/JSONSchemasInterface")); +const enums_1 = require("../enums"); +const ErrorUnitSchemaMixin_1 = require("../generated/ErrorUnitSchemaMixin"); +const BaseUnit_1 = __importDefault(require("./BaseUnit")); +class ErrorUnit extends BaseUnit_1.default { + static get jsonSchema() { + return JSONSchemasInterface_1.default.getSchemaById("workflow/unit/error"); + } + constructor(config) { + var _a; + const schema = { + name: enums_1.UnitType.error, + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + originalUnit: {}, + reason: "", + ...config, + type: enums_1.UnitType.error, + status: (_a = config.status) !== null && _a !== void 0 ? _a : enums_1.UnitStatus.error, + }; + super(schema); + } +} +(0, ErrorUnitSchemaMixin_1.errorUnitSchemaMixin)(ErrorUnit.prototype); +exports.default = ErrorUnit; diff --git a/dist/js/units/factory.d.ts b/dist/js/units/factory.d.ts index 087d647a..3022c1e4 100644 --- a/dist/js/units/factory.d.ts +++ b/dist/js/units/factory.d.ts @@ -1,7 +1,8 @@ -import type { AssertionUnitSchema, AssignmentUnitSchema, ConditionUnitSchema, DataIOUnitSchema, ExecutionUnitSchema, MapUnitSchema, ReduceUnitSchema, SubworkflowUnitSchema, WorkflowUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { AssertionUnitSchema, AssignmentUnitSchema, ConditionUnitSchema, DataIOUnitSchema, ErrorUnitSchema, ExecutionUnitSchema, MapUnitSchema, ReduceUnitSchema, SubworkflowUnitSchema, WorkflowUnitSchema } from "@mat3ra/esse/dist/js/types"; import AssertionUnit, { type AssertionUnitConfig } from "./AssertionUnit"; import AssignmentUnit, { type AssignmentUnitConfig } from "./AssignmentUnit"; import ConditionUnit, { type ConditionUnitConfig } from "./ConditionUnit"; +import ErrorUnit, { type ErrorUnitConfig } from "./ErrorUnit"; import ExecutionUnit, { type ExecutionUnitConfig } from "./ExecutionUnit"; import IOUnit, { type IOUnitConfig } from "./IOUnit"; import MapUnit from "./MapUnit"; @@ -9,13 +10,14 @@ import ReduceUnit from "./ReduceUnit"; import SubworkflowUnit from "./SubworkflowUnit"; export type AnyWorkflowUnit = MapUnit | SubworkflowUnit | ReduceUnit; export type AnyWorkflowUnitSchema = MapUnitSchema | SubworkflowUnitSchema | ReduceUnitSchema; -export type AnySubworkflowUnit = ExecutionUnit | AssignmentUnit | ConditionUnit | IOUnit | AssertionUnit; -export type AnySubworkflowUnitSchema = ExecutionUnitSchema | AssertionUnitSchema | AssignmentUnitSchema | ConditionUnitSchema | DataIOUnitSchema; +export type AnySubworkflowUnit = ExecutionUnit | AssignmentUnit | ConditionUnit | IOUnit | AssertionUnit | ErrorUnit; +export type AnySubworkflowUnitSchema = ExecutionUnitSchema | AssertionUnitSchema | AssignmentUnitSchema | ConditionUnitSchema | DataIOUnitSchema | ErrorUnitSchema; type ExcutionConfig = ExecutionUnitConfig & Pick; type AssignmentConfig = AssignmentUnitConfig & Pick; type ConditionConfig = ConditionUnitConfig & Pick; type IOConfig = IOUnitConfig & Pick; type AssertionConfig = AssertionUnitConfig & Pick; +type ErrorConfig = ErrorUnitConfig & Pick; /** Subworkflow unit kinds supported by {@link UnitFactory.createDefaultSubworkflowUnit}. */ export type DefaultSubworkflowUnitType = "execution" | "assignment" | "condition" | "io" | "assertion"; export declare class UnitFactory { @@ -26,6 +28,6 @@ export declare class UnitFactory { static createDefaultSubworkflowUnit(type: "execution", application: ExecutionUnitSchema["application"]): AnySubworkflowUnit; static createDefaultSubworkflowUnit(type: "assignment" | "condition" | "io" | "assertion"): AnySubworkflowUnit; static createInWorkflow(config: WorkflowUnitSchema): AnyWorkflowUnit; - static createInSubworkflow(config: ExcutionConfig | AssignmentConfig | ConditionConfig | IOConfig | AssertionConfig): AnySubworkflowUnit; + static createInSubworkflow(config: ExcutionConfig | AssignmentConfig | ConditionConfig | IOConfig | AssertionConfig | ErrorConfig): AnySubworkflowUnit; } export {}; diff --git a/dist/js/units/factory.js b/dist/js/units/factory.js index d0eb2e7f..e4145e2b 100644 --- a/dist/js/units/factory.js +++ b/dist/js/units/factory.js @@ -8,6 +8,7 @@ const enums_1 = require("../enums"); const AssertionUnit_1 = __importDefault(require("./AssertionUnit")); const AssignmentUnit_1 = __importDefault(require("./AssignmentUnit")); const ConditionUnit_1 = __importDefault(require("./ConditionUnit")); +const ErrorUnit_1 = __importDefault(require("./ErrorUnit")); const ExecutionUnit_1 = __importDefault(require("./ExecutionUnit")); const IOUnit_1 = __importDefault(require("./IOUnit")); const MapUnit_1 = __importDefault(require("./MapUnit")); @@ -63,6 +64,8 @@ class UnitFactory { return new IOUnit_1.default(config); case enums_1.UnitType.assertion: return new AssertionUnit_1.default(config); + case enums_1.UnitType.error: + return new ErrorUnit_1.default(config); default: throw new Error(`Unknown unit type: ${config.type}`); } diff --git a/dist/js/units/index.d.ts b/dist/js/units/index.d.ts index a7f25dcf..ad503f80 100644 --- a/dist/js/units/index.d.ts +++ b/dist/js/units/index.d.ts @@ -2,6 +2,7 @@ import AssertionUnit from "./AssertionUnit"; import AssignmentUnit from "./AssignmentUnit"; import BaseUnit from "./BaseUnit"; import ConditionUnit from "./ConditionUnit"; +import ErrorUnit from "./ErrorUnit"; import ExecutionUnit from "./ExecutionUnit"; import { UnitFactory } from "./factory"; import IOUnit from "./IOUnit"; @@ -10,5 +11,5 @@ import ReduceUnit from "./ReduceUnit"; import SubworkflowUnit from "./SubworkflowUnit"; export type { ReduceUnitConfig } from "./ReduceUnit"; export type { SubworkflowUnitConfig } from "./SubworkflowUnit"; -export { BaseUnit, AssertionUnit, AssignmentUnit, ConditionUnit, ExecutionUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit, UnitFactory, }; +export { BaseUnit, AssertionUnit, AssignmentUnit, ConditionUnit, ErrorUnit, ExecutionUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit, UnitFactory, }; export type { DefaultSubworkflowUnitType } from "./factory"; diff --git a/dist/js/units/index.js b/dist/js/units/index.js index cc4989c7..a578db43 100644 --- a/dist/js/units/index.js +++ b/dist/js/units/index.js @@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.UnitFactory = exports.SubworkflowUnit = exports.ReduceUnit = exports.MapUnit = exports.IOUnit = exports.ExecutionUnit = exports.ConditionUnit = exports.AssignmentUnit = exports.AssertionUnit = exports.BaseUnit = void 0; +exports.UnitFactory = exports.SubworkflowUnit = exports.ReduceUnit = exports.MapUnit = exports.IOUnit = exports.ExecutionUnit = exports.ErrorUnit = exports.ConditionUnit = exports.AssignmentUnit = exports.AssertionUnit = exports.BaseUnit = void 0; const AssertionUnit_1 = __importDefault(require("./AssertionUnit")); exports.AssertionUnit = AssertionUnit_1.default; const AssignmentUnit_1 = __importDefault(require("./AssignmentUnit")); @@ -12,6 +12,8 @@ const BaseUnit_1 = __importDefault(require("./BaseUnit")); exports.BaseUnit = BaseUnit_1.default; const ConditionUnit_1 = __importDefault(require("./ConditionUnit")); exports.ConditionUnit = ConditionUnit_1.default; +const ErrorUnit_1 = __importDefault(require("./ErrorUnit")); +exports.ErrorUnit = ErrorUnit_1.default; const ExecutionUnit_1 = __importDefault(require("./ExecutionUnit")); exports.ExecutionUnit = ExecutionUnit_1.default; const factory_1 = require("./factory"); diff --git a/package-lock.json b/package-lock.json index faff7158..f152a8f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "2026.5.28-0", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/906c4bc2a5b6c9cd90472b1f65aeb3568d9c4d9c.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", @@ -78,6 +78,8 @@ }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz", + "integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==", "dev": true, "license": "MIT", "dependencies": { @@ -120,12 +122,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -134,9 +136,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -187,13 +189,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -203,23 +205,25 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -229,17 +233,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "engines": { @@ -250,10 +254,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, @@ -290,45 +296,49 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -338,31 +348,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -372,14 +386,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -389,57 +403,67 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.28.3", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -516,12 +540,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -531,14 +555,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -548,13 +572,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -564,10 +588,29 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -577,12 +620,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -592,14 +637,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -881,13 +926,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -897,13 +942,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -923,11 +968,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1054,10 +1101,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1067,15 +1116,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", - "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.29.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1085,14 +1134,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1102,10 +1151,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1115,12 +1166,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1130,14 +1181,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1147,14 +1198,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1164,17 +1215,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1184,13 +1235,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1200,11 +1251,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1214,13 +1267,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1230,10 +1283,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1243,14 +1298,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1260,13 +1315,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1276,14 +1331,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1293,12 +1348,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1308,13 +1363,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1324,11 +1379,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1338,12 +1395,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1353,13 +1412,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1369,10 +1428,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1382,13 +1443,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1398,10 +1459,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1411,11 +1474,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1425,13 +1490,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1441,15 +1506,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.29.0" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1459,11 +1524,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1473,13 +1540,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1489,10 +1556,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1502,13 +1571,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1518,13 +1587,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1534,17 +1603,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1554,11 +1623,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1568,13 +1639,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1584,13 +1655,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1600,10 +1671,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1613,14 +1686,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1630,15 +1703,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1648,10 +1721,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1661,11 +1736,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.28.0", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1675,15 +1752,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1693,11 +1772,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.27.1" + "@babel/plugin-transform-react-jsx": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1707,12 +1788,14 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1722,12 +1805,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", - "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1737,14 +1820,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1754,10 +1837,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1767,10 +1852,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1780,13 +1867,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1796,10 +1883,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1809,10 +1898,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1822,10 +1913,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1853,10 +1946,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1866,14 +1961,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1883,11 +1978,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1897,14 +1994,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2091,31 +2188,31 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { @@ -2123,13 +2220,13 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2495,6 +2592,8 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2523,6 +2622,8 @@ }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "dev": true, "license": "MIT" }, @@ -2584,9 +2685,9 @@ } }, "node_modules/@mat3ra/esse": { - "version": "2026.5.28-0", - "resolved": "https://registry.npmjs.org/@mat3ra/esse/-/esse-2026.5.28-0.tgz", - "integrity": "sha512-J9nL113XnnOT7sWIWe1hUU4+GXrLrxruH6d8X94nsCTe0MN8n+3ABwL7MVJJ/HrvjgurrehoM/xvKxHC6vMurQ==", + "version": "0.0.0", + "resolved": "https://github.com/Exabyte-io/esse/archive/906c4bc2a5b6c9cd90472b1f65aeb3568d9c4d9c.tar.gz", + "integrity": "sha512-VmpeGiPiIFj/BE4x0eHSSAFmOsr8UzcVOFLu2iiXRiuV/e7xRqCbAMtvc1d1SNWPcPYtSDUBVDzE4XI9RUNe/g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2618,9 +2719,9 @@ } }, "node_modules/@mat3ra/esse/node_modules/@babel/cli": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz", - "integrity": "sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.29.7.tgz", + "integrity": "sha512-/75HwRbAYPqXv/Ax1h7Fg3IZfXgdU98jnA8H93/m/QBaPV3Hp5ICoLqzGYye1yHBCgpmXvtqgSUN8oOKX5tojQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2648,21 +2749,21 @@ } }, "node_modules/@mat3ra/esse/node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -2679,9 +2780,9 @@ } }, "node_modules/@mat3ra/esse/node_modules/@babel/eslint-parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", - "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "dev": true, "license": "MIT", "dependencies": { @@ -2716,6 +2817,9 @@ }, "node_modules/@mat3ra/esse/node_modules/@babel/plugin-proposal-class-properties": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", "dev": true, "license": "MIT", "dependencies": { @@ -2743,76 +2847,77 @@ } }, "node_modules/@mat3ra/esse/node_modules/@babel/preset-env": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz", - "integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.29.0", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.29.0", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.29.0", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.15", "babel-plugin-polyfill-corejs3": "^0.14.0", @@ -2843,16 +2948,18 @@ } }, "node_modules/@mat3ra/esse/node_modules/@babel/preset-react": { - "version": "7.28.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.28.0", - "@babel/plugin-transform-react-jsx": "^7.27.1", - "@babel/plugin-transform-react-jsx-development": "^7.27.1", - "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2862,9 +2969,9 @@ } }, "node_modules/@mat3ra/esse/node_modules/@babel/runtime-corejs3": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.2.tgz", - "integrity": "sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.7.tgz", + "integrity": "sha512-ppj9ouYku+RX0ljtgZd+KMO5mkM2bCqg8H2PYAFWnLsHEIKIdRojqbJ2i3eVHrisuxy7nOFCmngTDdWtUCdXUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3292,9 +3399,9 @@ } }, "node_modules/@mat3ra/esse/node_modules/@mat3ra/utils/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "bin": { @@ -3372,6 +3479,8 @@ }, "node_modules/@mat3ra/esse/node_modules/convert-source-map": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, @@ -3390,10 +3499,20 @@ } }, "node_modules/@mat3ra/esse/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4167,6 +4286,8 @@ }, "node_modules/@types/js-yaml": { "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", "dev": true, "license": "MIT" }, @@ -4176,6 +4297,8 @@ }, "node_modules/@types/json-schema-merge-allof": { "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@types/json-schema-merge-allof/-/json-schema-merge-allof-0.6.5.tgz", + "integrity": "sha512-5mS11ZUTyFNUVEMpK3uKoPb6BWL/nLgW/ln2VOiI8OOxKEYC4Gl9O3WjS5P49yqVTfkcbCAPKw3T1O4erUah5g==", "dev": true, "license": "MIT", "dependencies": { @@ -4298,9 +4421,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "peer": true, @@ -4433,9 +4556,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "peer": true, @@ -4475,9 +4598,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "peer": true, @@ -4599,6 +4722,8 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", "dependencies": { @@ -5155,6 +5280,8 @@ }, "node_modules/charenc": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -5267,6 +5394,8 @@ }, "node_modules/clone": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", "dev": true, "license": "MIT", "engines": { @@ -5395,6 +5524,8 @@ }, "node_modules/compute-gcd": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", "dev": true, "dependencies": { "validate.io-array": "^1.0.3", @@ -5404,6 +5535,8 @@ }, "node_modules/compute-lcm": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", "dev": true, "dependencies": { "compute-gcd": "^1.2.1", @@ -5469,6 +5602,8 @@ }, "node_modules/crypt": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -5486,6 +5621,8 @@ }, "node_modules/dag-map": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz", + "integrity": "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==", "dev": true, "license": "MIT" }, @@ -5956,9 +6093,9 @@ } }, "node_modules/eslint-compat-utils/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "peer": true, @@ -7344,6 +7481,8 @@ }, "node_modules/is-buffer": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true, "license": "MIT" }, @@ -7464,6 +7603,8 @@ }, "node_modules/is-invalid-path": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", + "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7475,6 +7616,8 @@ }, "node_modules/is-invalid-path/node_modules/is-extglob": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", "dev": true, "license": "MIT", "engines": { @@ -7483,6 +7626,8 @@ }, "node_modules/is-invalid-path/node_modules/is-glob": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -7671,6 +7816,8 @@ }, "node_modules/is-valid-path": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", + "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==", "dev": true, "license": "MIT", "dependencies": { @@ -7924,6 +8071,8 @@ }, "node_modules/json-schema-compare": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7932,6 +8081,8 @@ }, "node_modules/json-schema-deref-sync": { "version": "0.14.0", + "resolved": "https://registry.npmjs.org/json-schema-deref-sync/-/json-schema-deref-sync-0.14.0.tgz", + "integrity": "sha512-yGR1xmhdiD6R0MSrwWcFxQzAj5b3i5Gb/mt5tvQKgFMMeNe0KZYNEN/jWr7G+xn39Azqgcvk4ZKMs8dQl8e4wA==", "dev": true, "license": "MIT", "dependencies": { @@ -7950,6 +8101,8 @@ }, "node_modules/json-schema-merge-allof": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", "dev": true, "license": "MIT", "dependencies": { @@ -7963,6 +8116,8 @@ }, "node_modules/json-schema-to-typescript": { "version": "15.0.4", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.4.tgz", + "integrity": "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7984,7 +8139,9 @@ } }, "node_modules/json-schema-to-typescript/node_modules/prettier": { - "version": "3.6.2", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", "bin": { @@ -8083,9 +8240,9 @@ } }, "node_modules/jsonc-eslint-parser/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "peer": true, @@ -8498,6 +8655,8 @@ }, "node_modules/md5": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8508,6 +8667,8 @@ }, "node_modules/memory-cache": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", + "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==", "dev": true, "license": "BSD-2-Clause" }, @@ -10464,12 +10625,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.15", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -10480,6 +10643,8 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -10495,7 +10660,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -10518,6 +10685,8 @@ }, "node_modules/traverse": { "version": "0.6.11", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.11.tgz", + "integrity": "sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==", "dev": true, "license": "MIT", "dependencies": { @@ -10768,6 +10937,8 @@ }, "node_modules/typedarray.prototype.slice": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.5.tgz", + "integrity": "sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==", "dev": true, "license": "MIT", "dependencies": { @@ -10929,19 +11100,27 @@ }, "node_modules/valid-url": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==", "dev": true }, "node_modules/validate.io-array": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", "dev": true, "license": "MIT" }, "node_modules/validate.io-function": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==", "dev": true }, "node_modules/validate.io-integer": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", "dev": true, "dependencies": { "validate.io-number": "^1.0.3" @@ -10949,6 +11128,8 @@ }, "node_modules/validate.io-integer-array": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", "dev": true, "dependencies": { "validate.io-array": "^1.0.3", @@ -10957,6 +11138,8 @@ }, "node_modules/validate.io-number": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==", "dev": true }, "node_modules/which": { diff --git a/package.json b/package.json index d1802c1f..de6b3b75 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "2026.5.28-0", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/906c4bc2a5b6c9cd90472b1f65aeb3568d9c4d9c.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", diff --git a/scripts/generate-mixins.ts b/scripts/generate-mixins.ts index 9e80395e..d8fec630 100644 --- a/scripts/generate-mixins.ts +++ b/scripts/generate-mixins.ts @@ -28,6 +28,7 @@ const OUTPUT_PATHS = { "workflow/unit/mixins/map": "src/js/generated/MapUnitSchemaMixin.ts", "workflow/unit/mixins/reduce": "src/js/generated/ReduceUnitSchemaMixin.ts", "workflow/unit/mixins/subworkflow": "src/js/generated/SubworkflowUnitSchemaMixin.ts", + "workflow/unit/mixins/error": "src/js/generated/ErrorUnitSchemaMixin.ts", "workflow/unit/input/-inputItem": "src/js/generated/ExecutionUnitInputSchemaMixin.ts", "workflow/subworkflow/mixin": "src/js/generated/SubworkflowSchemaMixin.ts", "workflow/base": "src/js/generated/WorkflowSchemaMixin.ts", diff --git a/src/js/context/mixins/MaterialContextMixin.ts b/src/js/context/mixins/MaterialContextMixin.ts index 6346e1db..5f12a994 100644 --- a/src/js/context/mixins/MaterialContextMixin.ts +++ b/src/js/context/mixins/MaterialContextMixin.ts @@ -9,7 +9,7 @@ export type MaterialContextMixin = { readonly isMaterialCreatedDefault: boolean; readonly isMaterialUpdated: boolean; material: OrderedMaterial; - extraData?: { materialHash: string }; + extraData?: { materialHash?: string }; initMaterialContextMixin(externalContext: MaterialExternalContext): void; updateMaterialHash(): void; }; diff --git a/src/js/enums.ts b/src/js/enums.ts index ee819d61..7129d27e 100644 --- a/src/js/enums.ts +++ b/src/js/enums.ts @@ -11,6 +11,7 @@ export const UNIT_TYPES = { subworkflow: "subworkflow", io: "io", assertion: "assertion", + error: "error", } as const; export enum UnitType { @@ -24,6 +25,7 @@ export enum UnitType { subworkflow = "subworkflow", io = "io", assertion = "assertion", + error = "error", } export enum UnitTag { diff --git a/src/js/generated/ErrorUnitSchemaMixin.ts b/src/js/generated/ErrorUnitSchemaMixin.ts new file mode 100644 index 00000000..75aa9a08 --- /dev/null +++ b/src/js/generated/ErrorUnitSchemaMixin.ts @@ -0,0 +1,34 @@ +import type { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import type { ErrorUnitMixinSchema } from "@mat3ra/esse/dist/js/types"; + +export type ErrorUnitSchemaMixin = ErrorUnitMixinSchema; + +export type ErrorUnitInMemoryEntity = InMemoryEntity & ErrorUnitSchemaMixin; + +export function errorUnitSchemaMixin( + item: InMemoryEntity, +): asserts item is T & ErrorUnitSchemaMixin { + // @ts-expect-error + const properties: InMemoryEntity & ErrorUnitSchemaMixin = { + get type() { + return this.prop("type"); + }, + set type(value: ErrorUnitMixinSchema["type"]) { + this.setProp("type", value); + }, + get originalUnit() { + return this.requiredProp("originalUnit"); + }, + set originalUnit(value: ErrorUnitMixinSchema["originalUnit"]) { + this.setProp("originalUnit", value); + }, + get reason() { + return this.requiredProp("reason"); + }, + set reason(value: ErrorUnitMixinSchema["reason"]) { + this.setProp("reason", value); + }, + }; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} diff --git a/src/js/index.ts b/src/js/index.ts index 83d9fcd1..039fb705 100644 --- a/src/js/index.ts +++ b/src/js/index.ts @@ -7,6 +7,7 @@ import { AssignmentUnit, BaseUnit, ConditionUnit, + ErrorUnit, ExecutionUnit, IOUnit, MapUnit, @@ -33,6 +34,7 @@ export { AssertionUnit, AssignmentUnit, ConditionUnit, + ErrorUnit, IOUnit, MapUnit, ReduceUnit, diff --git a/src/js/units/ErrorUnit.ts b/src/js/units/ErrorUnit.ts new file mode 100644 index 00000000..661e2679 --- /dev/null +++ b/src/js/units/ErrorUnit.ts @@ -0,0 +1,43 @@ +import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; +import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; +import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; +import type { ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; + +import { UnitStatus, UnitType } from "../enums"; +import { type ErrorUnitSchemaMixin, errorUnitSchemaMixin } from "../generated/ErrorUnitSchemaMixin"; +import BaseUnit from "./BaseUnit"; + +type Schema = ErrorUnitSchema; +type Base = typeof BaseUnit & Constructor; + +export type ErrorUnitConfig = Partial; + +class ErrorUnit extends (BaseUnit as Base) implements Schema { + declare toJSON: () => Schema & AnyObject; + + declare _json: Schema & AnyObject; + + static get jsonSchema() { + return JSONSchemasInterface.getSchemaById("workflow/unit/error"); + } + + constructor(config: ErrorUnitConfig) { + const schema = { + name: UnitType.error, + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + originalUnit: {}, + reason: "", + ...config, + type: UnitType.error as Schema["type"], + status: config.status ?? UnitStatus.error, + }; + super(schema); + } +} + +errorUnitSchemaMixin(ErrorUnit.prototype); + +export default ErrorUnit; diff --git a/src/js/units/factory.ts b/src/js/units/factory.ts index aa227a3d..f6ff91fa 100644 --- a/src/js/units/factory.ts +++ b/src/js/units/factory.ts @@ -3,6 +3,7 @@ import type { AssignmentUnitSchema, ConditionUnitSchema, DataIOUnitSchema, + ErrorUnitSchema, ExecutionUnitSchema, MapUnitSchema, ReduceUnitSchema, @@ -14,6 +15,7 @@ import { UnitType } from "../enums"; import AssertionUnit, { type AssertionUnitConfig } from "./AssertionUnit"; import AssignmentUnit, { type AssignmentUnitConfig } from "./AssignmentUnit"; import ConditionUnit, { type ConditionUnitConfig } from "./ConditionUnit"; +import ErrorUnit, { type ErrorUnitConfig } from "./ErrorUnit"; import ExecutionUnit, { type ExecutionUnitConfig } from "./ExecutionUnit"; import IOUnit, { type IOUnitConfig } from "./IOUnit"; import MapUnit from "./MapUnit"; @@ -29,20 +31,23 @@ export type AnySubworkflowUnit = | AssignmentUnit | ConditionUnit | IOUnit - | AssertionUnit; + | AssertionUnit + | ErrorUnit; export type AnySubworkflowUnitSchema = | ExecutionUnitSchema | AssertionUnitSchema | AssignmentUnitSchema | ConditionUnitSchema - | DataIOUnitSchema; + | DataIOUnitSchema + | ErrorUnitSchema; type ExcutionConfig = ExecutionUnitConfig & Pick; type AssignmentConfig = AssignmentUnitConfig & Pick; type ConditionConfig = ConditionUnitConfig & Pick; type IOConfig = IOUnitConfig & Pick; type AssertionConfig = AssertionUnitConfig & Pick; +type ErrorConfig = ErrorUnitConfig & Pick; /** Subworkflow unit kinds supported by {@link UnitFactory.createDefaultSubworkflowUnit}. */ export type DefaultSubworkflowUnitType = @@ -111,7 +116,13 @@ export class UnitFactory { } static createInSubworkflow( - config: ExcutionConfig | AssignmentConfig | ConditionConfig | IOConfig | AssertionConfig, + config: + | ExcutionConfig + | AssignmentConfig + | ConditionConfig + | IOConfig + | AssertionConfig + | ErrorConfig, ): AnySubworkflowUnit { switch (config.type) { case UnitType.execution: @@ -124,6 +135,8 @@ export class UnitFactory { return new IOUnit(config); case UnitType.assertion: return new AssertionUnit(config); + case UnitType.error: + return new ErrorUnit(config); default: throw new Error(`Unknown unit type: ${config.type}`); } diff --git a/src/js/units/index.ts b/src/js/units/index.ts index 58b8bb4b..cd9d0f63 100644 --- a/src/js/units/index.ts +++ b/src/js/units/index.ts @@ -2,6 +2,7 @@ import AssertionUnit from "./AssertionUnit"; import AssignmentUnit from "./AssignmentUnit"; import BaseUnit from "./BaseUnit"; import ConditionUnit from "./ConditionUnit"; +import ErrorUnit from "./ErrorUnit"; import ExecutionUnit from "./ExecutionUnit"; import { UnitFactory } from "./factory"; import IOUnit from "./IOUnit"; @@ -16,6 +17,7 @@ export { AssertionUnit, AssignmentUnit, ConditionUnit, + ErrorUnit, ExecutionUnit, IOUnit, MapUnit, From 51430b6d2ddcbc5cdbfa841ca34bf5b68cbb6a0d Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 8 Jun 2026 14:54:12 +0300 Subject: [PATCH 02/12] update: add repair methods --- dist/js/Subworkflow.d.ts | 9 +- dist/js/Subworkflow.js | 13 +- dist/js/Workflow.d.ts | 4 +- dist/js/Workflow.js | 13 ++ dist/js/repair/createErrorUnitData.d.ts | 3 + dist/js/repair/createErrorUnitData.js | 25 ++++ dist/js/repair/formatRepairReason.d.ts | 1 + dist/js/repair/formatRepairReason.js | 22 ++++ dist/js/repair/types.d.ts | 16 +++ dist/js/repair/types.js | 2 + dist/js/units/ExecutionUnit.d.ts | 3 +- dist/js/units/ExecutionUnit.js | 22 ++++ dist/js/units/factory.d.ts | 9 +- dist/js/workflows/default.d.ts | 2 +- dist/js/workflows/types.d.ts | 4 + dist/js/workflows/types.js | 2 + package-lock.json | 6 +- package.json | 2 +- src/js/Subworkflow.ts | 27 +++- src/js/Workflow.ts | 23 +++- src/js/units/ExecutionUnit.ts | 29 ++++- src/js/units/factory.ts | 17 ++- src/js/workflows/default.ts | 2 +- src/js/workflows/types.ts | 5 + tests/js/Workflow.test.ts | 8 +- .../js/executionUnit.contextProviders.test.ts | 22 +++- tests/js/kpath.vaspBands.test.ts | 10 +- tests/js/repair.test.ts | 122 ++++++++++++++++++ .../subworkflow.standata.integration.test.ts | 6 +- 29 files changed, 376 insertions(+), 53 deletions(-) create mode 100644 dist/js/repair/createErrorUnitData.d.ts create mode 100644 dist/js/repair/createErrorUnitData.js create mode 100644 dist/js/repair/formatRepairReason.d.ts create mode 100644 dist/js/repair/formatRepairReason.js create mode 100644 dist/js/repair/types.d.ts create mode 100644 dist/js/repair/types.js create mode 100644 dist/js/workflows/types.d.ts create mode 100644 dist/js/workflows/types.js create mode 100644 src/js/workflows/types.ts create mode 100644 tests/js/repair.test.ts diff --git a/dist/js/Subworkflow.d.ts b/dist/js/Subworkflow.d.ts index 0811cc5d..170e9dd6 100644 --- a/dist/js/Subworkflow.d.ts +++ b/dist/js/Subworkflow.d.ts @@ -40,13 +40,14 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { toJSON: () => SubworkflowSchema & AnyObject; _json: SubworkflowSchema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; + static repair(subworkflowData: SubworkflowSchema): SubworkflowSchema; constructor(config: SubworkflowSchema, _ModelFactory?: typeof ModelFactory); static get defaultConfig(): { _id: any; name: string; - application: import("@mat3ra/esse/dist/js/types").ApplicationSchema | undefined; + application: import("@mat3ra/esse/dist/js/types").ApplicationSchema; model: { - functional: string; + functional: "pbe"; method: { readonly type: "pseudopotential"; readonly subtype: "us"; @@ -733,9 +734,7 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { flowchartId: string; next?: string; enableRender?: boolean; - originalUnit: { - [k: string]: unknown; - }; + originalUnit: {}; reason: string; } | undefined; findUnitKeyById(id: string): string; diff --git a/dist/js/Subworkflow.js b/dist/js/Subworkflow.js index f5f1d916..cc77176e 100644 --- a/dist/js/Subworkflow.js +++ b/dist/js/Subworkflow.js @@ -21,6 +21,12 @@ class Subworkflow extends entity_1.InMemoryEntity { static get jsonSchema() { return JSONSchemasInterface_1.default.getSchemaById("workflow/subworkflow"); } + static repair(subworkflowData) { + const units = subworkflowData.units.map((unit) => { + return unit.type === enums_1.UnitType.execution ? units_1.ExecutionUnit.repair(unit) : unit; + }); + return { ...subworkflowData, units }; + } constructor(config, _ModelFactory = mode_1.ModelFactory) { super(config); this.properties = []; @@ -35,11 +41,14 @@ class Subworkflow extends entity_1.InMemoryEntity { } static get defaultConfig() { const defaultName = "New Subworkflow"; + const application = new standata_1.ApplicationRegistry().getDefaultApplication(); + if (!application) { + throw new Error("No default application found"); + } return { _id: utils_1.Utils.uuid.getUUID(), name: defaultName, - application: new standata_1.ApplicationRegistry().getDefaultApplication(), - // TODO: confirm if `functional` is required field. If not, update ESSE schema + application, // `Model.defaultConfig` from @mat3ra/mode may omit `functional`; ESSE subworkflow schema requires it once schemas are registered. model: { ...mode_1.Model.defaultConfig, functional: "pbe" }, properties: [], diff --git a/dist/js/Workflow.d.ts b/dist/js/Workflow.d.ts index ff65a51c..be5fbca9 100644 --- a/dist/js/Workflow.d.ts +++ b/dist/js/Workflow.d.ts @@ -4,7 +4,7 @@ import { type HasDescription } from "@mat3ra/code/dist/js/entity/mixins/HasDescr import { type HashedEntity } from "@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"; import { Taggable } from "@mat3ra/code/dist/js/entity/mixins/TaggableMixin"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ApplicationSchema, WorkflowSchema } from "@mat3ra/esse/dist/js/types"; +import type { ApplicationSchema } from "@mat3ra/esse/dist/js/types"; import { ComputedEntityMixin } from "@mat3ra/ide/dist/js/compute"; import type { Material } from "@mat3ra/made"; import type { MetaPropertyHolder } from "@mat3ra/prode"; @@ -17,6 +17,7 @@ import { type WorkflowSchemaMixin } from "./generated/WorkflowSchemaMixin"; import Subworkflow from "./Subworkflow"; import { MapUnit } from "./units"; import { type AnyWorkflowUnit } from "./units/factory"; +import type { WorkflowSchema } from "./workflows/types"; interface Workflow extends Defaultable, NamedInMemoryEntity, WorkflowSchemaMixin, Taggable, HashedEntity, ComputedEntityMixin, HasDescription { compute: WorkflowSchema["compute"]; } @@ -27,6 +28,7 @@ declare class Workflow extends InMemoryEntity implements WorkflowSchema { static readonly defaultConfig: WorkflowSchema; _json: WorkflowSchema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; + static repair(workflowData: WorkflowSchema): WorkflowSchema; subworkflowInstances: Subworkflow[]; unitInstances: AnyWorkflowUnit[]; workflowInstances: Workflow[]; diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index 70d39f92..985bc2b3 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -24,6 +24,19 @@ class Workflow extends entity_1.InMemoryEntity { static get jsonSchema() { return JSONSchemasInterface_1.default.getSchemaById("workflow"); } + static repair(workflowData) { + const subworkflows = workflowData.subworkflows.map((subworkflow) => { + return Subworkflow_1.default.repair(subworkflow); + }); + const workflows = workflowData.workflows.map((nested) => { + return Workflow.repair(nested); + }); + return { + ...workflowData, + subworkflows, + workflows, + }; + } setTotalRepetitions(totalRepetition) { this.totalRepetitions = totalRepetition; } diff --git a/dist/js/repair/createErrorUnitData.d.ts b/dist/js/repair/createErrorUnitData.d.ts new file mode 100644 index 00000000..64ac2f7a --- /dev/null +++ b/dist/js/repair/createErrorUnitData.d.ts @@ -0,0 +1,3 @@ +import type { ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { AnySubworkflowUnitSchema } from "../units/factory"; +export declare function createErrorUnitData(unitData: AnySubworkflowUnitSchema | Record, reason: string): ErrorUnitSchema; diff --git a/dist/js/repair/createErrorUnitData.js b/dist/js/repair/createErrorUnitData.js new file mode 100644 index 00000000..43f71bfe --- /dev/null +++ b/dist/js/repair/createErrorUnitData.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createErrorUnitData = createErrorUnitData; +const utils_1 = require("@mat3ra/utils"); +const enums_1 = require("../enums"); +function createErrorUnitData(unitData, reason) { + const original = structuredClone(unitData); + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: typeof original.name === "string" ? original.name : enums_1.UnitType.error, + type: enums_1.UnitType.error, + status: enums_1.UnitStatus.error, + flowchartId: typeof original.flowchartId === "string" ? original.flowchartId : utils_1.Utils.uuid.getUUID(), + originalUnit: original, + reason, + ...(typeof original._id === "string" ? { _id: original._id } : {}), + ...(typeof original.next === "string" ? { next: original.next } : {}), + ...(original.head === true ? { head: true } : {}), + ...(Array.isArray(original.statusTrack) ? { statusTrack: original.statusTrack } : {}), + ...(Array.isArray(original.tags) ? { tags: original.tags } : {}), + }; +} diff --git a/dist/js/repair/formatRepairReason.d.ts b/dist/js/repair/formatRepairReason.d.ts new file mode 100644 index 00000000..c0164fcf --- /dev/null +++ b/dist/js/repair/formatRepairReason.d.ts @@ -0,0 +1 @@ +export declare function formatRepairReason(error: unknown): string; diff --git a/dist/js/repair/formatRepairReason.js b/dist/js/repair/formatRepairReason.js new file mode 100644 index 00000000..1e840e65 --- /dev/null +++ b/dist/js/repair/formatRepairReason.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.formatRepairReason = formatRepairReason; +function formatRepairReason(error) { + var _a; + if (error && typeof error === "object") { + const entityError = error; + if (((_a = entityError.details) === null || _a === void 0 ? void 0 : _a.error) !== undefined) { + return JSON.stringify(entityError.details.error); + } + if (typeof entityError.message === "string" && entityError.message.length > 0) { + return entityError.message; + } + if (typeof entityError.code === "string" && entityError.code.length > 0) { + return entityError.code; + } + } + if (error instanceof Error) { + return error.message; + } + return String(error); +} diff --git a/dist/js/repair/types.d.ts b/dist/js/repair/types.d.ts new file mode 100644 index 00000000..3706b67f --- /dev/null +++ b/dist/js/repair/types.d.ts @@ -0,0 +1,16 @@ +import type { SubworkflowSchema, WorkflowSchema } from "@mat3ra/esse/dist/js/types"; +export type SubworkflowUnitRepairRecord = { + subworkflowId: string; + flowchartId: string; + reason: string; +}; +export type SubworkflowRepairResult = { + document: SubworkflowSchema; + changed: boolean; + repairs: SubworkflowUnitRepairRecord[]; +}; +export type WorkflowRepairResult = { + document: WorkflowSchema; + changed: boolean; + repairs: SubworkflowUnitRepairRecord[]; +}; diff --git a/dist/js/repair/types.js b/dist/js/repair/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/dist/js/repair/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/js/units/ExecutionUnit.d.ts b/dist/js/units/ExecutionUnit.d.ts index 985a5542..fb28cb01 100644 --- a/dist/js/units/ExecutionUnit.d.ts +++ b/dist/js/units/ExecutionUnit.d.ts @@ -1,6 +1,6 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ErrorUnitSchema, ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; import { type AnyContextProvider, type ExternalContext } from "../context/providers"; import type ConvergenceParameter from "../convergence/ConvergenceParameter"; import { type ExecutionUnitSchemaMixin } from "../generated/ExecutionUnitSchemaMixin"; @@ -23,6 +23,7 @@ declare class ExecutionUnit extends ExecutionUnit_base implements Schema { _json: Schema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; constructor(config: ExecutionUnitConfig); + static repair(unitData: Partial): ExecutionUnitSchema | ErrorUnitSchema; setApplication({ application, executable, flavor, executableName, flavorName, }: SetApplicationProps): void; setExecutable({ executableName, flavorName }: SetExecutableProps): void; setFlavor(flavorName?: string): void; diff --git a/dist/js/units/ExecutionUnit.js b/dist/js/units/ExecutionUnit.js index 4cabca63..afe701aa 100644 --- a/dist/js/units/ExecutionUnit.js +++ b/dist/js/units/ExecutionUnit.js @@ -34,6 +34,28 @@ class ExecutionUnit extends BaseUnit_1.default { this.setApplication(config); this.name = this.name || this.flavor.name || ""; } + static repair(unitData) { + var _a, _b, _c, _d; + try { + return new ExecutionUnit(unitData).toJSON(); + } + catch (error) { + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, + type: enums_1.UnitType.error, + status: enums_1.UnitStatus.error, + flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), + reason: JSON.stringify(error), + next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", + head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, + originalUnit: unitData, + }; + } + } setApplication({ application, executable, flavor, executableName, flavorName, }) { var _a, _b; const currentExecutable = this.prop("executable"); diff --git a/dist/js/units/factory.d.ts b/dist/js/units/factory.d.ts index 3022c1e4..58f90555 100644 --- a/dist/js/units/factory.d.ts +++ b/dist/js/units/factory.d.ts @@ -1,4 +1,4 @@ -import type { AssertionUnitSchema, AssignmentUnitSchema, ConditionUnitSchema, DataIOUnitSchema, ErrorUnitSchema, ExecutionUnitSchema, MapUnitSchema, ReduceUnitSchema, SubworkflowUnitSchema, WorkflowUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ApplicationSchema, AssertionUnitSchema, AssignmentUnitSchema, ConditionUnitSchema, DataIOUnitSchema, ErrorUnitSchema, ExecutionUnitSchema, MapUnitSchema, ReduceUnitSchema, SubworkflowUnitSchema, WorkflowUnitSchema } from "@mat3ra/esse/dist/js/types"; import AssertionUnit, { type AssertionUnitConfig } from "./AssertionUnit"; import AssignmentUnit, { type AssignmentUnitConfig } from "./AssignmentUnit"; import ConditionUnit, { type ConditionUnitConfig } from "./ConditionUnit"; @@ -25,8 +25,11 @@ export declare class UnitFactory { * Create a new subworkflow unit with fresh `flowchartId` and constructor defaults. * For execution units, pass the subworkflow (or parent) `application` JSON. */ - static createDefaultSubworkflowUnit(type: "execution", application: ExecutionUnitSchema["application"]): AnySubworkflowUnit; - static createDefaultSubworkflowUnit(type: "assignment" | "condition" | "io" | "assertion"): AnySubworkflowUnit; + static createDefaultSubworkflowUnit(type: "execution", application: ApplicationSchema): ExecutionUnit; + static createDefaultSubworkflowUnit(type: "assignment"): AssignmentUnit; + static createDefaultSubworkflowUnit(type: "condition"): ConditionUnit; + static createDefaultSubworkflowUnit(type: "io"): IOUnit; + static createDefaultSubworkflowUnit(type: "assertion"): AssertionUnit; static createInWorkflow(config: WorkflowUnitSchema): AnyWorkflowUnit; static createInSubworkflow(config: ExcutionConfig | AssignmentConfig | ConditionConfig | IOConfig | AssertionConfig | ErrorConfig): AnySubworkflowUnit; } diff --git a/dist/js/workflows/default.d.ts b/dist/js/workflows/default.d.ts index 4beac8a8..b48f7c3d 100644 --- a/dist/js/workflows/default.d.ts +++ b/dist/js/workflows/default.d.ts @@ -1,3 +1,3 @@ -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; +import type { WorkflowSchema } from "./types"; declare const defaultWorkflowConfig: WorkflowSchema; export default defaultWorkflowConfig; diff --git a/dist/js/workflows/types.d.ts b/dist/js/workflows/types.d.ts new file mode 100644 index 00000000..ae3b4b97 --- /dev/null +++ b/dist/js/workflows/types.d.ts @@ -0,0 +1,4 @@ +import type { WorkflowSchema as EsseWorkflowSchema } from "@mat3ra/esse/dist/js/types"; +export type WorkflowSchema = EsseWorkflowSchema & { + workflows: WorkflowSchema[]; +}; diff --git a/dist/js/workflows/types.js b/dist/js/workflows/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/dist/js/workflows/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/package-lock.json b/package-lock.json index f152a8f0..e4415976 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/906c4bc2a5b6c9cd90472b1f65aeb3568d9c4d9c.tar.gz", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/52c9a1aec1580d7539e9d8425dacd50c0f9b4a73.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", @@ -2686,8 +2686,8 @@ }, "node_modules/@mat3ra/esse": { "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/esse/archive/906c4bc2a5b6c9cd90472b1f65aeb3568d9c4d9c.tar.gz", - "integrity": "sha512-VmpeGiPiIFj/BE4x0eHSSAFmOsr8UzcVOFLu2iiXRiuV/e7xRqCbAMtvc1d1SNWPcPYtSDUBVDzE4XI9RUNe/g==", + "resolved": "https://github.com/Exabyte-io/esse/archive/52c9a1aec1580d7539e9d8425dacd50c0f9b4a73.tar.gz", + "integrity": "sha512-l6lPUMif5D3FqmhOKPlDbJCVhVSDEjr7gLeCiWlNUAqHCvDuR1d+czdKhSP9hL4m8WHfLVIrhJ5ViSMvuf4ZoA==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index de6b3b75..4aed057a 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/906c4bc2a5b6c9cd90472b1f65aeb3568d9c4d9c.tar.gz", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/52c9a1aec1580d7539e9d8425dacd50c0f9b4a73.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", diff --git a/src/js/Subworkflow.ts b/src/js/Subworkflow.ts index 8183dd8e..452074b6 100644 --- a/src/js/Subworkflow.ts +++ b/src/js/Subworkflow.ts @@ -34,7 +34,13 @@ import { type SubworkflowSchemaMixin, subworkflowSchemaMixin, } from "./generated/SubworkflowSchemaMixin"; -import { AssignmentUnit, ConditionUnit, SubworkflowUnit, UnitFactory } from "./units"; +import { + AssignmentUnit, + ConditionUnit, + ExecutionUnit, + SubworkflowUnit, + UnitFactory, +} from "./units"; import type { AnySubworkflowUnit } from "./units/factory"; type ConvergenceConfig = { @@ -86,6 +92,14 @@ class Subworkflow extends InMemoryEntity implements SubworkflowSchema { return JSONSchemasInterface.getSchemaById("workflow/subworkflow"); } + static repair(subworkflowData: SubworkflowSchema): SubworkflowSchema { + const units = subworkflowData.units.map((unit) => { + return unit.type === UnitType.execution ? ExecutionUnit.repair(unit) : unit; + }); + + return { ...subworkflowData, units }; + } + constructor(config: SubworkflowSchema, _ModelFactory = ModelFactory) { super(config); this.ModelFactory = _ModelFactory; @@ -100,13 +114,18 @@ class Subworkflow extends InMemoryEntity implements SubworkflowSchema { static get defaultConfig() { const defaultName = "New Subworkflow"; + const application = new ApplicationRegistry().getDefaultApplication(); + + if (!application) { + throw new Error("No default application found"); + } + return { _id: Utils.uuid.getUUID(), name: defaultName, - application: new ApplicationRegistry().getDefaultApplication(), - // TODO: confirm if `functional` is required field. If not, update ESSE schema + application, // `Model.defaultConfig` from @mat3ra/mode may omit `functional`; ESSE subworkflow schema requires it once schemas are registered. - model: { ...Model.defaultConfig, functional: "pbe" }, + model: { ...Model.defaultConfig, functional: "pbe" as const }, properties: [], units: [], }; diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index 7fa67694..e5658eed 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -15,11 +15,7 @@ import { namedEntityMixin } from "@mat3ra/code/dist/js/entity/mixins/NamedEntity import { Taggable, taggableMixin } from "@mat3ra/code/dist/js/entity/mixins/TaggableMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { - ApplicationSchema, - SubworkflowSchema, - WorkflowSchema, -} from "@mat3ra/esse/dist/js/types"; +import type { ApplicationSchema, SubworkflowSchema } from "@mat3ra/esse/dist/js/types"; import { ComputedEntityMixin, computedEntityMixin } from "@mat3ra/ide/dist/js/compute"; import type { Material } from "@mat3ra/made"; import type { MetaPropertyHolder } from "@mat3ra/prode"; @@ -45,6 +41,7 @@ import { getUsedModels, } from "./utils/workflow"; import defaultWorkflowConfig from "./workflows/default"; +import type { WorkflowSchema } from "./workflows/types"; interface Workflow extends Defaultable, @@ -75,6 +72,22 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { return JSONSchemasInterface.getSchemaById("workflow"); } + static repair(workflowData: WorkflowSchema): WorkflowSchema { + const subworkflows = workflowData.subworkflows.map((subworkflow) => { + return Subworkflow.repair(subworkflow); + }); + + const workflows = workflowData.workflows.map((nested) => { + return Workflow.repair(nested as WorkflowSchema); + }); + + return { + ...workflowData, + subworkflows, + workflows, + }; + } + subworkflowInstances: Subworkflow[]; unitInstances!: AnyWorkflowUnit[]; diff --git a/src/js/units/ExecutionUnit.ts b/src/js/units/ExecutionUnit.ts index 009d6786..cffe4c47 100644 --- a/src/js/units/ExecutionUnit.ts +++ b/src/js/units/ExecutionUnit.ts @@ -1,7 +1,11 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ExecutionUnitInputItemSchema, ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { + ErrorUnitSchema, + ExecutionUnitInputItemSchema, + ExecutionUnitSchema, +} from "@mat3ra/esse/dist/js/types"; import { ApplicationRegistry, applicationVersionSatisfiesSupportedRange } from "@mat3ra/standata"; import { Utils } from "@mat3ra/utils"; @@ -11,7 +15,7 @@ import { createProvider, } from "../context/providers"; import type ConvergenceParameter from "../convergence/ConvergenceParameter"; -import { UnitType } from "../enums"; +import { UnitStatus, UnitType } from "../enums"; import { type ExecutionUnitSchemaMixin, executionUnitSchemaMixin, @@ -68,6 +72,27 @@ class ExecutionUnit extends (BaseUnit as Base) implements Schema { this.name = this.name || this.flavor.name || ""; } + static repair(unitData: Partial): ExecutionUnitSchema | ErrorUnitSchema { + try { + return new ExecutionUnit(unitData as Schema).toJSON(); + } catch (error: unknown) { + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: unitData.name ?? UnitType.error, + type: UnitType.error, + status: UnitStatus.error, + flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), + reason: JSON.stringify(error), + next: unitData.next ?? "", + head: unitData.head ?? false, + originalUnit: unitData, + }; + } + } + setApplication({ application, executable, diff --git a/src/js/units/factory.ts b/src/js/units/factory.ts index f6ff91fa..0e70399b 100644 --- a/src/js/units/factory.ts +++ b/src/js/units/factory.ts @@ -1,4 +1,5 @@ import type { + ApplicationSchema, AssertionUnitSchema, AssignmentUnitSchema, ConditionUnitSchema, @@ -64,16 +65,20 @@ export class UnitFactory { */ static createDefaultSubworkflowUnit( type: "execution", - application: ExecutionUnitSchema["application"], - ): AnySubworkflowUnit; + application: ApplicationSchema, + ): ExecutionUnit; - static createDefaultSubworkflowUnit( - type: "assignment" | "condition" | "io" | "assertion", - ): AnySubworkflowUnit; + static createDefaultSubworkflowUnit(type: "assignment"): AssignmentUnit; + + static createDefaultSubworkflowUnit(type: "condition"): ConditionUnit; + + static createDefaultSubworkflowUnit(type: "io"): IOUnit; + + static createDefaultSubworkflowUnit(type: "assertion"): AssertionUnit; static createDefaultSubworkflowUnit( type: DefaultSubworkflowUnitType, - application?: ExecutionUnitSchema["application"], + application?: ApplicationSchema, ): AnySubworkflowUnit { if (type === "execution") { if (application === undefined) { diff --git a/src/js/workflows/default.ts b/src/js/workflows/default.ts index 8336a497..7b739599 100644 --- a/src/js/workflows/default.ts +++ b/src/js/workflows/default.ts @@ -1,4 +1,4 @@ -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; +import type { WorkflowSchema } from "./types"; const defaultWorkflowConfig: WorkflowSchema = { name: "New Workflow", diff --git a/src/js/workflows/types.ts b/src/js/workflows/types.ts new file mode 100644 index 00000000..17a17bc9 --- /dev/null +++ b/src/js/workflows/types.ts @@ -0,0 +1,5 @@ +import type { WorkflowSchema as EsseWorkflowSchema } from "@mat3ra/esse/dist/js/types"; + +export type WorkflowSchema = EsseWorkflowSchema & { + workflows: WorkflowSchema[]; +}; diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index df6775f7..3f3adb4e 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -8,7 +8,6 @@ import { } from "@mat3ra/code/dist/js/entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; import { Material } from "@mat3ra/made"; import { ApplicationRegistry, WorkflowStandata } from "@mat3ra/standata"; import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; @@ -18,6 +17,7 @@ import type { WorkflowRenderContext } from "src/js/Workflow"; import { Subworkflow, Workflow } from "../../src/js"; import { UnitType } from "../../src/js/enums"; +import type { WorkflowSchema } from "../../src/js/workflows/types"; import workflowHashes from "../fixtures/workflow_hashes.json"; interface OrderedMaterial extends OrderedInMemoryEntityInSet, InMemoryEntityInSet {} @@ -280,8 +280,10 @@ describe("Workflow", () => { fixtureFile, ) as unknown as WorkflowSchema[]; const workflow = workflows.find((w) => w.name === bandGapWorkflowName); - expect(workflow).to.exist; - const wf = new Workflow(workflow as WorkflowSchema); + if (!workflow) { + throw new Error(`Workflow ${bandGapWorkflowName} not found`); + } + const wf = new Workflow(workflow); const expectedHash = workflowHashes.espresso[fixtureFile].hash; if (!expectedHash) { // eslint-disable-next-line no-console diff --git a/tests/js/executionUnit.contextProviders.test.ts b/tests/js/executionUnit.contextProviders.test.ts index 652278ed..48e09b58 100644 --- a/tests/js/executionUnit.contextProviders.test.ts +++ b/tests/js/executionUnit.contextProviders.test.ts @@ -8,13 +8,13 @@ import { } from "@mat3ra/code/dist/js/entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; import { Material } from "@mat3ra/made"; import { ApplicationRegistry, WorkflowStandata } from "@mat3ra/standata"; import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; import { expect } from "chai"; import type { JSONSchema7 } from "json-schema"; import type { WorkflowRenderContext } from "src/js/Workflow"; +import type { WorkflowSchema } from "src/js/workflows/types"; import { ExecutionUnit, Workflow } from "../../src/js"; import KGridFormDataManager from "../../src/js/context/providers/PointsGrid/KGridFormDataManager"; @@ -41,7 +41,7 @@ describe("ExecutionUnit contextProvidersInstances + render()", () => { }); it("persists in-memory provider edits when render() runs again (Important settings path)", () => { - const standataWorkflows = new WorkflowStandata().getAll(); + const standataWorkflows = new WorkflowStandata().getAll() as unknown as WorkflowSchema[]; expect(standataWorkflows.length).to.be.above(0); const material = OrderedMaterial.createDefault(); @@ -59,7 +59,7 @@ describe("ExecutionUnit contextProvidersInstances + render()", () => { // eslint-disable-next-line no-restricted-syntax for (const standataJson of standataWorkflows) { - const w = new Workflow(standataJson as unknown as WorkflowSchema); + const w = new Workflow(standataJson); w.render(context); // eslint-disable-next-line no-restricted-syntax for (const sub of w.subworkflowInstances) { @@ -81,6 +81,10 @@ describe("ExecutionUnit contextProvidersInstances + render()", () => { if (executionUnit) break; } + if (!workflow) { + throw new Error("Workflow not found"); + } + expect( workflow, "expected a standata workflow with boundaryConditions on an execution unit", @@ -91,13 +95,17 @@ describe("ExecutionUnit contextProvidersInstances + render()", () => { const provider = unit.contextProvidersInstances.find((p) => { return p.name === "boundaryConditions"; }); + + if (!provider) { + throw new Error("Provider not found"); + } // eslint-disable-next-line no-unused-expressions expect(provider).to.be.ok; const distinctiveElectricField = 9.87654321; - const priorData = provider!.getData(); - provider!.setIsEdited(true); - provider!.setData({ + const priorData = provider.getData(); + provider.setIsEdited(true); + provider.setData({ ...priorData, electricField: distinctiveElectricField, }); @@ -106,7 +114,7 @@ describe("ExecutionUnit contextProvidersInstances + render()", () => { // Same workflow + same unit instances as the designer: persist then `onContextChanged` → `workflow.render()`. // Without `savePersistentContext()` before this, the next render rebuilds providers from stale // `this.context` and this assertion fails. - workflow!.render(context); + workflow.render(context); const persisted = unit.context.find((c) => c.name === "boundaryConditions"); expect(persisted?.data).to.include({ electricField: distinctiveElectricField }); diff --git a/tests/js/kpath.vaspBands.test.ts b/tests/js/kpath.vaspBands.test.ts index dafcf9e2..3c4675ae 100644 --- a/tests/js/kpath.vaspBands.test.ts +++ b/tests/js/kpath.vaspBands.test.ts @@ -8,13 +8,13 @@ import { } from "@mat3ra/code/dist/js/entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; import { Material } from "@mat3ra/made"; import { ApplicationRegistry, WorkflowStandata } from "@mat3ra/standata"; import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; import { expect } from "chai"; import type { JSONSchema7 } from "json-schema"; import type { WorkflowRenderContext } from "src/js/Workflow"; +import type { WorkflowSchema } from "src/js/workflows/types"; import { ExecutionUnit, Subworkflow, Workflow } from "../../src/js"; import { assertNotNull } from "./assertNotNull"; @@ -49,13 +49,13 @@ function findVaspBandsUnit(workflow: Workflow): ExecutionUnit | undefined { } function findBandStructureVaspJson(): WorkflowSchema { + const standataWorkflows = new WorkflowStandata().getAll() as unknown as WorkflowSchema[]; // eslint-disable-next-line no-restricted-syntax - for (const workflow of new WorkflowStandata().getAll()) { + for (const workflow of standataWorkflows) { if (workflow.name === "Band Structure") { - const candidate = workflow as unknown as WorkflowSchema; - const probe = new Workflow(candidate); + const probe = new Workflow(workflow); if (findVaspBandsUnit(probe)) { - return candidate; + return workflow; } } } diff --git a/tests/js/repair.test.ts b/tests/js/repair.test.ts new file mode 100644 index 00000000..f0fbd245 --- /dev/null +++ b/tests/js/repair.test.ts @@ -0,0 +1,122 @@ +import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; +import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; +import type { + ErrorUnitSchema, + ExecutionUnitSchema, + SubworkflowSchema, +} from "@mat3ra/esse/dist/js/types"; +import { ApplicationRegistry } from "@mat3ra/standata"; +import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; +import { expect } from "chai"; +import type { JSONSchema7 } from "json-schema"; +import type { AnySubworkflowUnitSchema } from "src/js/units/factory"; + +import { ExecutionUnit, Subworkflow, UnitFactory, Workflow } from "../../src/js"; +import { UnitType } from "../../src/js/enums"; + +function invalidExecutionUnit(flowchartId: string) { + return { + type: UnitType.execution, + name: "exec", + flowchartId, + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + input: [], + context: [], + }; +} + +describe("static repair", () => { + let defaultApplication: ExecutionUnitSchema["application"]; + + before(() => { + JSONSchemasInterface.setSchemas(esseSchemas as JSONSchema7[]); + }); + + beforeEach(() => { + ApplicationRegistry.setDriver(new StandataDriver()); + const app = new ApplicationRegistry().getDefaultApplication(); + if (!app) { + throw new Error("ApplicationRegistry.getDefaultApplication() returned no application"); + } + defaultApplication = app; + }); + + describe("ExecutionUnit.repair", () => { + it("converts structurally invalid execution unit to error unit data", () => { + const invalid = invalidExecutionUnit("fc-exec"); + + const repaired = ExecutionUnit.repair(invalid as never); + + expect(repaired.type).to.equal(UnitType.error); + expect((repaired as ErrorUnitSchema).originalUnit).to.deep.equal(invalid); + }); + + it("returns valid execution unit data unchanged", () => { + const unit = UnitFactory.createDefaultSubworkflowUnit( + "execution", + defaultApplication, + ).toJSON(); + + const repaired = ExecutionUnit.repair(unit); + + expect(repaired).to.deep.equal(unit); + }); + }); + + describe("Subworkflow.repair", () => { + it("repairs only invalid execution units", () => { + const validUnit = UnitFactory.createDefaultSubworkflowUnit("assignment").toJSON(); + const invalidExecution = invalidExecutionUnit("fc-bad"); + + const subworkflow = Subworkflow.defaultConfig; + const subworkflowData: SubworkflowSchema = { + ...subworkflow, + units: [validUnit, invalidExecution as unknown as AnySubworkflowUnitSchema], + }; + + const result = Subworkflow.repair(subworkflowData); + + expect(result.units[0]).to.deep.equal(validUnit); + expect(result.units[1].type).to.equal(UnitType.error); + }); + }); + + describe("Workflow.repair", () => { + it("repairs invalid execution units in subworkflows and nested workflows", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const invalidExecution = invalidExecutionUnit("fc-nested"); + + workflowConfig.subworkflows[0].units = [invalidExecution as never]; + + const nestedSubworkflow = structuredClone(workflowConfig.subworkflows[0]); + nestedSubworkflow._id = "nested-subworkflow-id"; + nestedSubworkflow.units = [invalidExecution as never]; + + workflowConfig.workflows = [ + { + ...structuredClone(workflowConfig), + _id: "nested-workflow-id", + subworkflows: [nestedSubworkflow], + workflows: [], + }, + ]; + + const result = Workflow.repair(workflowConfig); + + expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); + expect(result.workflows[0].subworkflows[0].units[0].type).to.equal(UnitType.error); + }); + + it("allows hydration after repair for converted execution units", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + workflowConfig.subworkflows[0].units = [invalidExecutionUnit("fc-hydrate") as never]; + + const document = Workflow.repair(workflowConfig); + + expect(() => new Workflow(document)).to.not.throw(); + }); + }); +}); diff --git a/tests/js/subworkflow.standata.integration.test.ts b/tests/js/subworkflow.standata.integration.test.ts index 81e5a1c9..3cd8a540 100644 --- a/tests/js/subworkflow.standata.integration.test.ts +++ b/tests/js/subworkflow.standata.integration.test.ts @@ -8,7 +8,6 @@ import { } from "@mat3ra/code/dist/js/entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; import { Material } from "@mat3ra/made"; import { ApplicationRegistry, WorkflowStandata } from "@mat3ra/standata"; import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; @@ -19,6 +18,7 @@ import { Workflow } from "../../src/js"; import { UnitType } from "../../src/js/enums"; import { AssignmentUnit, ConditionUnit } from "../../src/js/units"; import type { WorkflowRenderContext } from "../../src/js/Workflow"; +import type { WorkflowSchema } from "../../src/js/workflows/types"; interface OrderedMaterial extends OrderedInMemoryEntityInSet, InMemoryEntityInSet {} @@ -40,11 +40,11 @@ describe("Subworkflow", () => { }); it("addConvergence on first subworkflow then workflow.render for every standata workflow (when applicable)", () => { - const standataWorkflows = new WorkflowStandata().getAll(); + const standataWorkflows = new WorkflowStandata().getAll() as unknown as WorkflowSchema[]; expect(standataWorkflows.length).to.be.above(0); const workflows = standataWorkflows.map((standataJson) => { - return new Workflow(structuredClone(standataJson) as unknown as WorkflowSchema); + return new Workflow(structuredClone(standataJson)); }); const material = OrderedMaterial.createDefault(); From a685ac1945704119ec9f8c193a5aa9736f7b1e29 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 8 Jun 2026 18:45:47 +0300 Subject: [PATCH 03/12] fix: drop invalid subworkflows in Workflow.repair and surface error units Convert matching workflow units when a subworkflow fails schema validation after repair, support error units in the workflow factory, and consolidate repair coverage in Workflow.test.ts. Co-authored-by: Cursor --- .gitignore | 1 + dist/js/Workflow.js | 27 +++++++- dist/js/units/factory.d.ts | 4 +- dist/js/units/factory.js | 2 + mat3ra-wode-0.0.0.tgz | Bin 100381 -> 0 bytes package-lock.json | 6 +- package.json | 2 +- src/js/Workflow.ts | 36 +++++++++- src/js/units/factory.ts | 10 ++- tests/js/Workflow.test.ts | 134 ++++++++++++++++++++++++++++++++++++- tests/js/repair.test.ts | 122 --------------------------------- 11 files changed, 210 insertions(+), 134 deletions(-) delete mode 100644 mat3ra-wode-0.0.0.tgz delete mode 100644 tests/js/repair.test.ts diff --git a/.gitignore b/.gitignore index c8e1d686..804427dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ +mat3ra-wode-0.0.0.tgz node_modules/ .eslintcache .nyc_output/ diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index 985bc2b3..83b07bcf 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -28,13 +28,38 @@ class Workflow extends entity_1.InMemoryEntity { const subworkflows = workflowData.subworkflows.map((subworkflow) => { return Subworkflow_1.default.repair(subworkflow); }); + const invalidSubworkflows = subworkflows.filter((subworkflow) => { + return !new Subworkflow_1.default(subworkflow).isValid(); + }); + const units = workflowData.units.map((unit) => { + const subworkflow = invalidSubworkflows.find((subworkflow) => subworkflow._id === unit._id); + if (subworkflow) { + return { + type: enums_1.UnitType.error, + _id: unit._id, + name: unit.name || "error", + flowchartId: unit.flowchartId, + originalUnit: unit, + preProcessors: unit.preProcessors || [], + postProcessors: unit.postProcessors || [], + monitors: unit.monitors || [], + results: unit.results || [], + reason: "Invalid subworkflow", + }; + } + return unit; + }); + const validSubworkflows = subworkflows.filter((subworkflow) => { + return !invalidSubworkflows.map(({ _id }) => _id).includes(subworkflow._id); + }); const workflows = workflowData.workflows.map((nested) => { return Workflow.repair(nested); }); return { ...workflowData, - subworkflows, + subworkflows: validSubworkflows, workflows, + units, }; } setTotalRepetitions(totalRepetition) { diff --git a/dist/js/units/factory.d.ts b/dist/js/units/factory.d.ts index 58f90555..3d2fb51c 100644 --- a/dist/js/units/factory.d.ts +++ b/dist/js/units/factory.d.ts @@ -8,8 +8,8 @@ import IOUnit, { type IOUnitConfig } from "./IOUnit"; import MapUnit from "./MapUnit"; import ReduceUnit from "./ReduceUnit"; import SubworkflowUnit from "./SubworkflowUnit"; -export type AnyWorkflowUnit = MapUnit | SubworkflowUnit | ReduceUnit; -export type AnyWorkflowUnitSchema = MapUnitSchema | SubworkflowUnitSchema | ReduceUnitSchema; +export type AnyWorkflowUnit = MapUnit | SubworkflowUnit | ReduceUnit | ErrorUnit; +export type AnyWorkflowUnitSchema = MapUnitSchema | SubworkflowUnitSchema | ReduceUnitSchema | ErrorUnitSchema; export type AnySubworkflowUnit = ExecutionUnit | AssignmentUnit | ConditionUnit | IOUnit | AssertionUnit | ErrorUnit; export type AnySubworkflowUnitSchema = ExecutionUnitSchema | AssertionUnitSchema | AssignmentUnitSchema | ConditionUnitSchema | DataIOUnitSchema | ErrorUnitSchema; type ExcutionConfig = ExecutionUnitConfig & Pick; diff --git a/dist/js/units/factory.js b/dist/js/units/factory.js index e4145e2b..1c8b390a 100644 --- a/dist/js/units/factory.js +++ b/dist/js/units/factory.js @@ -48,6 +48,8 @@ class UnitFactory { return new SubworkflowUnit_1.default(config); case enums_1.UnitType.reduce: return new ReduceUnit_1.default(config); + case enums_1.UnitType.error: + return new ErrorUnit_1.default(config); default: throw new Error(`Unknown unit type: ${config.type}`); } diff --git a/mat3ra-wode-0.0.0.tgz b/mat3ra-wode-0.0.0.tgz deleted file mode 100644 index 186421952770392feb75e35b301f66a3ed81c302..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100381 zcmYhCQ*>ToyR~E6Mq?*!lE${3#&*)!c+=Rn&Bkh)#%gTaw)L*v@B7EU$6n((c}~_C z>*QYZo^xL0(FhR#d7yyv&NCNc=~;T7?gt!;pZ(BYJwu^5E#zK2WKl&!B=RK+YPWvj z;gH-jumvmy#75e|IEqxe?<;i6A5CoaY>jO7Q%-s2RA;jWOP6pmBPA$<0~yCvqocnq zEG!Q!4$*~Psn&06-g~Qs^gd~d#Y_Mckdf>y*X#F9@1cLp6|+-#Pr-OV`o?9-K=ICC#J5PCP&wrRu< zN9uIDQLEYBEN!4E<2gCDcYrPgJRnPC+D9p`z5;ikFwM5;OzoS20AZW9K70;iP3Q@921ETNV{uGP$hnZ=Hz zKKxj-r_7-A3DhUd&H0)VC%!8iQD{)ok|6Kd*orLWgm)h8@L62p_-|H`TgcpAwv569 zlLDM9kNjT9{GACG5r2Lx`1lA!7Rq3AfeB?WJo84ckj{TDpATGWd8&5<`JSzYKmUE8 zFt8L5^!nk1H2kdT5pm{3Hto69;98jab^5Bi_?&a8+?hg2J!sCmPe^pnhQy2a!@7Wc z8~L=5Ut{mSXt6jSkADj9iB>X(^Zo4p`PhwpNIjoKia{w14DrNotxaw&*b8u>W9!#_ zn4OkqM{f0n?1u+|>wBxX8f%?6^RbZlgAcq}UR%;M)h2PFr4W;5zK2ldJTsu_*3$A$ zrwjF}d=p@=qdDa$`7xz>Q^?7R6am9tyl*clds@B&5$hBcK;t}6UpY3PT-WZu3Cl_0 z^Yi}T!bGKRV_;->hq|k9p!@(i$2f#{NqRVI9Ns2p9^RP~McSp?o)!VNY8~pD?Y8_E z9p2yI#N3U^`gHe_+Xh71J6SoO<99KZ44Qg$_>2Ue2Hat47RLM`)eK#EW8E7ZX&dwf zV`#e=uFk7XQ?Yl<%R=2SZlc#67pW0GGZd0e%%fz_Yd0==dGfF=u!OD5nFSr1BUDB$AC1+Z8ULLRO1_0i_`?xLoG($sbdY1L4Hi_cRS(qT6!Ts)=PkWyV@Q8g0gdu>|VRm zfG)8YWj^gxSP|ds@FWPD<9KP9eHj)i=-G+0D~)8ters-JMb+~$WKey>2mNv3YB!f` zoa2dZc~;19$+{2u(CDb(^SsE``DKx{P-YM1`P==GI|*DxY(U_aM`gkkNRx850xY6N zZA2^Qb-Xp<*LN%puFk}Sc$NWLBNA(y=wf?lWk$74DybPX1CWZ$3*W8slS@~AV7)l{ z`mQAazx6gAK7f=1;kQK-sDe&~REP`rE86Vhh96Y$wrh#%dyZ7#hy(w+< zJ*quF14|*aqUcx*q2zVDA*A8zpu$k5lW~PFZu5OkFXzheBTe$EC=wxX^R33zKm608;{7Q$vvL(-hP?`YVV^TAlPBv zB@JY}L<%3wlD!%McYs(rg#`LgKoS{TIz2Ug9;Ebvvd8oUf%M<*PxpwE(wJSMS6k#= zL2@g<1ku`Cf__a5{OPdWZPp{}DlfReh(k1(%EO3RQJ&Tx>0{P&V?&``UVLS~fhXs} zxF_zJxk*?Q#U3q9LTcm{R@(G^uKSuF4q1;_@AMExoAXxe7kDi$ZAa-$mlD3?a)zi! z-5fp1cFwhVyTDj+tE7`&6m|Q$dP?IJHkXiX(9+T;^v!)lTFzcUu`ZBSXy@!D0PneS zl*nZwp*cu@#HQA^pExWThwg#TreLFc?PctD(8Irp*YC6Gv#zm`#%Sm=Rc5hHSUSf)^s3lVWo`!^)wp0u@0BjVQWxM*kRZ zzZuNlwoZwgfjiY_uAI9Oh*uitsea;%EWa({ZZC_}3Kn)XKwH>I?2jny3%5Lx(pCJ8 zbFM6z$rDM1k`@^0$N_C$os_?zJ-oyt+Xrzq_t7eiRuUHGq00NQ5MO`f{aHxMA?w?x zf>ttOaY^RXFJewUNe<&aUD5}7m~h_oxHk_q&N76mk+;tfnXX(qe(6mh_&q;Z;LdL^__(j(ex7>p3Or|7J{St zgflrNmaf6b5>+&h%-$HVBALKcnF-Lb;NOr2+g`Y@y zY|b&#%sUcoFX`Vy0WpB;t{;O84A1>q(1cUBK+J6`QS$}Q?~bi)s2^L8(GM@6zN4+a z+X4gg7e-Qd`IG)Xk0JY-yXZ`vHT7ANbxb5$sZY3Q|E6=%J(rySujisVwH`jL44w+D zK;jORt+hNf%LL{n##Gnp!qxg?d7NX`Qjd!#MA;kXUJ1s+ zgV*{HMNs*yRfHIft{U5`Q&Qv72vG(D`PN}3IOj+Cnt?4$X6#&dBQSaD^3n$BuiP9g z^==+tlfs6{jG5dLopE}c`iu0WDug!&)$@^@xmvg0=@+W&wa=)~u*y{GIP#P~WHd06 zL)UXB`_(&cxP3`~i??_$Ba1<;tEgay8-1xGLqk+z(i*}RfKYqp8%Qn)zr=e*W(sNY zj!m}l!q_o)tJc!7KJHg9y)a*j#tR4;)Cu!f|4P1|T>)B<_z=Z@2&O&Vqdi5B-LTHC z_30FbFx~7f0EvGtKHjdbpZ_okOWg_kR9yM0=e#;yw%}>k;%Vo#_cpge zYp+521I6hI4jx<;E81;_SLi1d>>ogZx&4powjM6-bK4(d!`yByq&_GhzTX}@TK4Ie z1Fa31cf(HM<#5H}In!7iRr_lOZ?!1S+LAf)co<9dwnwsdb=^ll3G^Yd@V*O-*MzT zo(UcS<$8E_*d+q3OSfCPV7)O=z8)C)wpz%n=|#U)a8f;FpIPZ6(go~meXNWCl2&9H zY<@7s<#44ym>kl8YcFgYDVb11dPpgm_~Fiu7TM&spRc{kNt2WdpCCp0<(ijzmPWE! z|8r~~khK?#7@IB{fH-$U96>90q2nGc^sQVyXYmZ3!n^ZcR;DW2U|Gb8P4;~a?yJLu zj@kyCCjl+>LBDv%Xv8l99Ujz$P<~6vRS{4*O{mD!8h%B%?GTo31hzsGHLUJ_I~3wH zT!Mj%$aPl*r^c9(Q4a#UY`=908Iqp)MkNrb%kmg?lswhRxMjVo!~jJmK-F->YB-_1 zXT!sjy8|gP)v^Om%S-c%D^@Bq#^QV`oD9PCxQViM%v;1t=V6p*nOpmz%f5!mGk3Fi zui2*!6zC@37UF`TDB32`X1S29^Ho8)`1)~riFrUGQ20Tm+=fMSQud^E(NrwOUSv#Z zdR_gTdBeq*h2@7zvkhJr3!edoR5{CcqC>_41DF<4E1%P;(}#b8Fb^$DKIzC?)~|R1 zPOs9`MV5&a9kNz#pXk`}_7fWsYAo{Y00gRnG0McPpjBS2ej8oNe)-7-3_O#gtt)c) zIa+&lqwhs3J#1FE;Akl{v6S`CC$GkvNPGLmbACV7UpLyv)*U|5Y041Xy#W}~$!oe( z6D~MOCT})h^6>55^ET{qh#t3?dmB=$!#wUC)lA?Nx`7m$tVQGg~;@@zl?Hmio63!vXTcJW#1&U@6)9mlkT7=Xt$i}lU|pTsi+k?P&gP{wl3>W+Oh^%}%@+tm*$kglk1p)Jb0 z*}=-t3ee=5yeD$Oef|X^warvG)A2K!%}%CPvA zlbBdiUoe*g+|2YL4Bh!>iJEmD?A$WvAZQ#Y!k*&=`F-qH{H-^QyASOkR>(<<CQ+3aB6#bJfw^%6Dsj!2->l=9SuRRL zwExv%HU)0y<<@-R#^J+O$4IRxx&1t%<|JDZrk_n1Z*~4^%9!-TaAeURVn$8V_;2}= z($Sgnq%%vA_Q>A2ao?!Ne2Ss`L>9ua+wZK@h*EW#WmuyIcjhGXHc^I`*dW}GK{9o; zPMs`k^RBCC5>+cs&S-Hx=bQn3HsERydKjHJsZ|tTs<3Z2l!7{+RJr$Nsu7m40y` zkW+Geif2IP*B9(fOWVZCw!+O~#8+5{`73{%F5~_i8}TuM(H@M!3%PUG$BGR?G3R95 zuEm*}KW>*qcOR>=8BAoz@QM`9+IK3)s4_51)UNrda^Dtv)^?)sFUc=}2i6-TBt}X_ z{ru4A_d>f&=w{{qwWo3`>uqIPG)71(R0FlJV73{Ws&1c^z+CFX-+j!7DvdN-Q#~`O zcIGgiE=;s5yrm|oS zzSFAyR>twh<{(X^qmQay6ig9<-NuxCageV_Ou_DyP^~tLT-E43a5>#GN&z>%s)mXp zZPxA$In?A&w4fMnmmy>xe-uvA`@3g81JTBOS9yb7tSut2@Zc|AT;$#SVE+h90}=@i z5{XKbB5aj%bx5CBeEDmXTGaWtBgzM)ipUTG`)}$v=bmmKnUHl?L&KQM2%+0-&M5U0 z+8Q&*{X$U^I#B}1UXzc+wG*835tgEXoGLrSSK_Q^8zM9(an$8iTS^65la%jH(ru^+ zcJ+{KRS`7Y`MYi;@aASp*Kp&64wm`@L-)4_Kc>?Bi<5AqnWdVN?Hf)Q&vXrgw^IqZ z*%du3WvjY-nhdtor-F46!qMw=(32`_Dx(O^m^ z0IEEQ^nMS7bwlIw7{5>^OW#@PYn5c&XJd7wCtih)<%HvqxbQ}0W2aqZ7-Vd9!r~aX!w3WOW63D_PvDbe?w87hGbPW=ImPKHXyi}jn4hkYp z?|YF%^yWD1_#8Vk)$J8c$8z%x1Rxa9T!FGlzkrV(@7%$|lOkkrcBRatlqfa5z_)zy7Flanw#;ddI-$q}`Pjz8!D4_Gs_X zutebo@jLA{^t(OQcH{z6$Sid_EK8;l2Y)P4NPCmk&cT zeZ8#fK8Rf!qR?HF<@|dU7Nuc~`=8cGC8Qo%j`>;N=ghuy-^8zqRONf)zeoR}d7+y* zr1Yr3670fz-Vl8gUghc0>n-5FZ@YQ?=PX7SE+Pa$HWq*5os){(P>Wnip3{$FqjjG2 zKY==E>a5op|Asie%Kj|+46-eMV7KXJ+ywM;9rnOi-@msmJpsurfH%m^Yf*UB*LPZ2 z;I;ng@LCfD40k50R|Q&dO+Fev#y<*?fL*W7ub(TrL4NnI*ZFEMY{PWIodK@z^1!|Q z)%nNCk9BVJgBpK}g%phDXBaF9()g0M`#9dmH6*q!p(ZMS!DrSMtd>U{pq79!eV^VdgsAgg@z zyf7=}YdgcVd6@=^?00RudMzzm(jh?&Xnl`#1lwTo$wMWm z0`i%#J$m;b&B;BQN8PY&SYFe0m=9x@FohqY*i)O4-V5<>WlIm<9Xq2qJDRiZeTPZN z^X)kJ!0L7M%KSBqplPOXj%w^7?)B#+g!$*GT&rlQR*ZtGD!s|@`y*0!qp`Gk@=T`F z_!QU&>7$kgWjBTtN>ip~2HUYD)fJ++%YY8+c2a$3)w8Hl>Z`9AQ z*9_s^9x+Jg5_h~-pzPFtTa1_-u@=jlg;t4Hj354-@C4)60IVND!CF|tjSRdKvsnu@ z18Oh5hh-7ljfj;KR>U?ab>7>!EP!bWWnTF;@;A*JD@Bua{pP$M@V z1Kr1?X)f9C0@P#ohY`u3C_7dn7Pxb=$NMC5c5z53B8!K`Rnf_^tp_b$Cw*3?bzPaE za@6RK&@U;wcQvOQ_wee!j`yPPp4jJ^O2@zbbj$35lS>Y5+`c^PUaYElxtE>*#*pw2 zIJU`xL}kHG6GvrW(4C~!1OV~|gJdDM36mrPtr`)G)#dJF1cGkLg!Il;F)oV(5b{iK z&O-=MweH6ECMpTBAMD0zJ>Yqar9yQ{gB`Kca^-k(1ztX&SYeqLuodO#dZZXgCxktG*Ex^($ z@W${0N}i9eNUT}7Hb|*Wq7(cQ_w~;Js#Ppaay8TNpDh00)g%5JGm3s_z2Cc0B38t1 zziT6rM|%3!=IQozbWUgIc9s!<7j&dk|1^-ckjIt_Y@MXucH(y=${*4+dHWFbj*u8j z)4D8BWHBl>^Fc4PM&m$H^K6V6{@XC<*!cl z2e5O=w5G=Uj^iQu{#GEib5)^-XC!@&fCN!2ue*Egl_%Z)nR~7a4Tm9&O0Mw{Geh^; zzqV0zQKgb`S$KZ(q@59g1p%6-6yKs6y%2PDlwS)%a_5Dzcj)erG>h54rHPzQ8`?hF z%{OICAHEe2C(G;`;Rv)$={U|lkpYDiO#YuaQnL2WRJ9wC;@mTG-ZHZjK)1UxHq&D-<&a?KXv5 zd|QYf?DXE?{iA0Yn3n-Vndg?yJv2-PDm9W%w`!}STbq?1tjA^>7y|dK8_u6x(~oob zMh2$EB$lNrj-o5CAe(|37EN92S|@)(yT_Ksme+Zxe=D~NZe$S_j~tXq;XXyb)hQmc zAajsiw_(@@7cYUFLh5q{n^-*59xN%iYCRRIhdsF|eNJU*|y z&n#44uwS0lHqghP>vsyx>N`6SD}6l<+fsP>Lt&1IoH8J;;fir`*b2)qntHq?+>8r- ztBR#%8aZYwA-%I5BypGtuBwIIDpmL1RF4c$)KSBNIkRTYg6vG0MYpQ;hkYKs$KYK{opnMyCbT zKvcSGev7Wz$_+w(y?Gp|FY$ZuVAtdT!({;7m6b;jcnNs#md)$03b0xE2CO06?Uk%2 zzQY(IZB<;&;NYx6Qk5nZ8?mywFh`(+2gK^Fx?qppb0|(fk3*p)$mSgK(2?M}1xs2r z!Js>fk^UU0P2&q)a~bsqdNuj<=$6IP6^Wib*ki?4%CYd+2G~YTglH zseLV$W>J`@tSr9IZLC*pWebO55yFjtH>>-xY#!~nv*B)P-J3>7Z6ZPOR@KqBfvA%C zIi1T`$qkDw!JnNM;#7&QRrf&yKSoQefzMXA9$K|^Y($;A)|F2k|1<`|Li0$x;+Om- zS!tpuL<E|(0W4>GY1OVHuLi|v594S$(QdT&WhyWLux{oPG23R=>2dis!4 zE7!1rk~F9ATiLso&9gUdSdjAR4OaK;MYnwDs|2kv_-E zCjvcrBb1}Vy=v;XSfMeLI4@qOz@(nYtn>FwCGyuxhl~t#x&U3r<+;gb-Q)A;1!r`B z5*iZ-A?`a_h^}5Rt}HeP0w!&fkyDVW1BdcYyi)9-`n}H2i5ESPWyR!4lUwX#MLYd* z-K0L;>$5T!uc#y@8+p~=*8&xx%X7yaS23j; z+|V?$q1YhSAH|BS_7Y#9kvy+zCb|l~3$H2J@{S4AlAiJdL`TlWFc$3S&SV{-w2PQ- zBeK7qapu}{b#kAGAFW_cSP%WZ`<d@(%Me%<35d4jN)Kz7hP)zG|6d13V4}^|I zif7<^8AFlYJrPZz#duR1Oe|!_fL{IJ=Q|S4$kO_QJ)=T_9~*X~Rf2sLv_FwrCw_)$ zIiGG6zKCdT{?&Ts@n?O;%7W#}Xc}_8TfPQz8#9bO-}JlY$j!OLpkq`JueJ6*avHy6 zf6vL-ikraIG8xCu_#E5ij0WYQ&7OReLnmJ-xE^h1=H=a42MRlas4FvEAz9I4uGqSp zUbnQ(E<~zB+yFU)`Lo*5x0{s1(n8HW@6SDN&VgsAEaVJwI(f-MnX~;4FbUmA#E`X` z(1rivX1R@)m#gF^pvZK{Kc+|S9az;1`?&J3@^t_@T7lnfAL-=A9g(Tz#w%J#V(P0* zXuBdFaiLKy<;I416U9bH!SN*oq^i}^aCWf$?47v+OH1{|8vfk9Cw?9S&b$$|{nTXv z?y-Cb11~C{6~i^kFYBL*=*^{!Od~t{k6H4DMlK*fu4!1h>F1_b5kkdexgfr%p;GVUmCi&DTOMPEUD8ZiHnr}@58JXf4{lw7$Mu_2pgP8gH-LvpCgw*N4ut9Ne= zijhcN7o&LnwIE~N7S-H2j zX}mzQhXYzWZ&b$Wdz!3WNgIotv-!O`%|_x(ubINgEx`$JG!C@3IE(pz|nspt*q8|mbe^;LRewI6lKIw(7qH|K8hfj@bfaQUm*m@`8A zLBrFOUO;org<8U;&pUwRWhvF8EWozib8BiCL+Pj*SRAMWDGzzB42l%q{%|}5jU}VB zpb0^$BFyD)Yd>x5j0q-s9@mh+P-(k8e||wX6|8y!_<*<9k0Z)W&^lt{D9P9c3oiU! z(p^HQFb-u=d*K+7TPB!8u;s`*;B%Hb6-4-v6DqOwLX3j+{g>nUFZ}O6os{Yc2q07# zdC8dezdgz^#;FlgGmItHV=#EjrWNN4me5g$;OFR7L`>2z6t)2#I zSOmfHo_5u926F({2T1N7xJd-B&e5D}TE8Aq9x10K2@`xw?M|WkFGsfJe+6rIG(GHw z5&~y0uOC*50J#Y6h)gCI%>t_neiZV4ge_$+{C+uz)`UWnr9)($g~qHJ*90GOGObVW z*DGn1#G>J8o9OK^^*(LMBmVE|+a9_MSch{#SFhi^@W~w=Gn3}{a*x5wuN)*S2p z5#RC#cj(cI?Lb&?jbF4c=laa-{e9s91AV#l5p8K8_Xc$3OqenaTui!Bfv=(``M`VR zA^NI6FYC5}jPmLO)xP>w;H0*Dm;#F|zYu5)IV$5WG|&;$?sTJ^-NdE6A63sZ)7rlL6f&L zfx4igJ`KJJa$n!EhHpT`|oyep0 zz9DK+x!xk3slTq=TT&6WU!8dKjaBL3SPV=luQbSLHqu+Vxp{?)j#wp_*twO7t9Yr{VMsJkuw7yDroB0FHElfzJ8 zHw4=v-8f@yhiFb0DeNP2#?~27;OU+tArM*(eu^#M*>($qr=$(XAWBOr^j?;)Cm)#E zZ>5!qYzht~tN$eIXx%1Okl@Mus|klqLa1KR-|*zypLN_`^&#V2J7aNQzXfai(O^V> zcZ%+iljm4aC|!xu>$niEkJ-f+>{bUid55b!9l>G=Ar1>28rwRZ!+p*&FvAxzk!;w1 z0^Rm<0BaQLP`KI2D<`6fJq{M~n3qOX{7)A4p?97`Ro0+yD_w=Ym|9oWgj`3?up{d_ z&Vm`IvJX*y|1ialg7H8D{Elg zi+-{R^C0?Qt{11k!wp7QDVcrRarF;y7$2O9O=}IN*3WE~NXM#k9EX>4=VF~esfMsq zTU;W2JpCHG%3GViprE?yTM2z;z#;3UyJO=5-wvp2dG~aDxvI&Z9mfiqHRm{A|CG6O z`)3h{F)6L4ojUtKVG}D4*6?gpyF@nJ@yEw63$?WBE2#LOs$1#2tA@ze;9TFoH0Yn4 z2SzkAUX#C4%El(Vv|K76uN$sW58*e(kzIDSS~RbI)^*6N342XHg3I~e;{ZL`3Td?# zc-LqB@b8FywOhKePg{2(ti2u$-ANt#gbyX?Xf&N7Cnd-31%>%u@Z-!_Rv(^KA0DeV*MfKXZZb4f zn5#@TR=}ZrGAM}a6fLfpCoH#fCacDe9(-lQxD)^aJKDLdcYX!aEoA!9 z-6^K|0Fc+@PAMHC>E8alNLqcFy8cu^p;zQm8$nJdYVj2ZqW-FbHGGC^#9iCn zhaW5a2;2W?u2LYsNPm^J1?ay6Z}3L||5QgAxUKUMFuDWmz}*>uQQ8v7$+ys(VG01B z+`ZqK<^dmbyDvvZbrVzC)=78eW<5)^Qbvg4;DCt)Q0hAn9)1Y4@jDO$-ElzoA+Yog z^xpz0 z^Z97Lrc3?&8L9#5DX--NiH11!IiNOF{b#6_LHqZcS%21!7qnMMch!}}<4r3^H}baS zx1BuGtMC@93H+y@Cu#WtxsE zg%@v(mTm#{B;d}hQMU?FPkw}Sz~jCd2m7&$yoa(xpUA$bb;&(4gc3FRZCfpQNGI^P z#J|Yl@!^;^KIZ0yN)xjX!Pq|9(|pCLx_r4_RIdq5c^6#XHS!b%qwfWHu3acnf!{nj zI^%$jE`Xc@d^OcNuaFRyfeUEp`+d{b&j3bLC$ebS>)x6!^3tzaScRBb1HRr+`Ry6) zeRvb0hd;_mJ2#Un)0%{Q?AHiKIT3-S`m6Y=$p5%`K0i+A?1s+}(w>~yW0lqFmh&j~ zTT74>M-^+gB?_a$$05Z@Ll*bFH6j6w)yA=YDNDMRyF%x=UHp7r-UyW*8(c_H@c}F3 zdp4q>`RJP;w^x0)yI`ZCJNoP7HRfNR7?ySEhRM;4NOSI$(ZJqbJ|4IEYRwK@bP|W7 z%(o)@LOwCE3>U32g{-h5FQ*n#I*>HI=Mk#k=-N>3s@J-3hJS^QF!zQGurRS(;MBIb z6_}XXtuR)b*+G_>*llH^ak|-G@PlOCiix)e^*p{IwN3^f_K6QKc_gF{Jg(9;rJ=?J zRR)_bzqOfo1A^IBQ&r++bfwLi`CNU^I8sFW`%Jjh8Ys}e|dx4#Kw-OnX{Zcj9lWoG* zx>?0hE}Px>Y_O*!Xj+wWZ`bAiPf>|F>Q{e>?>f~QHgk|aOTd19KPjF56 z4XS?)5jV_PK&`Fs?P6o%c4PgF{<>OC+Koehl>c3jSU`=f@0DU>pJr#PWxSXZ?9E%- zP-raKFK)H#G+5PjyFHr&j4B`CrO(h)b=P3l4Y^LzdpUSl4Jp&dbW<5IeaDUo2^Ffp z%`zoxN$8bVOjpxNUt=f9+h=X~*J)(g6=@-p4l-P-`b3sdX7(ZTLur0es&x(wlNFG3 z#)|9vn?H>v-+r@c^~3f&2+2j%QTF7AI#V`LvvwINt^-R|lVK)VMoY^HqA$&A|DV#9 zEj0tOeEDkH7VRpN(m2|8Mm(LU#^Jx5hioW+@mn!pY6zvMA1KH8HxNzajvRwCqovzq(9SDCRs}MGDX)B#=N>IsSS8=u*1RY ze#uHnl!h*UhQQ`Pq5CEJX6o1gb0PWC^CO$UENdMTTgJS63e!RM!UW+<801>!d`5Ia z0q+=xBq0V1VQT>_XS%!k{Z6yxPTv>DW@U$bB*V-}NXD;vrD1|{@+%TUnfP{TnAMI~ z5V~pT(JM#Ix^ALj#u3%ZJ~9bYKZ_BROoS+pjNq>85HO>`CX$YWW2A2wUHA&XE_d@e28u$l>?2-H=>l}Rt{ZODCS36Q7woAswqo|N z8Mgm9k_$@6tC_a4F^bXjaIRI~0aXu-DY5HcsvNQ{i9WPrT-spjoFAA>5RNkV5Dswk z3sO8ay_z!J?}1&Ja);9MvOy?+vZ)npc9*t5R^;DI2Y4TF?DwDGr4QqNBQXSo7~`&v zd7(M!WA1zUfNxCUSwi|LI+V^W|E=4~$&XMWZ9jaTa(kcO&7PnxK2zthi0t&@rEjMw z{#fghuTwLLtb?_jys?lnR6JvLd8@Ir{Ub@&gCrz0wcT@ETUcw`>XG#tIcJHAv|{ZN z%>_vmIPi5w`5BKV?vH0?D?@;gjZ2u-VW>doFepQX|Q1yimJ?<`y_nYUZe_z{L z9`F}HXPf?-plWcQ9;UQ%iV{k@y(lp)(ip<6{6l|(Gt)A3rG$m(VQ9%(iC4Klay%iP z_9j&ra}+L9eTuXGw|tOBB-QI;zQqqziNrJ-UB;0+zA@SmX4e*bPOqQ-DrzwDTMN{K zwxW6Q+8jqIw{&BNE)w_hxo@$vU~J+q4Q2& zzlANp`AVYJx%H_L)cmw_o$qTEJ}mw5u~)nl4x~`hS9&)Iy)>`Tsec|z{?M{V)+{sk zY>!fH=^+038llsy7^O02gov;egmWTBEvb0zOV5vc`skr=fCL?Ajz%FZ$4{Ta@>f6H ztIHbK`LzKlZqcBTv+9#o3vQN38w&1lnjs+}{GY00f^tU-2^5)AD7mBR^Jy8))ZhX# zRoH^A1<^!vd;HgiQ4iIM)miMmH!T~pg$EUe3;)-&9*qlqm7~-ST!<=5Mrk1D5+M&4PV$AaEJhzUTP=Qp;z0xOILct6U)x^X*Z)66Iwn4IJUqa3V zfwco)N_P)#qc1EIpL>m%Jx6t6e=h=ZuSOneWLn7jNkG$wsrnM|{kx#iFi8ImBox@! z$4Vvq$D_9t$BVrtxWqsO)~i%>1+~xxxaBH*s{XMMih&CtZH(r0FV^v4@|ky9abT7j z1_teD=X~7ijPGQ8mz>Q??Z6nZ?>c2IVeN!lMl46oCzsUlW|u6{b*ekVhp z8dlP+93E-lz+Az^#XvDajm&1g9mDV|Jr7RAgbBvRnRXRZTl_(-_1B+1MJBB5sRXl$ zh7&_7pVojgu#R`QE*pSu-y6FH<>Iq3zi;t@mtH?WAK>l)z^EIj+XC`W-vH>5dTo8R z#H}UAaqUgsx}tCc%&lBGnMXHjcX~)qu0|o#k%-?!mhRSLT+olld)+GrJZUCq^3UBD zEC#^Rh1=TNe|5L7*p1QMuEm9Q;HTF0iBh4oky5Oo8L6JB8m`=^97DL*v3K#}mwP0- z;r=L(3 z@CZvi&g6Ld_~;CM?RSkc3UWJ-zxM39-WbXs>_w`6Cyx)sZVv;jQgZkX|L7VUtXtIb z^oqAhYdXg+e&18Pu-9_Vo54+>(c9p@kobiZf-~5$c%PSPE*2?C%mHUwYk>Uyd9VocZFQ8#(B_pbNAVmgyDcO=8TM2A{_T z8b3bLE62&@Aiv=Ops@&`L&2HA3%YkbWbAtB||EtqgalnQ>K4@5qAPE)?91i4C4{_zC2O*QL|4o^fqpvPzyoe-OE4ovis}D(yppj{Xu%Qy4+MS zGB|j=TwS;wS9BrbT>wWqSr5-YeFOP%E@=Y=PRoc|+RE(2vm@b8__iB>RBZHt9)Q)C zjZnCfu#5Ou{G05ziqba+rY}v}b}i?Ec!m&+UP};yh0a*W&WVYh@=V;ewkZ=c`BGaIG}ky z>Ym|4S-sp~7Tz*7k47mX$kR~t8)ZV}ElptT)#DXN>UY?)z@v$Uwfzv39{3{}yDU;x zIc=3x7e<)}Bk>tsC*mt$kES%YhKOdbZ03h79=H=suPE}=FKhx<=ZLrQQU__(<%0&= z^jq9!L^?pyM^Us$a;fN5MNz_-Glz=BAxg|GYFCA0j#t(!Yyg6EyOy4Q6)FwOie&Mw z#m~CsSFwP`Cy*?6?%Nii$Hx56)&`%wf&;6Loc4KYOs$ICN;X8HD-OC-m?y}+qL@EcQ-~perkBpjNJk> z>f(gzhKWJ#{wd}M@Y7tnFQB&us=WfFfq%DRZ{Y2@ViOR;`vZL37hHjaYqkKgG%!;G z4*6fmf`35N%*N+)z{qXsW^3^tfK`aR9s~2ItICbd?;LoIK{ui+tO91%R z*7WRNuF!u0)PwXP^+I`S6fcB3DnF8E z0mU7ZAc~A#>T&a%h1wrjuUi4N!=UrluWQ+MuYmapXfj!WX zlFpAg)B02#0{nIQ@hYe#>K9buYnI8CQlUc-T6vK&k34Tn2v-D6G^ofGiX+Ky$+Y&o znBx3#^<@_1l8;=F0d8w+Q+(}y_@~zat{IS;3uHogC*#ITdjZb)fK{+6mU$)8_d-MRfgdG?<&%sF9Zk4&kV;MzE>ia&3VDtJeh%K0YDw@?kow<7}_(!Fg9m3Ur!tppC zzWn%n7~0M6_H-MDQNJqLJ@PTmu#o&oY35|78rtpp^`RHM!cY~R`HZnkoWm)Qt+u;< z=OThnreNH8`E>@jrP3n~<-XBRJ!s=&T=^REyb~k2|2V^;Q$43EE_sdzG8qg9yQ*Qi zd=@U6+{wn-Oz2}D5Rqx2G(B5%B0HNU&8F`nz@k@*IT_7rXjjW2sE5%r>kEdz`J&!x7 z;pf~WxlIq}gloWBO~y|uzn{JSr89mr*IliorNgIOPxDl$%XXwORQENixT*20XmWMG z&`R|fQfeQ(YA>L)_kl?);h0HwS!Jtac7r@*<{jYo+FIC$=f5PyZUU%z>0Ws5#+f{m zijw^;x;?-;43CDLUuyx1p%dMr^M`<0N${z-aK~kxk|oH)t1CzAAGzU`e)D<}axk~M zbkw}8+g9P>`Dzu-g{++z>YCTaMfF7U(p?;!KGyNh(hsyK0^J^MO|5{=9q3>fe^_lsO;^#^=7eIFh`i~7}Ec`m62g2Fme2*PUs2<0}y9I4LM#tp=#T^Sabz7jN z_bv5Zz@B@XCMREe-{K}zBbwWiof@#CKPaPLrD=YHUg;d^ceIv;kS{(ok)I_8`C`(TcM?Z&bQYs?-Ns+c8WM| zxS%{o1&d!=f*i>(jO&ofvPZ=2LwiYhj4{C7DEc^LN93!v;ygL0s<3sD(Dx#6edKE~ z?P+{=1z?B$Ak3`_nw9vl!G8FM6HR%LiNQHfE*&K(Fm}un+>F+6B7Uz2<9>jQ?9mfq zh~;`*=$nS4}$_i2^u)+-4Z3EOho{YO5kx%=y3r=YnWZZ4iY{GO&VO| zVs+pyPYDo@%s$Af(12VYcBmrmdMq&)AgO{fd=E&&dd2B`#pNV$NemMenb8#;a!Jm- z$pF9-6g9}5@}(NLDr{RCwKpCO242$FRSp2D1?~@o?hhd9h`Uu$@<|FRihcdAeejvS zJJ;bf#v2E`L_)5>9^3dJpAon9teruqc}B^!Ee0`m_K%V(#>R?9#N_T-Eg7hljqFSp zLX6b%Kdcf8E?FlE@|E4)QX_kR7ek8kx{>7itQ0m=Sm>;Zd*MDkV#e3IdeRNKION1< zl9j3$_+4rVanT!*pvNJm2K#5|A8Uw6GbPmMXBz^@WD%c1>4EcHIS1y_!p zR*7JJtQ93m#tA>NuVEAF5T8LD{mC3VQu&0BwqTGSE+M zcoz9`N#M830RPV=f&aD)@c;fq6!!%hcpe?gA&e9sSDFKY-}6lrf}@wkV~NYA=I*8q zdh9>wZ}6O_*I-=H=?o7-AWWhwqaN3el+a5#C_=-C50=q@r!#D!1TsmSqi)wmyDCkR zbu><1ssaO5k$tMbGgW7Bs&O?{IIuFds}P2y6)b?0)vCf{l`&Q-j7-0%(0TUJ#THax z%p4Mq$q*WwQ;13Cy<^D>qe@Pz-HbyUpK5gVsr2SD(Yr0Zkjyr}mEJSX!7P*NC)dlZ zdaiYw$ZR8-b61;(y#)IKP$Jb9=WG`y4Xf*N&h@?Cq5-Gio1@WfYE2js>bhgR0KG9|T|}puBD9|EP<6 zX{`iL5hQ{jGoihHL(WwKcP z(sRsVHMXRh=B2dHdYPL4yYH-XT9@7@+{)6bZx+hE&6?HHIQ1vB#sl2qt}$EGPma;9 zK1o+gPSTZYlCD;oq=g>D*Y@r&bg7McCG(l$z`j*LtZKAnvHuZSd%*JNeH20(N16gh zO6aqk1$asP|IJO){(JkyI{wev{^ud`e;YZdDkK3n+DJKH+=oKW?``R|Am_^+4KM@& zZK#3;h0!3P>It+kZHU#%W^OC-W`ETG*pK39&XBDciA^H`p|q}KJ7E|L!yBMg%NkBW z4v8ZO!FG9f_w8MV+~T}_u~=L-k^Z@3|J;So7bb^6#^I0#>u)y^{O_XVHn*e}*SW)m zVTm9XVi#SWbFAd)Uz~>*=x-4GXAHsV;{@XM@D#h>qi^qW04%jC`W~X&`>C+PIR7in z!uHpT^S>r|5YCc#;7>kKQ=JolLjHPj9$qvWG_h}p!U!dPG{W`G#>M3WSP|1~2z)Md z6C5ShzF}Q_UXp{Br)iLYm8u9<0Z?)I?f7bW^z3=}SPQo|{2mKUCT>n=+)FA%k zU)`p7BaB<3>ISXq{VJv8dF)oi?0=upmYBkS_)rB`w;Lv9*`V^*2BaYw-4`DmkZFD?0c~hQHJP6Mw>kIXz1&7=ZHJtZ3I|qXvkHRTYpd z`{w~HOII?Va@b8h*kks?d7pjHntYGWj$a-3&^|p0$iE6FV2}k|=bYdK`el?D;&z_= z^Pq{|zJGJpL@)PF4^NRF1?ctrqy4kPP7Ya{7WC zo&D!Kw98s(ugcuwMQ^cpcKr5mzyI#|^bqho?f-Ik_T%yUv;O|^(dpUA-r>>NX$Fxg zo8QGGq#9N4*Eo#owf_;-8jO*506%?quzz@P>Of32B&09i5f{?sRAfi4?rCpq3Z#tgMI-uIIflhBXq#&*|+ zpN(gP(>=8ap71jrUP|`JX_`RXt$NuzH`_-&q?u5`w(9Bc_jH%_P;Gl-v-3|)PB_{- z>*@GfZJuDqs9*FQVZzC$uehacFIijg4WgFiN2iBsFE`)(=R0kT`+Fy62d9U7M?G`# zsJZMsVy81OH0L^@>^Vv3>KabFC{Uu)v^H9cY>!X=dpGeTeB)o^{dpP>hbzPZDUttP zY?|@k+K>}sE&r|MzbE7WxtB{atGIwVnoAw*t0cRU`={21LTj}Uymq0{+)pS&IT+)? zM_@>Ox)Gug3JLOIM#DfJ7F-f}u>Fu|MRgDiw6$ll0=%kS`(##wt&)GjWCpQ=;~K;( z2dpRuI^Y~AN`3MX(3{5BnC?6@_M>0|_@yyOZV~97`Q!{JZPIepLZ7g|fOrYKd(vHr z0%3!beG_U&ft%TUt1Y$bw%gERQRGeQ>irorM%FP{(XDePsPqP#3gQ->-2`2J!BF?w zBa)l>_#Be6dvK36zKa;oeLX43{7PhWtQ_h^-J81MMPM^gs~QL3m0|u){0#9O0aiva~c|B>EHT0=$wa{ySGP&{xAGx}N5UmNQk?bC76l7*SN{MRwtDt5-kOE)1FZo;6jrgec5a>3ynh5P=4s$8GK+GzZq}>gx zNYfSMzZeud@U|-bsYiV)6a|ap|A6FY#Q*88-~ZO~-~Hu3`u~2ER!K3I)y*INz^tP} zOQcF1>Y-XRpI+fa z)6ROHR~H!mfbJH^=IkhpwVJlyX6B{Y0?`iCVLiv`%Mh15Ce+AgwB9Y}dx|&~jDC zgT2LI(M?|GO&e~}l!)zIUpev*1Hs~Jc%G-6lMAi8QHCHVX0olirP~6#bQKis-keeo zrqGFlu^HoIRsAxtsdRF_v;L z#@glBI_FTfLKXcRGwi6(9=8*Eksr}Jv(9)ak6OyIYxFFB2dx2%deTIjjYh++YS2&q zly3uxY890{_gu8u)#!tCzgeh( zo+3r1epZJ&`zh=d9ck;e31>lzWM$7Mtj<7FADkn_aH|D9TmlulgmVCIEMOZC>O9dS ze4oz(KZOUHSrW!cn1;V$(duT5BXp@x%B6IwY&tCKrDSZv9~{Tq*g-a;Uos;NyB}qR z&1To6265WL9m=DN9Lf&I{JjE#A&qI0nT;=?zcn`zM& zb>Us=lSS1hK@XkR@^z~#3yU<58!%=`Emp8mIXLfJz2p*^Q+5@{6YNK|<)(mjifrP2wVBYdzV}oV6c-eInf)*BmoIPvtSZdX1JGXK z0HE_u>;L^fF4pG&Cl&_cNu7j?W#W4{!zbCy1wfO1I=`Zkm4Io&(^+~ebXVd ztPx`MYlVL36{xqi6TYdq6^!+$MoG;Tx3%-qn7xYC8&r0h`X8|{7foZJt=F*4;6h|d zAF2l`nusdo*c?*g8iIawtg=ku%DBXpl9iWaOa917{r`z8wwfR>?nA(W>u~x~R;?t? zRVm3?@<2Ms{3;p|i~d%Zd<*ormLah#B?1p6!;1|4VDl>Tc;%j~d9>+{OvN`ydf8aP z1eU#k?#J^et?TNr7RO4{d@fc|$yUYZlmXIlY05?s9@y>Dc+4bC;%TFzu2;l>=rj@h z@4~LN&Gtlo#*IB8KT$l5?T};aB{-N5aJ}v~(G}%XeDpp1^*!(O0T!D-p4ividZwxS zDFX|;Kst|sr0yx$19qrsOhbFsHycZC5{F8kV5ZAwnz1{>oKQwq-!#TmXjMN4iV71n z+s3Qpci-u1JLQW(rles}BLh#2!rXlDSnQ{kP^+IonY^%?^wM`N+mNLljIVKWTdxOn z_rkRu4-tEb6>_3sCcE;$?e8B;5{W7Ux2_P~XUq9D7Fau$SY$dIK0g1(s`j7n{B$h+ z`Ed51oo@Gqng6lddA_#)T-$%%*Zy-Q1I{n#G+5PEbXDiVW&8`jls)QwY*CAoSW@x? zrg#6}|EVWCKTYurn7~eZCFeS3t~c}3v6)kynm^Lv63uOH*=RIh#_#MtCWFiQa#g)( zt&^wRu@!wN$^ps7sHdxph7I6@M^vSr; zB!cm-wnmEM+zBSk$#0B63B-(JK>3@Axl9W@xkZC9#ElG4ee9EQ!$YrPYA-XGU_U{Z zBH+>``gKlHxr-}2@PS28ppJd8wn1Tl>VtSXjWdG~$%+TQk#H2@gfxKH_frU6iKxUO zcaXpgn`%s@#bJpI)h!CMtqP$A5~fRMVFav&)85ANyz*IHU~5KR zFS_+BCEcPF*rX%uJ=Af)$n6wtF>V?4W+tXANzfK1^Gi3 z6Y3f#=~*ln*7?ddP){tfVY%m1a=fc{#`l18@#P`xDr}3zF4L{^&f;JxdsLpFhQ;Jj zsjyS+eHqromN`jU9O(xe{y?^XA7o0@|7bKC%VY>+GpxmXK4f92C$~+;0l=;2hY>;I z+_1euxRo0ffClh7!K3oQt1-y+ne2}FvIDmuv~mPte=z1J^$Mpq7)M42SGN?r4t57(;Pl6l+X zz?;p<*rMMh=2d8%0|%xqi9)JAGx>r=6ONudar|saM;umpC0tj*s@`gO`;8z?a1T+uAbYzdvuU^S`Y1|4%9Y-)E29 zE{e(hdmv?9oZ|EWdeNYK!6@`UAH4hJ-#Tq7iVt+k;n!duIm>>ZtNJrZKHo3g zWwb!m2{jB{bR}nnfbcbTJJnVW0B@HB^!Hl_|FSX|gGX5gk|}Ch+kE{}=6&Qp3#nRO z{_AwNIxkH5@A=kR{#(m`f4cl%Ghwji1U;j+YG0Mu`G|9p{TJSt-Fzw%+$==!>k-^6 zgIf!3e~{qD-plwqu2xqr{QY+`4*Re1)sH@T=O-+ct=?KL)>?{?@<00I1W)`=J`c^J zgRs{7vxtvZ^KcT-(;`l-Eq;=axTvcU&*aoZ{4KjDECi_dBbuAyn!Hp^WM3UK_|g(d z%8a~ZcUo*l)ly9|H6VB%#MGopvZ=~9W_6<~28jh-yl8O44`xX)^YDZxWZvCH9LtIi z`2X(l2IkwnK8%@FHiZvMl zZ_AE=t+4VrIB#D-%;8$;VY@0lYz3i4mpp9plr3@avgC$x`^C3+bQTwv>l3;1iQGSU z^QQl9?_}@o!P&vdsbS82-N~*NkNKz5LkMa$E$VL9QL&>}+;mjzUKGSf(-l?O^&_Z+ zWWXgSl%xT_=}|xDHJj}0$%b*pjm5O@g+0Cb#I}(uVjiuG1)=^h@65ohOHGYB- zM7Lmu{aKO|Sl!)K;AN$^2#io(}^+mh8*8i{d|4+#N%N_Kg%JN>kU?N#Um-Z$8C8QuWVP#-aMRY`1Eff14S% z4cgj(`{~7h`B}Eaf2jMvv)O%a-v6EL_5HuT|L=SMyZuM1UCOqW@}+D!589<{@4Mhq zHZNY!^ZaBqr)mP{ElbS;9?i`%;{kPSH;ZM??s2nNpsjC~d(eMaNYXl?PL;4@DvicuJKMVbS7&Rhv$p?Q)BmR=|3T;qGZ8BNnp=|P=ZZnfjj7~DBOKubLW8ud^>c79 zeL@S%E;CV2y1H`6*@cxuv)d;XL>u8ty_88uO(*~<&1u13gE8p(ON@xj`-un{OO@p! zs+H#JLZh5QI7#j>uIg^5{_M5r|1f|@SGAm)8THWlg&r}Q%qI{^TrZdYa0Uj>fQ`8&B($3PKk z?t_8?$izV@=AsKD`e{5GO|Y~h>L2lKlRC;aQAqZJAdHmV!2)uc-^HNLKjPa9Zrhyw zW&kg2&whA9Z~>U?Z?GgyagxWcq3Zj-FJ2O$mooj^HJj)xn|6Y zWg_`jTcH=RdnkmgQg&>$4&@!RN{`A8Ea?)MBsS?_B}WPZ3e$yQreX=*7KywO zByfCoi{XhSPyi}tF>xG2SGUTri#u0msLGh+RV;xmuXhE|?5Mn?zFu`^y&s4F9F5;U;9N@kN?%#e!jWR|M7JB zztJSV@+YT!;~+s~gzovDYH{%!D7`al1-W=c+;yHpdKW#{^N-3kTx4a5E_SpuRx?!0-#Xw5 zr+eSfG{SkSeI9IH*#+8LM}e_=As?5u~+Cv1BkSqsoA;^=Rw& zA4>mE=U3ug_909^%IW{+i|+Q8PX9O8{NLLC;{ohHoaxn+>}o6)NQFFctYY4fPXTx) zTP!&WKnMl94j=~&31x6_Kx?lC+klV*2T}N5uyp``NUWqmJe|!`#{!3eEYs48Ig-=Z znRYLhHwL801>KIlt|-mx&(m;1?3HOzUUTTva6_8uPm85L7~yDuTf9oG(85SJFp|i( z+rmg@@~!oy5y5ki-kg4{Wu`vj)W+FUh7k~-@d_}X(O3AU6bqGl-5EynXa3`bNI$G0N2 zZc>pujHE3{>o*z}Q)o#Qz}$i?ab9`3hzoTD@l2%6RN^??4}+c{0^WQ0uQ#8E0qoQF z?+;(qHIHFtpeA)$Fq5#nIXRNo_ymtak|wux7V?!rllOquE98ASes#>BTaqa}f?SFV z+@D-R_6qT4kA@+h1RgpZLSmyPPh*D;PEQZG)twIdl5QSPndeL9!!6TTH1%&$JPlK& z>m3eRA}HLpk0V4-n4%cAD*G1ZpH{!CVsFSJZVu#^qo?sNuQ#6imU_xQsewLLIW&q+duuD>!1s*{H#Y2?fX?#s* zb~3RlP1x;}C9ElZ_-(Z)-S9_1G4+nc!oiA9CTxk!Ue&{HW+W4@$WSl4BRx2k^u@|J zm@FJ3Y)=cUjFJdoX0#j%Ufc9{%D9XqKyL3?xtY4wX$*Xymg|(7vjO#{=Vgqu#f>A3 zhH*l_$uJ3?;6aK5gUz6KK;6aZfUA@;zSX!JoldY$=>QDMuQOrvw~bK~W!el$K?o02 z-zni(WwDvhX|%|zx+`tEXZC%@FB$g^^9kg91y?n7i>Yba=F5a=0{6GUz>HyZKKI~O z_M_mUhvptt0Jx(THPKyZ`FS=N_Y)!PwCyS8MlNORkYV)Y!fKuOF7YAR# zt^)T057JL!MGJSvQvAi8k-ThPiQL#|i6=&oesX3GTc|YPCyZx^(6}|>Z#ZD-e#s?d zS0lI4fMq%i1@iok%&_1WA?IN)sR5~!BRC(vauV{npwdWo1o&zzN3iw%_YBi9D;6#e!aW_CmCaHafNtqAF&VfS+_}RP=d<0a&TF>tTT3anQ2z zJx6V*D7JsMK+ag?91$|32@q(TCTcfnd13N6ORpBVG%a2!EOn?Vh=x7QvRd09-`ZmA zB5bsK<=qMp*>T7?JQ^yU2YzJd z+PYaLfTdHt;9JwB>Jes@TH_0yc{(Jo5`UQ1uj1I`o4 zZ}XekLE8U8=F_P!veE1XT8?_2}I7j<&_(ra?gx# z3Qq&DEyzZ?zWGK<+D>b|^AmpxFRf+~vw_t+(c3EB=z-pqA!ji_bZ*$f&iv-*RhSbju=*$b2F|1ice+zGFCIw;2L08%jHPEz{ zsX>oXOy_i}MYI+Iq?x(FpUtYh4akFoDWT31pwCpM!@m2ZI=AjMuRn7hutEx<1@F$T zX1P}?4v0wg4fNf2#uhPa`?Hw@jZajgQL?p-u_}OPqC^X5S?9Y(=)U5iV31kfgISz{ zMTS3NJBZqBeWNXgxF4*uYr7k`B@107EB|jkY2#1qfbYjif+t)!Fb}Ign3B}i z0OpO%Vlc4*)}J0!3IYxj7CinzYS$RJ%D(ol!Rr3uX$HK$w>Om7)QvDZiUvA zzrBdYa>pS-X%db`>N|YV8(lb^O~T(XZD~2FQgf;oLcd8CF%hh#L)oA zl>YKSS4jVyX|@Xz^R`-i+(e>W=sOf&&Zgyybruz1H<8l2*!ng4kh zg>V5VUj_+JsKS)R;=ftdK^z6tdZdY{V3Wp46Q%J4WSjwpbkm=X2ZMQ%K)=Ki6?&m5 zI$noSz+U6iI1`L|h>YX;B%pK(68Ft~La4n1Wfj8+fdWkU@J~XLnwxD31{8CG6ZZHI zFTboGAS4n4jPNJeC}BFeHMykpb)3k8*KX-6yrEiN`t4oO6kGWkMU~I1Gi!+5zoX1M zmDO>aNy;Ob11t-EeJNXZ1~DdJ1eUE5onHFl_SbLkSoe#+!rg&CrHKzO@4{~C*1NQ7 z?%~p4TP^$z=ljysM=H`3RN;>-nH4R6yWh7|ZPaa1;qnur#d)LXd|<}p#@W&8^5fI9 z9jSthO#}74-TFG~&IM^Mqo+OvH?1>fV4(d}78D;kQP81H=>ym7FmP51{p0P!&0dU@x7O-!O{eXD`sNcDMrYH5SCAVTr zuM$GnMW>Hi87y3OGUajYZ~FZ{6OaL}ImT++4;C{!K6Gns`Cw?F2mKKk&{a_WU93Kj z`4*(samE~m{E)6Xg&eAD0<-R|6V|CRF1UwC8dKZ7d^BvE^#sWz=&$_XFpF7v`%rRA zwLrQhPa1=Lq;#5>odOEMevU-oOM@3O`6&8U2l(}DG)j6AXj+>xToTKX)TA=_cX6Ln zU3IyP!^=p%PxKXlx9QUq&sLavE>^jYFrR+wk(?9!!B0Z)9U`{)-tGlxd`>!HT!3`6 z_)}VaTWHJjIs}28zyzx#Ra*x9X(a*x&8mfaeaML#!k{#Ay5hL$@m=}w^Bwp#oc^Tx z$*+8K85(md&7d1xqU$zpCt?BalhxPAeoK{Y*5b?S^4q(t!U7cJm(HQeqERLp(s7s! zE-QR*Udj7%nSHc_F&=!B_q#S=sxV`W_vN>DS!WCM?VXTP;qOdN)zf*VV;uD;wQ%oC z&|38LtJPgy6ND|auM#N3DN5J`W;|jOwViboZn}v&u8M+LYND>IibPUeRg^_8gp-fj zRZSd?qH?%kUFEQr>R!F%MVH*^f>3SZB>=i)mN!i_#zGZK)wa3LQgp{{*-8kS8a&%{ zt)&-({Halwo$U3*jHXYqa94s)E-<`t<`V1izpD4^@*I`Dd6c-{MZhfH%RpDh|37H#=F7Eo&w)z$23l08#1%|$G7+RuEPLIQbFl}#WMlbNVuO|c?g zcnRAd{J{|lJD&AqNtU0y%C>AtVau}ofzuKCJLWHOoO74FTP~=DO?HDZFKdG3Dh zxo7#En(eW%!A1wny z$>lD&RH&M3zeB+2p%86>2!E8tqR4OQc`IqR!B7G83$_rF$#F_LXd$2p9O?t|37*{% z+DP*!U}6-%z?3o|^ksrLvK>P8M(eG?*21WUqNU+1%)(RJg6v$d+oR)VTe>ke)AQLV zo;Jze9{NXs!j0S`Az?l<&8A(KLN9^Jz{1dE4$w{Vi6n!`-9O3N(qnTMn}w#8mxoxZ zr;vNKi-fo%6L=6&wI>w3a;I1)(3P+;?cJjKLs@gUtC%;yAj9)}e)*+RKl8HYU-)D$ zpX01~P|>Aa1!5eT`GwpghxnTe$m7Lq1crwU$~V^T5SmWI2yFRpx(Jy;)9#!m-AOp5 zgC6*0GawB}z~chb0EtTQ1#cF>+G_vUQPlw#k#Kh9qI;ZuGoNrMo%;-w z#(_#3J?~XpPMU-tVW2z8sy_(OlG`E1^ev{-4iPiKe+joh_}Nx5QxzXPmCQXWd>(kF zS^|&_b`?6@71Su#%xVzawkjhhuEo28&3@G%`;6L}rv<0o?G^;*r*~_j7^=1jg8^f(O$MJA4 zYK5lc2!&ub+O9JBy8+eG(Bgm;R_`w7#%+;^EjhsDWupNhUJVxCmGFSB3j_TGJr^*F z%EnJoLsDF9MGPH-OkvWl_u}!v^P}f~@$})L3p2%qmSW(fC>&Jp0uNCmFH(`boXwLo zt*VS5ODIK`!-U0=AubPx{nogM>_1;yV5Hm^scBXC6TV@@X6X>d<^*?t`KptLnO$6V z$bGz0sroE!jl$Po$H_tPE7lFhCPnyImL=h6kbkPBy6FpBUC*=8C8OwrhnAYhNJ!RfgYx89IzxX3R|LE^bT zP1Pe;X`8lA?oW$0qhs*21IL&vZNobEsO!*k?Kpl1mS}A(8u3LG{-I^Q0{8NaMlBIg zhFtZHBaj(RaL4m@+h7g3VS!^mO&$0QtiuDMogmUr^wQuLd5krh;$>JFensx7zglg= z%D1%*$|9J26`IS%Jq)ZILq7n>(2@W{*8mrC$+#Ax(ACj|ZW~9a072+d$2GVr zUXT`vi5o|(Pksq@p!VRMRr<;|+tM3aTiV5|u7e6cJy>1`msSP+j+15ZkFO2w9V`KS_}+DZ|LC_Z?So^nrQF2vl|tMBO`+eVv=8{`(>EBGf@iT& zi*nfDb=cECF*&UQYGZO(E7n?N-*Oo!2XBkVtD)(N+|y#C@EIq@e+fnn3cbrVtfY&k zz*!T_gL75`*#Dd;&wZidtlm9Y;HUvb|kXU0RbUC2VA z{pr*y{^_Ug7a{~l6j+(@I&EH=kuhZfn=c^lYyHUxEPwn2(AF;YK)=^1BxHMVcrHz z@+Hp!2Rlr`(Hy1f3Q^{fuzkn z16eX&=_dSu&f$=b%qyL-g&h|N-a@&Nm@D$zw;+a>Zd>hSsM)Hvb;IJ*gN&Fmqr8|O zJ`?c>yvrd32s|KbRV1WuuC0_~2Q2)&qK$gSKy6Uu4MQ6xMIzzb-8ecg8fI9*eR0(h zKoyKLvk)fc(LaVS$6mDz!W>U2w~7F#V&>b8U3;mN3ZA(@PiVTrl=uCY29 z{9s>i6^Mm=z_iiI-Y9@>aB49`w_Qz1D58Y3H=-Z9?>n~A+4e>e#9J*yzXBAuM>dLE z^{KeFCL;h?xL}wPunEjYQ?cspfIUD2;bAdZ%mwZ&#z3?LcvW^n!z48{vqn#CcB*p$ z$2w3`fVh@Cn|B4s&B2OmBca_PUotma+({R?#zi~_r+#wrRUE?|SbxPLAupKaCD+qb zVXEocfn2KAL#ZX0S^2+R3jm{)V zRkmmQtPC%#0xOL1xHpvmVKz8e9XK#~eN%!+)z0GPQTvDwPW&jCQstg}8v1#YNI+pD z@IZs>530>G-_*b&(=QykBw?QSMd}o{O+9QgAYO`VR@4WHDwJ2u zc7S?pECp_spMDjfW_gV+9J8BT4Q-WUu5m+gHwaU(=5}F~cc)=Q2^vzn>=;VBi(m&~Tp1NCVSQbI zQl}EgQ`buxSX5Ig*l=|gRGkS?rysW}I^C^e)7=;{ov^4lQ0b}>=_=9aEF3!1#Iy_y zodQ6o7@z9l&+%)O>$VHbS>tl07<8&oRsuZ-OR4~N?uH=e3J!)vDF&R{EE{O92FTo^ z0%EQNUQVss0WDY5A5GowAE!Eeo3?)oaNDkq+2(%7fW%nEmjynTn#;85)uz1ckfv#$ z&biylLHZ}=|Bdp>O*wwo%Ky6FTVFT*zc+XKtNec-Z~j;9-~v6G`g_?VZ1t0>l_x8c zDhJsbJiPI2)wO_{JCv4{!N?0{C&yy?B`FN#wq{KXu_caVRs z^M#rT-dW&g(!o3Qr!GKok^7M8YVwat60a+iYvf&5NLHqa=k5$OQp77sZVOr|Xw_(< zAXeEv-A|=@IHfdJ&_+hDMhk_9e?|LrC!Ol{@i2zM_Az=j+Q$f0w$J4ZSlvp^H>t3# zD(xCA);+c=+Fhh}Enc6d`n9;-ChZz+w{^Rf?bj8(W$k9l+OqaCTD96KG`|Jy<7zz@ z9|rEifUo)6W12lViv*W`z=iiXNn1IGX;+DK*8Ly$)tce>eoY-f#rfZdcl!CiwY9#v zI{)AQ`HzvfdZKo4TY*Ikib&>HsK3W>8+m@i?a87De8BHhNcf_OkTsu&;_!v=`)PH$KVbcC6Yf{h6O-p}LNFv)4w`c(gY2 z(~Kr-sa(|!a6-Bv=2x(H(1pn{d!+fN|M=ZMdiRgt{de#F z+jsxu-QT|Zr+@kn|MZ{y=|BI|fA*)pe)m7T`yb!^&+q=HKmCJ0{q4K|<=sDf_rJaS zU;p$kzyA;Z^l!iakG}s;-~Au&{?B*+>ihrV-M@JEFW>#|@BXjv|Ng)G>+k>J_y73& zfAIa^{=2{b{XhBspS}CP-~H=%|K|ID{_g*I_s`$`fA9X^cmMtO|K|ID{r$h?H~`Ry z3~(BnzW6sDk16~+J_*Ax{BAmpqL}|n;a`?z3;Y+IpO63e$3JpP*p*-I;eWj>elefZ zv%diEML^gSoTQB#!|Ng5sG`!jUdB5o@^Rj#Nm+7ltvNCFkEdB;IoET!IVFfEz zKl20%F~DLm#CDOS?jC72$$$eRwbbK}cP{U^Yvn6V|NUQ{{bkyHCEBhxSta%Qhm zk-5H6)MW*mLaNQ&RT?TZRf%<>Wu58dd1dtMNldS!7q$VTBLU-c^tx%h$`R+u9>6Qf z@&NnY8}8ca-0$Z>b=u{IIsVuf@Ig4E5yaSnl52Qzq1JH;a7y)_Int%3C*cHjay^WL z>b)w=*@q5N=?h4F_nR>K&X-{kW;U2hqr>^I+oJH7Z&Xrf2(r0*-&4wd8hy)$>xfyEW@SrRw zrzneyD6T~Dk3{~5Gk;Bnp0AD0Rph0$Q$L-r{civ8=>g;&fk?GSe&iq1r1-cf=l@$h zTmQegwccOx|CRjz5!wHR?-3W8bEAIoRl{3j|KnKnE((qc((Bid7F3aU5%#qJ+o@B> z$k#?l{am4+y9+?j9%*uB)0NDo8-xkPlVxpm-Zj}y*DT)@mogVWk~gxVUb)>Ga|gYbiC@?J0McC~dzAfL%n` zx@@x68!v-+=A*r@$ui%f$$Z^XBiWa`HC6_QR>bbY(l1ySp@N>en6h9%DycSld z*eH26bxR<%a;saQivo}GjAwz*&H#ZC5MDA$o<2FezyItIvQD3mC}IPKDWOrkI6l!R zvw})ebVTcAPg|%2VCaP%$5%(+9z6f`(fucn51&8VKY0B7u!M|3zyObX%$$vYZ#6Bg z0~_;WihKGgO`LwTxH4GSznb=5e~?ZVyyxpUi^cadRwde-|GIiy8pf3`=5M&NV6NL#h~&Y zFPg3+t;+7_`sN1jt`QxT-(Ma4^v86Cb#!lai@ow?^yY5A<}Uro-hfN)Ejd%+gCY^X z0mn>^Ggs)>DyQ>tk;W$<)D|R6xsZ1dW4b!>zDh3J;)2pr2c}(d zBl`N_+2Qk}gGc+ndN|Pf{Id7TE4U@=*Q0Ot3kaw`#KpBs`ZdWOJbwQ0*`tRK4)&iv zWaJNZ`d*57sr?QqsEE%3_%AqSK=Vt>{Gvwf>aGX1wE%DeG_Q3#bV=M-x*#q^$dUz? zqvgJDI=)(6IX@i#j~fL4s&W6@vHbrx@lLq9|E=zS*L6h!T;r4m3f?E2-HxZ)Cx_>0 zMrT~4(|%i&5sFEn$$o3agjm6&by)r)=X33|r)v0;_FF6V>&48Eo>4yl+0^`|;AJrZ zvr7dpa{`zG3bBn3Ge29Tl%jVM<*cX=T ziBY>j0PA&hrj1zPE!`{sC8Yk*x`X&`dL6I0(^ISEkH?4)Y=~4S*8AhJm&P+Fg|B^n z-D3H;SoRiE;D>K8Oao}TBzlpcc|7Ja6efDr+^DoYTQFn3o+PY*FXSJyxl{Y051V6^ z=DF{9;KcCf7iP6QYv`cahIFQKnpp}`t5^9Jw0gyxQET1t)D%oa(`&G~(t8@e;m=`CcXfC4HQG6CzePe~#+2cKW^5Ee&N00X(Jv@9l zGx&yma9IsR8Oe9%#YM}Yjn1I1jX~-DR1=^UX$b5~D`skQph6gskSeHejti+Ai0mw9 z9XGDEm#P9Gf2DM*b>urwsWviu3N1F?)%1Ay>GCB`Hh2j4$dkE zJW~k?VFWV?%6~ z7YK=@DMFk52sFa(PsQ7-AeOsgV9XGhZ*4qO^NSp`$5GgcK2~K6Rq?UfH38PkB6jS6 z9e!_B+oKlO)R1|3&MB&zFQtz)!CLYFPBBE%xGI>0cMv_Ivp6|t%m4kLo$26aDb1ck z+M{Q5PP35RpECV{S~Jgwqkn*a2-+i~hWtextlSE-X^K4Q{?NVI<;E1S(IcdVW!+g$C7P%1UR6!h`=%TiMTX?A! z7O9Vn@K-M1Yemsn730I&MW5x@QoTt^##&u3qu-Ow{(&JODZ$(~JqfM+kyc_oK9Y`wT=c+Y(;_Dn&dNl#oSJd|5O` z!JMI7wmtG3(o2&dOy^Vo9HkhZ_i^TD;}cOs8k3<9R`s`xJ+ts_i6@c7SaDnRYbo-ZEJeb@yXaL<0rU5QzrUqso}LEjs?%PoL4L|3=N!exg1z6xM|-6w_9i zMk0K7&Ks$9lX6k*y%7@e?A<^|b?DXJW8QiZaL+0sHIT4CpYN0YRuk2R_|WuI5o zg1vy8n%Alh%%dE22ma!9qZw4IT`>*So;g3&Q_!ulT1SzlRA z6YtAgr0`+B7IS_IT51k38}8QF)CfNO#z+KjA~UQ-NI0anmQ)6&CJt6v^oq>0=6a5 z0`*QYC3QMJF{Z<~iitbGmvhXRjdJ(}1D1WuOof+t&%!ql1TiOZqMk?w0c1=UU&S%t z&R!ZX*`~aByqJw>a!D|%gZKznJwCzP6E3*3a5{y|_kIx2zyrA7(YdftkXCpc#fivq zFYg|lJ;Ift#hO}&MW$zAHa;Qvg}DF#C)y6LR{QuC0+pi3T>6MTZMj=2*KIJc`v+=WNBwQP0lFHL?BTi8GM+Lou8v*L zs|teFhAY(Qs(RD{qT;0GqgABx68}aC^GL&f|a8Y_siPDMkbyIce}O9sZMG2so)zvmJ~qiv3ihk4^vY+;i^c zVt`Bizc>1ukn6+9|J(1a;(u5E-!~Bd`)z)@FqsdMoEcD;Wahu=qH`!syK|a!C*hQW z!sePzu_^2i zE2A`a7QQ(PGh;;gLuagT%^+dT!TH7ljccVhNDYr{wWuo3nCXy<-LY%>V;4GPvpHNh z3+vNY(+gYkz0PlZDA1V>-}#%onhTXA#b$5)~UfqcT98`4x;F5Ms}$mQbA!Z+=f z^zueoOA$YEk4z48vL6M{&{IM82XA{ou7z91yKf6S9j$j>F1vmcABSUJgs}wAl3{>n zUKTm1YhAo31jIVhg=uYVsW*ZSIa2&8QT6Qbx9pH3g?E0NfBQ%(XAQ-yg*?Bcrk-|*1jxnCl|3nWgf6}P~jhG+tyix@}-{ALw#=RGbz7`naxrMSzOjwnq2iwvu&#L zW>gzWhgM+F_N=w*@OQi&naE`%?&^x3w#Cl;jMbi=R#%SB-9w`gtN9+nn04C$i^HytQ zoIRlE@Aq;j$ajB!!9X6Y`RL>W-{C!frJD$ZC6$40%=OxNqqYgj_qi z;;K;<*Nmy)+fdQj2h2;%(fBh>qESNz(wC6uGN5lRUkx2b#4|V?(a1#xc;@Q<;+TM0 z8M^%p-DZThT13wd-2s!faQPCydBxm6iluJpX>=7PtjL{?7&3fb=)ufB+pQbKBBfhD zNu0joDe=h^EY--{ig=;Ua}$;m{BTJl!XyxIq}msKC zAK-xSj&orxl`xeKX9bIcUF&7JW{1gH4oZ&}(=2r6Y2tcTL;7`cU(yW@QTG~nU*e2?jvQIwI#>1fMp1FBx zFov5yl^=E`yD6`%UBS4@V?<;(xr#&w^eY3J#7aQ1$DlRMHl(GYBsCE%U5AGQ%2Ea> z>1ctDGbE@LkfPSi7`jXApxa=2BEC8$yD^3Srk(W-b+p^OGvVEK_m z;Uddw`|4b~G@m)#5|VT^>8D zs!W(t0|Oy0Fi!mH5f-ipiKPR`E||cCc0%2JAtJ@fBg8PCg;xh|1iSAoe(ZMQ#%?%X z>}qjhSGk(&m-3s8DytEfzbMe?EEhpm9uD?Fgn>EDc}Ip56VukF9 zA72X7eECY_Gbj!fg%W7$p0q%~u7@^sG;CX2ge|G4 z(7)(reQrR+(qde|CT7WrpM*gjsnBX#q5F^>gXmHOR(_@1ZjE>rP#jhp7M+eAsmq$C z_fbLd7xfBzPQjQOZ76MkDN5AgDj|M9<0i})MOHG26I5%#l*AL1EM;@ZBkD(CbUay1$t0xHASHf6 z`L!KD-LwG~6}VqB__+}!;5~+`VjfSy(bk_%&&h~R;)KeEwESs8{otGzHU!wKg)ypr z=2A%t{3*ZYb;xys8p|ut4~uJrIF?tV*0FrRCU{Z3*IXf zwEV6{&_pi4%i^XJT%MSBmH&ec(F2->#}Q40Dd;*;VCDHA*S9ve%=oYE{?^ti{_Fk6 zfBmpYH}rT5OryMHvWb*tYeiJ@dY&W!O=xg4)y0h1S_M%hn#wPXrt(=d6`rkY5s7PuIXdfZu z;6|X<`CO)&PDys+qbmsE!_fsRF^g#P8W>8ag|?X7MTWYt!SUqtqG%WJ^1Uod`A$L} zvK~(glRMlKQ6dtPQ9!^u0Ij$g8%Da>(M)Un(aTp(hkxTH?sji28j}_u3x0Yj38GE^ z+qFA)$hV0%Pj4(%XHz8(K;=mx@{iOYnoA|8 zqfXiKfU=Jdg{1BQWl*kgg(~v#(43))+g#*bA>vEl`-W%Oz^lM$+HpQ5m?u`ZO-C2dq`)@Z3p zw6eXKf1K86C=@GcAyTQ)G$d2lCazU+v1s5xz$-iA?J>=soJE3x3%|NJNn5IiBBW6j z=Rf~1DpGFxj43_;`@QXr9rOI}Z>{eC@8=&|k4>;xH3vjqMb7}(gRQ$J_x*?0J+J5W z#Pc9`*MxW9KH;~|2M;G0U>--QD9Q?^O%;;1nb8y=Uz)RceBzUCH=*N2l7^?0bh{%z zoZ=(oRwPTi5!}BMdJGvv67mc9I0b?A&YiV8UY7o%+0iKv#_=gl{A27^bUsFEAfC`< z4=%In?~`mcRew*%@hK^6mRWUS%>$t8s2;1k0rKM$I(}W;J$&62rEj9b(~zEFeQ`hu zpVKvXC~NV)(>@312>5`xNsu%duYH%w3IP>pp3p1{X+pZ)vn0%@S;nL`n1pW>irp?i z<8`}Ze|$o(OFv8eD4mB>TrycYCfzy7Ql=H?%9jj7NBK-t0beQA;qaGLH&5u?Pq4C+ zMf&=jsV!J6JAD&oq^Fh^7qc$Ys<0+@wV5!Az*IJr1EdKHBn{DpSKo-|b8N+Nn5i`` z5?s6|SvF4xYiq}0cCr{j;KtfR=F;2^V`LN_e5lnl^F!nb;#P^i2l?7)0>Bb<;bmSM z6jf_y1E)UmM*fISlQFA`$747BMRpS7*z;DAgJ|rDibjiLgX`4p)moUQ3u+7@I8;U{ zj@JGh)?9ZzXNV{9jLtd7sivQ^(K#q#qH#!#rhZBDFXl7};~*S&5wiw{azL8vz4di( z+xx7mt&}feK4G!NQJ3LALD}E$cs;Mb3cg~e?$EwT14M1 z#;>vV-*0&9-ln!l{(7(XS#Rs^=IFCv+spjKJN~1q zPS6ZjSBm;$QR`@Da^V!yBe<$db)Ed_5YN+(| zZm>S-_b2{{j_;1ww?`Yncw?*I-vG7Q_Go=H?v3g8XWKzZowHh#I#XwLG+7_r?QM?z zt<6z?(wp=r!NzDKnB4Vyqpi^>SfBL#yFssPd}p<0b*9eh)~Gk$gf%mv!Fq3V{qE-7 zZMsFbd*ki9NB-t#8>2A|dejg4{oanhIojC{Hb2|!({=jU z-Mi~s!QHaj#UYFAV!gM%>1}%j8=N7L2}W?&TkkoUpT(!P)k5PFKg2hi-iFS>7{B5C zawF&M%1h3Sx_+39q7mbhcfFpsUR+d_5Ptuex8)?uVAQ$^P2=e)O}bo}#u;(X>vcyo z^S!MapU!AT*_rtJp0`=6wurC0-}k%?@2=y6ImCZO{5v*L-ujleQC#%9G>FG+0(QK< zvlX)Bo37vQpJU-|VDH6cXN#~q_p=k;l2lwv`dh`{Xyd=>t(Vcq(@-pcURkTta5kS( zF_NhmmL1Rd3WYoQYSWZxyJ_Yh(}2zMy4Tki5=!m(?ylF@M>{%aqubvyM_23bIvnDf zn49La-S5F3(%!=UL4gtrYYx>tq*T!rycV#~UH*UJnBB zC~5Lnpc+4q7i0#xgJb3=f{@aPvrONN=^Qd4BSOS91jh~L@RH@!y~bZ~0`VyG!-)7~ z9M8{%izzQf{Hy_62PD|R+S=I}xXwc(y*N2u<9GK|taZ4$HySUZDNR%1jDzWsxrqRf zp{M>CL|ysE31zOwVMJiFhS70{r12y>^Ap+t-9-|P01#FgAJM2VC2D~G`>A}{_7_%o|A9)pFP`u{QThIA$jtQ+<)@;!NK!`Cyx)wldsAC*e+jw5J#N~hF2glT#ERu6Cj6tgUJDWWw4F8?=uTklno*uWCDBo_p{NyF) zAp?GPzO&4aZH8^~`(fApG1~eKj3l-^-lX#KR6nPw4 zRr!laoD3R`Ztg5MBwgYY6&Z2_rxzUqTZe*5tOYB}0}{wMo=z!qbBQNBpdp?hDZ-u5 z@!Ww|e^^j5L?jZ1a|GzHQ9y=>crt`)Fl-tsh$AWvz)3uv#%E!43^99MGTcv7u=2(c z6voEj12}p3slgzWSkdq}n$ajz%7({q#G)mdmAW5CL8ua>@Y2sHp2YkeD|+xmlmW0C zIGvc~1#VcZ#6ui3l^7dEXx?!D0Uh!YU}pLu`-q1MLUHC-NqiEVNB%4vlL+IQ^T8eY zDLZN7MK)g`u%0htC~1|*EKxZx8hJ*DI~ zhfGvTW9DdkR#5ZUk1%?B%Wmj=5rQygYLE9brq&;ABjpEFGUike7BY>6x$@XPkD{T z&wfS@m_3XS_t$Yk7AZ(BARJ=Lf8(F}hjA}`}Pjk;;PNXGP4 zE5CNNaaOyit%{FPu7eeEM#&kSj^i0cFKkKPYc#%vSvp=!{bUM3`txagj?)dHIS7Xw zuy6bjr92o1SQ!{Zr_myDgfZ)W3KN}ip3->v2nP-NozLM+K5LWt)X%_H1d?!0F-}s3 zBakvtG)!1iV8$2^1mTr>4U|=1K0G{pShYl8HMdce^#jIfkg1|mI*fsz1kgj|;ILeo z9VipL{I!vpm~PP^cxd4a?pU3FfAI+q^K-K-WCSHm*C{(ZOK3L$JqkgdQ7ua3=Lpi zU_(y)`J6^+gEP*dqO2Q|AWYy8Kb42>P<5IbvPxQ`bI#;_GDOYq5GJC_8+a1OuiG90 z?nB@Bpg-<3!U=)fu^$8w29fvx%8@aEb!fkjggdOa1Y+c2k!8s_VpH>eXC0)W?mJZ` zkZb$T|IObZSa00@E+xldHfT+#pDhx)Hjd+Im;Y#!KmW~tMUW9P`rR36?w?VBFC@GS zva6IF!%^I9{P}PG9(juX3=r_|dHCSjB0|oS`RVJFJ^U}B6s$@(86yJA>RhSl6ZRcF z1>pt0j7gk?$06)@2u+}5M8`hHnM?@!0H>m|`%@NNN)~f?)F9-~|Mfp2$^?r2;I0`$ zLSLk8;JRHOMy|`s#B;{97>f&|1?_-L!`wU0<3)n~(~sgtgL!mx&ACU%4jM5125z@L zX<pHqg&Yiv3~vRD>5TmGYg7P9-Xe8WAZ?OS;z#3?4i_Au z%V9*KSf9)knP(cq0{58E@B~gn#?Ylec{r!zT)s@@9l=laWrn}vWG301*zr=`gT?e~ z%z!(Ig2ek=3C}i2hgnLe6DB6J6bcNRh}~=uW|AZv%o1Uh3G)XWiIZ4(_WM(aw=!bE z8C@Pqjlu2w#>8Q;bC5=q=NbE_{`iF96lMNveq&R*eB#e3x$`&%EG{=(lSGq*SXn!j&n9^9#C3m3Hba3a6Ic%^g*h)AjLyqFX!Zn6` z&7*JzZ4-^*QzCnUbAufTC#&g5VKt4<28F@tWhF^KR zKvO{tVzd+<=?x{7EyZtcv!U1dwwN!f49d+K;g-p8mrWmWDFS z@GDr?G#L_<*#my`1B1$9G%;c4MyyndssL0+2^|p==cnfiBh9-YiH9i{heFH`19b7s zV0M)-H6}YB+vIow1AsCI;+Hc4Qs%*tDk`4NyGw@R#7tE}X*dg~K3<>1lJR6g=Yhhd z8Ej@ekt5I{`DdV_5~3K#N`V_3a0o2UIcLU=R+SCPOD@+U6)K>oVCRQIKjXJl-pK>^je zNW)K#Q}}j2I@cHN%+JOrLXv}tAh4tH;#amd^o}XB3sb?g%3M_CeFGU5Zjj31B0DHQ zzfKSFFQtq4TW^l6r=i!c?ACogFnTMbRunflV?fGB4YMuEyWcsRg=>r)ho^X{%Xx*Y zs9{_b?u)U*d!u|T@DEbxWjqdjdF9Ls1%9>zVXtLmblyPy2Gg_4d&p23@5Dzbh3gfw zlY~+-1$A1Q1Au9Hxj6dppz+B|+0I|FfCV7Ad^-pThm$=|(_<@y^}t z{?4ZN-Tb(XS1&}RZ8Z8G$*)@U&3x+PCJZCO6rd!C#|ycw2U0B@#A86_7y3{obvjtq zAuMLC@zL0SMWhDTs)}sXiW!Dy$7MhOftRH>WB={-cKX|f{dc{;zPXD3doTZ(_bNvp zCdzbkG_6Y}6}z*GqpxUlx1kc@%j9VipN63JWuJQ<_^jiTbPYtGHKSZppa(E21?x@* z_iL9rtJS+Q%WVOj7U0b!5u&NULyg8m{at&2`9m=&eL)kAFKV|krzlWFB!l$}8V+H; z19OmN6R*Dixld@#?VqJL=Ks;_Z*KI>{omW(T={=|Jp2EK7{JHC0hV9^6-^`xwQFww zB_UEQ0_4-m;l9b?bb%nK8mm2GP*dN!a1m|;7~v<1|A@MgHO+l!Ibm;k{=dCx;XiF{ z_BK}h|NZlSHBqz4`85DU42W^ce;072WxK8X@W3Ah6x8K+1wr(JvuB$OV``WAp_JpD z6_w7(e&wg=D<-~P6AzlZ4XjWi&^l=GBJc?yf}hU;olp??oR#^4e5y{t=S5BW!jMGO zViG#{sh?z_KNX~R8!QzC<;Q{c(Gi@;18j~`4z=T2If>I~f1PW;QZWt}O1{hiX(4v2ZY-(CfHQK%HL5-};4ta|{?5J4VEkKhTxQ37; z@EGXOYRDFPB%t#UH?QPp6CS>gXbS#n;;r41%UubPEJXmVCASY9XvqIA_J2L*Uyc8} zv$JXO{~qWBR{a0t;{W-sOAo;5VgepaRVRS!qYvpw$7cK9%% z)h~Q|3un`NKb)>|IyK6Uo0jaJpJKb(g~yFJy{eBLt$4}#Q+5E^khre(4A&0!4AWf5 zlqSe-*W_Br^HwZ%PT9FE#7yh=EM^NAtJss(b_{eobbKF>m#_2}^8{{HV84wM*XuaV z%HGf72;86@Ze{jg|hGnXc`=!+K&f^OC_Jy|U66 zRPrv5b~}TB{hvHDrro{NJMez5I2sLjS+L zy=CeDHa1rGzaQZIH$c)$MF5W8UwY8uf?4LYEj&1MDB+??N(dNT+cW$6X<>belAfIv zxt6Zri_f3SlS{AV3$DP^pSA~_QcB=8_?$d1ZO`q=|24M%^4Ec?{2zTQ|HsY_*aTMl z|0lQqug?H(hXV+z*V+2aB;nZqoyL+JU}=4S?Veib=`f6y2*{roO@|PwzG$&ON-&b4 z9*!qpMXdrw8Ol_ndWUCRJu z(J8k8xr<-X1Y{ArqMFU!DBB36lv~0IqDsh zA4UEr)BdBf|LYons`5W=Y+L-lzqzyG|10~?hj64^!vN%F+|mM6^!hdqr;p@xYLuQf zKXx+^?{hsnkbO+mH3Wsxe3999nD=k_K`^B#7?9?_XP9yLov_)jXWn6^EuPU6gM;qf z)2uywu&Rtgyx2`!g@mZ!vJUadz*{W--N}aqAM#%vnQadqvUnlGJmlVqE#ow=Fc5t# zg3IdPt=#`>95_p>1FGzQmjBOsZ*ymb|NGJE|CMEPT?1gj^?k3nnlci#ECB8*OO1f; zPj1W#Sk$81w*M7u|D~^kRrkNXZU66Wul)ahlKcNA7{G0D0GAPP>8*byD`3GW+=Lmh zaDcC92Xs%$l?{RAr)%%jQOJCI7uo`R{t7A2+u?U|J+Zgskzs02xp|GZfkv1hi;0sNW_* zQ~k~&ij4(Op(_wpK6BH3#z58&GCE6_A*_C9QGV_pA1^zs;v0h)7t^61&rso8Ae}qR zJxqydk@`TK1`abnTcoTv9f{~8IN8;m2y_Z1?gNg37BRJvC8VrkrOWKa!8d@0nUiv@ zDPBlW)6GHd(Q+DutUH8i4pMf9X(>{6x%o=0RP(vIiOqLv*UH}UZkt6Mb7dB>=D>2E z5JXDcCUWzcyb#Jk7Zx?~LL+y(UKCv4|4dkXOm6V(386qzT5S<`=og2$}k6#+K5HdEjSM z4%E-TzrQ1Or+M65L}L0?_x%-eL4Hea;|WE97M zsm^_6AR|T#@#!VR2P52OCMoWoL$hbHeJy+9awrwk^dwgQ%INgN`~OJs{|1ErO8I|h zbH~Jg>Tm3_ucfg(2NPA=EGAYc`$oWLqQF~$F->MOfE%Tn(10v*ccpSE&j%tj@%|H7r$Wtvg4DWa>>~bp?5^SCALbVCx%}kJ|K2W7U^= zrxo64I*3Pod)J%}7iX?@^KowkF5%nzLA~)PPIWadM>TIpb*@L)s^Tk>^;*9sS+A9= zlJ(BGE?Mu5D^uzF{Muv{b6=gTVy^2`WBE%_%NWof%JHxI#zgiATv+Pfn;gZfZ%?j| zs_szgH@QGg_DGLE{D7}fD%cV_+g;T2SS)rqyrwT>f&ZbnOK}fG_LIDQtFUD+41`Fe zfAt)$fX1iz48Aw(S7t+gqC7*lM>re2#Uc#A@&hx{Y8!r!{&C(`_+i#`+2%__8m5i_ z`%z^OeEuxAN5_5Fc1u^U`|aO=)zToscf+zq+c=spok(LMO8P*GW9nq)YA`i^cGmyVNSH zuSc-!SLPchi~Xs)JQr<ksk+{|8S_X_ABiW&Y6n=|hEpqE`f>HDZsi=t|f^rcSrh`H|3Jy?_Br60ZK3~XJR+{LUbM|Ck(ymFUzNT2S4 zmKfdq5&clDN_azi0igvHfpE0bH^FH#e;K|IPl!3jhBj z+y8ZSQI;3&)ffa9frL!kP~7IxZ?O9ho0w((m+-G59InV z@W0kq_+KBX|G&9!uN490^1azBtHS+xwb#F+qGE~0aap;USRZFA-s|~azWuK#4OIAl z?(}!e{lC4+|MQdG|JP*zH^~7kS!KDczkIBZtH0Nd@^KHM9^VtD4-$V;BMzoy>|ZuH z6&4G_|1OD!;dSzuiF%YPVq$o)$_SClcqT1Cq_k;QiEOGt@FrrLKn-@yDMd>R^bY?h z?j2TDr+18CdGD}HEeyv+dd>a`MKuR*T%;AKjf=EaFJ1a?H)P`?t?uaw^@D5n6G&h$ z@sHv@VpVl|$OxAA56e{cPSM2Q(3VsvVxQID#a&n1QD+3STFM7PEn2;6>6_~^Vj#hG zE&NfkYoV%IyA}yn>{=*OjXfHHzWo`bY)`J)OO+IZA5|Zez>lg;sMCABq6!33wd@BU z!B>?3H&531RlJA-KRLf2M*&)u(y!xW_Q22lM}FiV)1*=>P?i6uXXXFhz?=Xp`Tu>( z|2b+^4Ien+gr<|QmkT#>f+g_kQ8TJfRMdP>I2qlPLB@d8SAlDF+ zi^ioH7gL*{dt5#jPL@WazmRHSKZv90IY$O-j;#8cyL!POp7~)kAWb%TnYo%ze=A{+!^3I|=#91zIbv+H(<;2*@3NlLSuqerK7oF(D->yS=^0l9FM z$^7J)W?$1}7CwwAbr+Su+{=l}W&|L47)|F;L-`XPxFg6_;IOep^4PHDq_ zZ7=~1x%FcfIetKyqp`L|XgUp}tjiCCE?g_S(=ejsOPol&{B&8NwJ7e=**rV%N@3*& z#g@xPgQ-_@Zha7tJ<{ZCvMbqSHwY67=g9e*5H-4ES!)-#zbxF$9pT@n6a?*dh(X{{ zkDZh*;+jANU*!@}Vc}dhf)7wQGRxkUm}EJGDknMNuE3Kp3Y0bbx#~Ilts z6X54wIdQ5uVf8_G_Ozup7($o$Ryg`XkkhpKT!3@QR;oTkN@i6BEs-mK<&?Czp2KYP z4a!_rbU=+km--rTXm{=UR_SC_33v`~YX{^oHb5Lg_q-X+eE9sHXRp9}%=`N7Thg45 z#s(U)n7gIuv5(MM-bl2mPjJr+8nEWLXE{MDaR5aEuC-mcn45~dY7VjKu%8o#CIePiUZ^ZL2K2)L5YL#R$PVJlxE)G5ssWz1Rn#D5nniP+8mk`#fzHOAj zSKsPQ>8IiUWnTdA$5Rl#{N#~;9MLTNqYoo{bNb(nt<4=<|GTsD|M&s)zwWuVr2S5L zK_Q-ALECFx8h7O9YGR+2c39I6!!xqC%%qrV<(dszA5HO3jn-)X!*MI!vF(nLpKN7Zja@Nt!)m;oJp97E$3dV;!ha>k5k3SFn?0APMnd=%7qY|bd`bfy@(IqHER2q|fiX4XVE#?bhnO}f zi)Z2Za8AeQ>tz>!e{hq-%>b(@ZQ2-84%NDmdF5sa8$W@JnAxTQG-VWbts-6DpSj*Q zmTq;;HeEUt^fmU;#}fZ@74h$S`u~0(ef=%{|H}XWN1^}cxFGe!%Id4hyAI3e8tJ>VB;l!V&Jf6*U7~?Ae~P zMNPaXpl-e(J#w$S?91LOG9b;SS+{E?iQU6YB+e3V-!i7Ekh?YGLo@f`^_+LZrt3B~ z^WPk>J7Vd$@FCRA35Io{vH>36Mm?pNb_;d352C#*+Sai?k|qsn-Q08sSbh~(!%eda za6VSNb{kwvs(xLruWMJGU8CZxeziY{F$ouiwgGLsQi<}W$~0S`mw9Ooo?A5%Mge^@ zApMT>t)aH5Sl@;&reY;JmV|*C=RQxDTXb0kg|gLiX`)-1`ZE_qoIM$2kH9wtdwk~4 zTdgEMLzFcGDA4n~BtA0+g-uvF`@}*|CO}tbdTsJcb*?Yl>W*LlV4|N^Q=k)_>b2Lg zQ0o-)x~XBj;_9~7a-rt2w)WAfasw%}`zGyfG~G-6vUCSrp`z{j6*(Rm+Q33tqLeWg z=`O1`)n1f6S@_13{oU8~9mFiLPplNF~En3cGN;wiXhrQNQ5EV7) z3mxW0E5^`8$)2g9Fq0Q)AC+V<(#lEYo&ELgCM@DwHrug~O-)PF;I}=vR>JBF}bkxs{922^N#EC-k~|BKH4uZ;m%;s4d|+xUMw+bjIfkBmS!jk4oLLNfng`5y`nAp6=~q!d=P!Ob&{ zHG%AQO|FHee$B6YPT9&6I~as1Jm!ncPH9k>MB$pL5{h#$WG56n;hLtCJcuCXQy6z{ z(rH3Oit&2pzj-nqFOq~tW6((Sd%ao-8<_7NPl14@M97@LH@GKfq~iz^uuH+B)UlhK z=d<2)2lW-V7RSaeHp>{#RrB zFMl1Zz<=G`*s$=Qcls;;&!6J{zdi%F9S&dt!CqnOFOLRWH~`m%ge@7`i{)@q5v8wa zI<5weT1D+9kWuk6R3B}!xJgKe0p8+YC2+S`Wn~{Z!3vyPEL0026>kSO(NjrGf~B%w z<#?&A`pRA_#H%4wS;1gD|7PJtZdMa<{Q| z=Z+xDZV_i;c0w{bn@|0Wb|?NgjE>0==nqM2=AV-hB|cM212c~&1pW%sj0R+QD28F! z_8@2Sg^dWN1XOUVAyg8>;Ha~In7 zkgSoR>Nw1v9Meo$RlKO|*1AV{D280vQAS#cSg-B8t8=6K^XVcb6To6h2^2o10b_(> z?qyR&uUo=RvP1m&d>W3KgC+U%U;WcI$xi%?%ob@z9zS^w+b(5e7$+n>iO(W2m@pLi zC~zlsvPZ&zX}p zd=k(Arho?I;o;#!VG?bnG^aUy8i!GqKJ~K`0TU(Un<4on8P4(b(cI5Yj$lz7iEVZy zyNTfl!*;%tHazk*@PT|F#QK0$HpJB1JmLX{^ef~<9iCiT55gUi35$}z@Ya0VzFLIS zjEv67@FB81VW(qN4%srTo;qRo6>WdEn9_8>YUz^4kbISl{MR&J{%kjdQ5MUsI9wa* z!4^aE9jx*!hFH6Ce)@=I*UdjAZ~{efGV`b5A1RsAV}E>3=KlFK_Jb5iAXC9BQKqdH zoXeb`dl(+QIDAgV{&ZTvC6J{L@xsBUXh>QQzG}lt5@TIs6mu$a%I`~ZICE{uaHr>D zun#FELvOrD(l}X5VC2`#kXnWr%DML}7_+M6L36wa13wxg6JL`qd;Tb8$B%TTP^I?e z&*z8t#9@ccwMXAW9TT*PuA?B;-fS?m@#NK5cL7nft=h&dO!Ai;zNIU3B` zf0zrC+FJ{whY1x$rBs}rT$&KDHE~AA&>i`m12IxZ1JA$VlArNjQj($|7SW_zJ!sjA zM7^)ejRv|&b&RVsy!C!t!r>fn!Y!)?6B$R0fghc_z;tBSweL{cfq!?%17t=;LM^gB zWl7;vk311)X3_b`SevLLKdhrTQx5AE^^QF(zwidQy2+T#U4WrJ9N(x)NZ$J)VCvK7r$tl3eY~uw`eLs6MM;GJIKSBr)N5{A-B@lnVwGv%vR6$d{*P1rvz!gM9RFv% zw`J*ndfUAf{{P3L|H)ls!7bSOMxgrtX!S&eiXvn%b+koTa5;@pr*Q*1qYpr7gw0!4 zGR2QH?GYOehyFy-TB(m#>LXMiRj7@wenMYK zeGCAINyzw-Ss25N=zYl*|^fWjl z9SEmHb7l^P(mC;`g?famLirGSm$$dHTij#F-6KiE>Wb-XJj7DNErS!;d#WC)ApBMh>f1!G$U>?XQYB@i3_^iDi|SH(V^?8UaQ8z^E}Z7 zYZ$BgtGBBN)axgv_LZYhsQ*=Ca-Di$RzlMTTammW1AA2}LCn_{x-rK!0+C^&GX?xJm?RqhhF{rVEjK%X>tr+$e{HXe?RpTe@3%qJwI#V zKW%PV`JW&w)Jp&VUiAM8khwkE;3l1Nt^^Rop+Ef{^YM-rvk^_mTk?|q)gk(SUn!O? zq5ieVOEie$x<8e*j}r|0xF;~0$y;8Ph#QcXj9`c8|9z!| z?w^Dcgh=Rh2>kDrmPR~GU!-AljMw$w`AGsLSC&2qW0+u)f>K_72p8|D`foq)umU>M6a?ir;i6=U3 zxFR)KLz?8C{*L9S@YvgMa^6zk8mgzIGs!HXMM{J2sh^~sGL_C%PB`Oa(@r!v%xpEm z%UAgYaCI44-T&5vBSX5zdDXSie=G5S);BEt$F2Sf|L2Fm|M-^A{xZ&AI;<>THG
n3+yC0=ua)xuMt{e`f8By-tNs5m?El6R8(#|JLWrejvIIwV zRAFlbaHQg3m#P_AbR)-67(iNtZF)BtjVS%>?)u$;_WF}ey0cA9;7G;E%9U<`w~wat z1n?~#ITq5BIN?hD(qfC*%umh-r1^Ijev~a{D^!#5n}NSR?%nOt zfNlok^@+btx3{-9cP7S1C)5wvy|XSDYZZ)Z1qy5-dMuyJv~cVzCnz6n#|?TVG2D*) zkAT)UAoJHh|2H@ciicUp#$yI55+$DhguEK_q`Q zttiA0Fq`2&_ABmjIS{V*0PkZIn)&kqY0mt)`68jg0xM^Kn6Ldb4UZ#^7@hwxi%I-G z)(Z~6Z4^?N*T8i1*Y#WRfHcF{(H1yeuoC%qQ@07RaffY}1I%9t&6pTmo~Kuib%)1! zgc%E82s8PJ4`&|MfY3<|29`aC$1tWH-cT4pc*e()J7aJB{6(1utEY2JuU$_*V_^GKM1S*clyfXdGGd#NNFWB?4CLCsd zwvc-9V2VQs{}r7YXW)efJ;J~E<4G8W=?Qx9HO1dz-T=H2=M4Vf56}E0Vm_%&{->i+ zY{!24Rx>Mvu_#)}LdgU})VbS_y|@$>z! zjvnv-?%-GZ&kvqFKDz(p@z)2xvMPtLgVT_n4Kxj;*gP4XaY6bCFW20)i^=R~EYGX; z{v@Fj*rjLPSf_GnZdMWAb4W8tiI-Nj>Ogz|4vhH4_1Y&J&^73pEe&XfxiWuOW9T06 zvgG>XC#vn14B|MR%@-N1YSn#K?0W4PYeX)K7bBiqkM|!vJUV#%yZvtt9vt2O_5QO% z*g$K|m2g-?|HH(;n-u=4<-cBk+miqKtNd^8RsJ*OKB=f#TSG5r9!CQvzmx{1crqxG zP6nEAvbM%gMwN_P7?c9bz?N4Ah2qMfOj;R~3M&J*tTJ$kDw;G08GHPc4PbsvUCDF0 zJl9dY0p7bL=dApPli}3n6i9D!`xQ%VjJ!)&bFat}aZT3d64PALnd0269^(09hb+dS zTKS?W6T!+QuO;es$XQw|io~lzscMP3bs0*l)*(7MB&H?m8f%|imd*c4LR$SR)&H>s zka|q)t>*vj_qMj}{J)#MmHhVu*#AC|{J+}ryL$fL{pj2XV(D-k4>MRk&$(z}Y#5Dm zy6UN4m%7hdO?33MBt>yi>3V4(c@d4s0m5^L!uBgGv$3NIrO6|Wq>)8EFftlz#iWxc zg1Z=rBRiz2m~s*E<&b9k`6Kie6uq$DKq|^`{Q7f&cxX|>w|1olWXxphpT>!({-Jzn z)NZ_xf>%xr&iQ+~7doSDytp(SZ?qvR$>*$AG`vA43QM3%wbD_RM+ZD+ z9cx?zQ%u!W*t#eo$Eg`>)+F{dmTx&0X%U9w(>wq>WXr`9@zz5YS3QH+U=6=R8I`rX z#iRweE%BWB1qk{|+21jjiMB_cfXBdDh~P#tVq1oJhbb%p7-b-MMo9+HB~Vh>n}J1& z3Y77EMvucZOU}*M((sg#m3_sH0THAi-}_lOno?_E0GdS%id_3VYF!-+Hr9XstG`Zj zAdJ?~(W;*vQ??^p+NxsTw}&E__YRrCK@~9Y8znxTJ66vZ8E-}E1C)zY2%wuZ`8rMr zqO~xrr*s-;d7Bg76mmvIW%GniXo3O3VkneKllY9yKMfG2M$8dLwhlX(ga%$9^wlo- zs^?VVgv`PeJn=*+V<){UG72Gpmd>xKy&f0}Tn(L)> zF>}4--f5+c%6sK(+lim<2dA)V0Kq11cu%`;_zv%VoDC? z{OtHq%(b$1i)Y+E58dUKnjB?J*>Uot7*E65t;jFbMf>vQtKCw^x@!^3{r9d#MtbXA zi;6BXRxY~huS}k~-fpxw$PbFvnp&u2SuHUD%EIT((jtZ(fX{5sUsO2&5xP;u=0X7wZIaP5z z#SuYcvCzyHp69V)?6{<11n6$Dp=&D$t0Jebs^%UG6}VoCf!8U2zkSPouuUnS34hTX zR#elWyHqi6|ti!))C7PX)nG zBgmBRPGX!<0wMmVYf@OEWtAOkQcHW+`a(4xl->&U-{jss<;guZmG|!1BXiGz)R_Y3~SNS=lGo zI^b3vSOYC}lMt18!W=6v#dgZ)wr$O(pj$DMoE822A}3#S2DzSuIctKH#@obCzFlYO zNBsE8i;DxzUH++hTIL^VhiJi<+Ci#(sy$amZEa1gi7*xRC=&Aw9buAYBw0jgHwt1L zA+S#!(+n<5%4x@}aS8pyB1~u?64o1wZ=TT8FkYlrJ_ulnbt0UZej-;2{&u3ECzVqs zi_U7ymn=MAYO?arYR*(8E8*iLEu}UK(JgUBNXRQoH#5v4T=Ae(2h)}sd5ghb@1Q_@M<6`+CRuqsth^qU@OrS=LjV~clIJ2hOqn3&$(2zc zVp;s2pR#hE_Q*bf)O%ry|83=C(kAyv{)-H9g^B`Es4j7`XExoN`SVswf7oGD?hx&b zrX3(uytUQkdlfidpvB*l$I-o9Jk;ywhyT5M#gt!S3)S9A!9r`?r=N;M3#Dg;_EEcC ze4#<%(>hX&?~S`k!^OUAA|6wO1MZ?22xDGUdA9AGXd#U0v(Dz2uNasHtd8m0%%m4L z>C|JwWfm$3MYGF1ep+S%4BL{RtWwdK{DrNFDE8~ohop`_QmawWvVq&^VKlQ~1bMm! zi~TI3@DB@WH0CiTdD&BdfVln)*6bn83Jz~v3{Kc3bJ@7@o74;sY+Z?6Y)&_$Cu}(t zBo(sa3uFtsg30B@(oG{B^!9Gw;t zX2E$xr!2k42!l-%lckG!eI6Tg_XwjZ_0f2I^m;&=Sfe2u>F~RbLRu`AF`C6|r(sV% zW5i_|9^HC}A9S?cZe`sv*<;&LZ^a_9L|Dg`BA3{0GxL3u6kVG<(%ZlIE>buLpe@Ca z-A2hezRIM_L*B6ocI{GC3(U$5ruz0e^at4YJc6Pi!~(So*oJ%@D${DA)yp%QPzW{I zDX^Hh%pFeaAWMmN;-@Fx*q@FUaJWOwAgS`&Z4Qkyk84C#rIZ}{S}wpe1HIlXKBW(5 z^X&YaFk*n@ho}#470LkS*Z1QYn#1wic#(|h{Wzd4T||kpwi|cS#gdB!20g8n+aIE( zd$~bAuo&#JZ5wRxgZALN_4r?QBf3Tqa7F&7ogEARcYAYV761D_{r@h=^IXTOJDB+a zRlTzgqDOQVC+93*ZMl~q%Wr!N-h865SC0+0SNL+#x8^71fwE?4UKq7ydrqGj;Zr9Z zSfqm%FZ`CY&{a#iR0%$c?pfSFjz1d6@!D;`fu84lak#2EBSNhKx@cUM#g*!$j3ra# z8O1$_U{GA4o#ykuy9mdx?Uy$h%E@UtltK2;lDEdHY`Y8|#UY~BT(`BzF53<486C$- z@VUrXvxr_t@mcgmn`Q5;@t*XhIPG)!WKw^i-e9r3StLGjb=(Ot@v9Ujkikt>~SAJoz2IM$d7 zp8H@$r(~~iLRz4J6=UqFFVOL2`E*Vc?nGUAqTa~adg*jFzS5a$c;~WXvc%1|uz=&V zy=}K%ytl4(Lt!H_ynC;AINJ>@FehC&T?0%XT{xUElelr4H8YMs@}q@6ou1!60ULfW zV5ajz7sYylLY2qFn1kc%g=Fj;S0jP)LwbquXYnK-!h8Aa0S=Zm-m1QYc>`Z4KEuks zHLI2i7qkCM3qLBR+JtcPtU2lhUJOiZaybVj=T6(Jn07EZ3zhT$EvAyeXQN%auw7L~TCKqlwWZ>E=A|YIVg!-SFLcvn% zpo;u&JL@L??|Oe@bCv($2Z;Z?0p(7alV3flx-dx1l9cvJYpbGUbav0|{ijueu7N== zG8C1I;GaJ)km0`IUXuFL_JBj`rs%N){+rLMTXyC6@4DN6DRn?a{zBl_^#0KV=!F>r!_{HOMdkMch4AQa>B@ zL;r?;+;3TLt$yd!%lj?MRrcGuTHVwFun5D5SQcPMF~cNWIC6H& zYYm~JUFBoxXkpQyir8)LbiynVPvs^>@t`B#9@Ff}StO!@9&p7}oTROMTf^O{Dy?@- z`Twe-e;xUMdwa_||2NiG=l_r3{Ko}zBeH+VsjpO0D)KLN)-NyU->!^*Me+WIsI1mni0-Rw2DZnMw&(an8JnZmLKc&|CF)ai`TrRQ6q~qI?K+T#t&8$h}c-VjyZ^ znHa;Mw4ibnRQlzEpy5JPi~;k!y@~!iqwWj(&1 zf0bOiu*%AQa)K2XD=bvm%dsQY;)?y`q_C&r@8Z6SiYt37$(Hw56#KBQkE?$_GXHN2 z=5g(597b9C)Xz@V9=?I|B+Pybzt*1~e6{~|oM6z+BR}$wY2wxmRQP}Qt^A+sTN|tV zpFf2B&q49bq)3ntX3dDl%LV^@fr!UQCChS1r0aWh3`eWdU# zD#qnlVn*F49OHa0L=Z3F-6&HeAf?r#vf~^%N7yg(4X&8QmePnKq=m~5?M8KV`M;Lv zUx)wqHZ1$!CYE3E|CRi|wESO7^uJB1zxgrA^eb_GCI4Sd{;wzc*Wv%0JDV2&U*B5! zf3M{K4?+IFLDBzKrT$`p|0gZd*OKOc41)a4$^SA@)5M1$!}IGvztr*n+v#mv`QJ8s zEB~MO$^S2klX&s)?3|O9=kI!qCQblD{OzxjFi;9h0>wpgGF3E+31COQW=j{_2k>$w z9TR9NT$X=)^coXQ>A;Rn%mG#82gtam6IJknFdR6~^X9BEmjk_Z?Lpa?y)7Dv-J22A z-S|&8wexHF|7~qp_)nYbTN|tW|NiB_eRM+8+`>BWFg!+(1oi3tI0{0uC>){(Pt+$4 zN3#xjWg&uFk1Q}v007p^}3)_S%SPKVYzshiNATFg#+tC3R1M5U!Xb`euv=hU>Z z>?q7Qf9m4G`P+izgB>T@l|@Q>o0DP_DQU2u*2nB|{uQ5F`JVsI3*@sc%jA#pV#X4X zWsT>C&-i|Ht}YU?C)@MZqWD&6N+}g7`fKafrYN7A3)-S?HpOsgC2x(DMBeJFf&BmM zz4=z-#@0CcKTlEd%Iah1GX^uR>kiGKX*zMz3}MPSA3qidt1wF2k|W79g!Z5J3GO4^ z7r2jfR}GSC*j18^&Co4YRvJ`QyXHOD-e384u$tKk&FjgQWm1JDe$^0wI->NeiUK%6 z-nnDlrNLgHBl(6Ufdp{|^XGiW!DT~A0fKjrLxfS73^JWg3K6=193Y7OWO(iU6p(av zI0PM4YBOY8Ax=<3RN4G=yq&^Z_~|Dp0|TM)=(9&e&nU?$Lc(M}{JZD*pQ(JuITRiT zpJ!lD&eEtsk~E0t4X#IXxo#wxJc%zV;jf%@OX#1SWI^d)UXavb)2e8^7Zb0Ap(Z}j zSz?iGI(Fnxc`s7uPqThphd8=Hm*i{b#tGxLdr5HzD<>go3{6NaU-A1ioh1_^Wy)4fA?k8gyO%tBL=! z&HujGT+;df)y2h<|1ahLiRAxTDgd-+K#!CBdB@QgkA`GY^Xzp00~)AL*@D@2;?fiL}!59Hs`psN2K^7cc91NQ6zD<}ErFyVTA&Fz^eZIa(E?d7L_cY|A^H{8 z57DAOf$w7(Fdx#~?V{ll`@?>zO8VASNmJ4#%~+X~t4*R8;j6q={F{7k_($mg@NaB0 zvR0ywsi2Yx8U`zaz^Wx0u7L(CmFTLcQup-Sx~G?+eBuX0(3~V+1XV`zDN|=8U%Wu9 zpQ@yi?!QZ2R2CgqQ%cPNnU9Jnr?@8wtX7$LVB;yPW-r#Oagh7s-=smOhxyz>5%c#taFfMsr0n##Vue z(H%?nr;&E4_h`)PC1$_O#*s+*G=Q)gcbQ7(!bxq}lHSS`rTUJGQYeOAyuc2gQ6L?z7Z?C$w={2gGJ*uI4lCArNi-S2aZhr+h9u=Ti6ucopx@$< zc&6PCfJ~^G0_4PJaayp;a6TK=j}JVJngF_%YC!ZuG%`lOpHO=)%r!Znta-zDPScg_ zI|J)Ra1NIPgtjyVB~U6WNEOi*03A~P*$Opdv0;Fqip#LeG!VVK#lnJ0TWi})(SRX3 zM$W{NQH++1eLhm$*(#jEyU2!S=xrPm@9)SEhyt;BiH~E*lL33B>Pq^!J^85sI;(sr%Yw^EXOu$nA`_%q_e2>|#YL6W1 zV0q%!KY>FY?^Vpfmoyi%^u3+N+Y-DGyk)dp z#q?1LJl^EVgyA9M4Qq7Kqp;MMjBe0(Jimo1Y)KtIR%@`Bkb4Z+km*#X`OXpErCQ6j zBFYf6ELAP>;Hi%`J@)-5zVDGVO=7kvUZpbhTET!2+NjdfqKolLj_WdMA$#+w)d@lu zhpZOO24$#5vnWHrgiPVtBY%>d+&ro{=zE=`0q%G>YWps}gJd3QrpX@_XeuLZFe5P0 zWpWu>=)ehM&*>${vG`WMO;UbyMFPum-=bHFpEb-rk~Dkld##0T1J5lVw@&i@vk3Xm zu@l?r|LTgK|7Uq+rOf~Nl=OdQnK|i|%wa2xb!1{#(2hGUZ}Fm;iy3nlJZC27F0xTD zqYv9W&J&!RvOt#2#$uhiLb0Y9Ic<|1bxD}Y`4oZ7yIzQ?26%x(nrGa_yjrzldPF-L zc882s;dhKrXc^~2T4bz`v2w-)kp`3tQtQs_)h&F|rvAiMSvSKQTg$!`dtzIVbF;B- zQb21P%O-JZvOZsB(A4Cg5?@w_0>Xmq7|4Y|%$5i#3HGXY7m$8vWsBK6~Sb>;W;YhpC)K{v}Xh3TO*xJO6ZY8KHjAFi>IW73@vL1uY zMi2Yl_y)a0i)a%yQ7f~68n@|OPD!kb9vaS-wx4(=lgh-DQmux;7n)uf$~CJ`hkG?> z5u=OD546^9+S@lg((C>;8K!*kNJ835rH1|oH9^3_Lc%F(!GjS7UyAH%-6)CH2##cO zp^V8I$v(+@@m;zdPpbb-IIJR1#B=n&YfGB`ce%M-#{YZ<{jZQ)+@Abp7<)aF$i)xJ zZw2+oK>3Ne=ybyHMDjbAT_?t&mvS#O9)DdfG74*rg+^ncPg+C^5S*;DjOzh|;{E3N ze>s+JsK^P!FsYsOHAi2~i<*_4TFQ*Vrs#ZUkZ?EPNxm_yGN0CaV)kU76~VP(8Glv| zh63pwdLy3ZpP`+4_jWFQPD+U^jN&fHMzrXlvIfpo6o*a+7E!Y?rt)bT4`EvsS@ktD z&B!k6(qVE^nvPCU@E@I3$S)Pnwxrc`e(vb3LKu^z<`irIBzrpZf5}8O1FO+OEFt{a zxv{Cp{3X?ml_N|{`ziOBQ#%N+yx8e|@}gKBNWPQ>30OPZH9_~B=r-V8d}_V)g!k?G<)=C2Mjm1|OvE&~h~$A=9w#wZj3Z#r*HpHEJ&T)|HK@;J z%s~~ND3OK9g4Bw02xG7av(=VQ$T^J1I*iFX6ks0EhM@ndEDZ#w^~!Q2{Uw))S*$B7 zQq2{q=89bNTKsEOYPTx2Tb0_aO6}I9c570*HL2aYRC8Ubxt`QKFRY(7a8Bc@p(S0I zN0O}p_qA$KUt5)6(w=ff74=KTag{bq$Vub96M4~Q18X3*!qB-VDzmfmnxsgSM&Z7nh--5f-^s|G%mT-AWOEbCUr zm%)j@68+zAvN>-G`oG2IqNe{_Y?kp~p3nc&qPqL7^!gk}{RX;Z{5FBFr*iG4 zSa5tCN#>1D&>`2yTtBIwF~@j2p+oC!>Bu@OM^?zwbh_S&W9$D;W}yFT>iWN>(*FN^ z`oEKW*Su2y2XN>o#W?hn3G{y_v(WzyUz+~!Q~;Jg-<1CEWcvC)Aph^u z%IacC|Gzc;-$^k~zf%7<6Yipj{%>3r-}K*x564#ZoyYL!X zcB$)o<_Fl{o!+f{P+sccUXTCZ>C^cCmHNMD)c>94zrQW@e*lMmT8u+Kok0J0It%^Z z?Mu`DotFN8rTVY@dBOU>)2ZwK)|Np1Um5@To74ZD7JJHD>i=fKUCcuNC)HmvG*}W_ zL>|d*L8Easl`l)_C(fUoPEW0PJGNT!bS7%W+fuDaSHZ4UJS{y4OReGy)+(kbYXWUu z+V&gNWXj}VRvRb1PM&nQSC6u@QOOM(ArI)SBK7FJr`?OSLKV59p zrTlB9uxZbFJI>#hS*D&;|9=p8ejNQ0dhSA-{QqMR_Q{DZZUC^$|IMX!-T$|_v{K6d zPp|(c`}?>6n@_3S&rW7?CN&w{EPR_AC))i)6!W^F=V~f{aH$MBeCXb!0;PE%Ka&xd zboj}rou1sb=Ar)r3gF!Qf6GAp$1?u&H=+N1N|N%jY04vr z$`etQY+O&Tt$LK2s*V;LOHEX^K?Uk*V0#oI*7cH&MiiS^5Y0OTfL17Htfnw_7 zQhY2Z|IxG`Mclk5qyNp7^)=Q1tGTvR+JB!z{*!a2Pfn}127{j0afpq@60exYL>4N; zVUan|0+|^KMOjwBMaAJo#Q+}Rcnp|FIJSZX*_a$ICSjSZ0i$!`MRQQ^gQ4#_;eDF+ zK2lkZ1YB;-4Co&_dpqyj{$LnGfUfQ@oa{_2;AjxyC<+$9RwB@YKmVf^XTh_BE7iQo z19;>3CU8j;xctu`{CwRDzF5}LI9^~t*?9N<+`hs6qO0J4A)B-SH_CvXZXF#I1$pa4 zg9WI83~r3AN+DV|YCGulJRdvZuG95#?EOO>j&K}%eiv*FmWqv!L&x)vaTFg7 zdR`2JFxC++&dz%i4$_N+W`w>JJ$Xec3sPgx@$nbu7H<#Z;QAT@Xs#mc4kXd(!X>DP z$)NmR5X$dXD1Q`$@`n}5&K*GxUi|xk6W=TywBK*pL6T|F zO!l$-Q4q=>FqDO#ewsr+p+nsDqBy)qeP=N6{4PrPdn))xsOm&0zQOm%84R!!BF{%L z?hkrSjH4P6KjRzhg-r2)qXq$aeB(vPqs>s{`Q08yQ7{ZU7zNkF2`0Wl*Fl(d#CxWV z7cz~8n1AWuaR0RZVdwDTaOaoy(edGbTdJDEe2ZF1q6c#oMOhA={}jsapaxoM|A(#p zANlRuw)X7;{R2Cm^$!%P{oC5N^V|P!YyW$Gd)r-1;n*tK;6Z2u1`5?wAj3311y?9| zF-+i97$-$woZ4ZW7J&irJ}Mxnjsi`mwmTC};e24(Y zSVz5S8C#`@Y}tJSIWGlHE=Q7r%dM&IV*z$2+t~t@Ra^y$LK(7xN;L?8Od&u3N)-r@ zq>}=G3W4^vF&N6#l?Da4Y;D2fx5WKfOqG-=YO>rwhqx1j?$3}8=d40pv>e~9oYxUt zfkpp2e<$~IG`#x4<=?C$Mw270sHG2!4xIBKi2$9bf>{s42)pQtU~k+Rl0!rWMdy#c z++d$+rbUiL;65k-FG5c5i*p|#d^cd(c;WzEVML^Gl01ciNn0brZg_q~vJ!btj9rNz z0S!DGHhtC`qk`ZKpmPwiRz*OONfjYB1GG!VR9IvTaPBO9W7B;i;WuU0jq!*U7Excr z1i^88*JpfBxI)gMscc@_^@;BVJ_8V3Bd3?0m2@m@>pGkX{eVO77Q2igCY)%PFuG&{ z6j0<``5;g)}|AY-(F+8jDrgP*IW@z&17>5)6b$N$lx&koS_(C@@_DgigGAjdov zHhM3P=t7f`5?KGHu~3;|ZXO-qV0k~tc6c%0j7ZuIp>@(H13(Nb$tR(bVj|&{v3gyr z{b5A&<#lf8QmcoGt}4&-O~*s7=(X3wHQE=m+C*r}&n8aJ1l_d1hd3fPS6w68l3K+g zW)dS7v{+jUFG55Avmbo%A>kt34Yn1@-c^|=jkuNdWB}v4tmwxn#iS4U3``xSV0DvH z6DAXNkc`z$l&PN2Ce&@bVBNs^)(zZj-N2#N4ct#1X4UF8&Z`dao%KQ-OWh(l)Y7ZhVO0BMZZGCu@AiT#r5l(~V`^{>Szp@&Csw?+rwrnED z^?>%t8#?SJ+$wMa>=s-Zn#dC8g8~e#GPo`OURn1#;x9Rr@03F}FLp}yg=Y11mFnV_ z)gOPT#UrPjv7Do-9MEx2WL-N*bqfxuD>uK+&J#$G%AaTT|6yl&x?Dic`;X;i)&IA- zyuMia|2`%CmoP<&*rcx+zL)WcSX=lkc#v@PlsSs<528nafQba_zwlMG`3Xoatt@@b zCy*LxWY{mWgzw96I8w|E)he0HkY!pY`vfu?QeEY{Mw~KO8r_zwcugd?sbO0|Mz+b8Z zI5k(BoWQd}vm?FNkrAxd-*Vh`B9Mm%uP}7z;wL>-kQPc9ZWQ!WN>4 zD+xP3AUn#7Aa@*E1bXnKCB|k3hoCtr@Mu8~QVKB7jnq9Ftk~>bDmRBbOr;uzaedf4k}TS(9?3-A-+nCuRAD4Ave|0Q5y5zW^VxKV%xPDI#E zax~)r;aeQui|xU{Hi%>Ud2&}#)en%9*f?vAIU&T1v=$9GNKVJ#BwQl_>*f{~&>^1Z z=Yt@a^c->KnIeu(;NN23!+r;+7T9svD+@ni;X+J2!z0*`f~-+4yEzLU*T5@2nm;wM z#>F|sJh8?sqD&(26cjV^<&{aKAXug<{lH#`{cj4^zOntkm)A7^uchY7T510){l8zJ z|92wy3NBHAD9n{3i4PU0jiRFz$FZWb6ho@}+3$(d6#YYRoKj^f_VM*PiGSB#;_7DB zB^3bsOZ1DQAKKd*C1FLzD0|ym2l?4wxaKtA+&qBJ0%*&kdOJ+}VmV!a{HmBd1 z$9c(V*y+FM{yjA=AjkiEWpP#W|65)xA~01xMY%2dXB1 za)Z9(`6MkAT>{6C)f!oP;TF#>Jl!Nt!0y#r#lqSpxq4etlEh@a!?{0w&ZpON-t|IE)ffw2;Lj)Q!Ms|rl7e(Invr^6D&(TM zxX7P8rF3Go!9U3aqPe)36iBpTnSCD_Q@eI|tfciU9Rx$? zS)JFDKz?BX;i%{N@x1Fr&Q%Z3`vjE}M>2*!=lj%?JDMLxc%Fa-kVkypmc%SnC0rtu^eymiXLz7d!E zXKf%#Bz{)T4Y(UB3-WeO&ZNU?Ul5UmF(X0+#(^_)cfxTC^^w;f^e{2$M#&6$1ciVQ zxfZI{(8jx@=uNiWjHX-=s@5_Vb9R}K&W!vKswB?U8lu4W6%Bp<+5=RpU3=Y@ zv`jTYE0xF}ti04vS^a-F`k$5oILH38vaZK}TwX2X|GYZK5u_BR{&VWD>9i$-0s_KTxc> z-~|;~C6Y^?H1$rTYfiG4gUJbOc!4YkN5d08+H3K`(%w2N8gq;C)gaX6$TdZUAXYfKuX;fSA) zGqFj6`>yIy^|1W4*5a>=$@6*KCvT6B;Ssz5{@-@}Cl&{C`2Y1qjsIU;B08b+{(oQh ze^LZ6EexQAaTw?7vj7Uf{ijhH3Sj`w_AM-+f5*{0i+nJTiPb>}=r9OL44&A-QLDhD zBwmtmy=0B5s*Qv5ywpNL;QtIRbi!f1tFm82Ge^dCMM)<#3Q!AKLFvX8FKR@XFpUG= zOC3=_aA#yjoc*;`6a)br!|M;m=Fl?sm zSIb0MmpSv~0CT3vYUR$7N+FM)Bol_n9NBN?DYE|TGvv_h6J(W)^GnRnOd@SCUFJc0 zpDFiHPfEKu-v8qB()$lM>V)2a2usxr1JtO7bH@JPIS~#ENCi3k|N63O|5;jYu9W^? z&p`h{&!{}tC|lkqt`jp?F$br%h7_Ps6Tcj9;KVl-lP5M5F*70J=01KVz)fD*Nr%() z|0%pg#H$*Z(}W(lx&EJd*S~;NkZ1p0)!u(Bt*(~*|1;cwvcVHNYR=6XlVm~I3tts6 zCWaNA!1zSgtAlG}ba0$D*2%^-mIGqSf*3JT=5jYNMq)6g=&i^mYI0QsmbRFqV(IKO z3IAtF5>Zeioa_Ii`Ts91t(5xTXTbm2HWx6oDgk~n6Y?Yc{MAsFLMRA@WN@_WrG{oO z{47IBUUWiYMA90kPUsP*%4oBNu7aS49iOmHJf7;mqhY`Ag!f70$4GR$CCHe?bxoAS z&Q%nLPA9?o@GbfID8>Bx;%w;O>S$*>bA^XywE=#vQ`z-n5FTRR#UTlbxq*((Dy|bd zmGgJ%AhO|+4)w+f8A|7v<27CIy&yoP+PceWviA9znn2cV+-zYYBtvH)IrAjbjMu@@0tktAM=ldO zX*VRW^kXuRz(@GbAx@GlQt9&YlKk^Ct;3*gJS2BjcwIJ1AtuukswJPYO4s~S3zf)o zGV+d$Am2v%RJJxk3-7Xl6p)1U7rZY^8ZyajcEWb;;hr0{P#`>QAU=aES3$ZMS!9#s zQlzmv(z2uYzK31%1R|?rkz&;Kd^`7~{J)0&AFcmiT3*xae@iRtrT_mokN;;(07?q* zBov@H=6{L8&~yob7-XOzIVeC6^w$a8M}%B~9X}3<^N8e@!pku)qf$u%zt-qGgKG8c zGrs4ZD(CcV#hCR>578AO_kTIlk}2U@d{eMDcsqDp0SsW(=h z{GZpdzYB>+Qzn+*rTr%-N9^O}zg1oTx7=J>FX{i&(|@wRPaFGjn`FKUyCn0~0m%)A z<4oz-SYZEkvN{V;eVqfD-1$H};Tk8B=d1)ZR-KhTcSFzBoD0B(H+VFG8J%U{0%#ys zkEUc)PZHA*j%PS6M=IT23R*DMC&^ZS4;`uMAo;BY9?@D0-3Fff`okU;^#3xW|3}Mz z%Ztmay8qX5ssDRQ{6D*=+fPVRz9*XU2%_>tR3#giF*w`I!mm9l^jaM?rxtxpe=H!y zW3v@gVB5+g=ocNhY*rL}dX9zcJQ^Gep&Kwp1jNaC2`R@edrv|YFAwUIcv_mMWop`s z`Lv&gFzW`nYJEZ+Zo{$Aeye73#+`MrGq zGeiDQ%I`d-0Khr^A4_`v_m$>q$^Si%|Hn&+|I3fxM8SWH2Wpghv4myR>rE0PSc0NO zo04*Kq}i^MlumL0z_)XHC_MHp2}sy>TPTW&n*x7x!@~LrY6d6l;#jUkX-Ov_P}R?@ zfAuRhf5YD zVCEIHpqKmo6lNWMf2OCk>ZJ!(H>@R$ z6^Bx~aLm&FCzJmv1%S@6|24JzU(My!^8N4YqyH~C{__MZ#dLUzI_l4u&#*HZ2^xht zj4TD19Amie4C(-zk$o3gjY_3%XEQ3hTL%{(wvM+db(PhqbbG;-(-R7~j!pQIFdAZz zV1dWDc6t$aJmmg@TD)RC(6AwLF%+?Qlq~V%*@?&S6LT<|@J+|mCckxVoG>mBT3hBa z46(Ia=m?In-Dot_yHO}2bvijyzZN zoz<~ZH6j1DAlM~0_HF8aY~*NCbx>~nZ%zNRzF5Bhc@F+>3h{sWv3XSRZ$LA%0RRRY z)3HR(Z8WFyaf5rdi^IA2lL+lY5t$hwUzbK|Nr~C|C1qr>0tmZ`1e>> zfBfj*z!V=H{u^AjN#cL&OFdceZ!?@}ME=gW+Ty{Yp%Dq(F`1w6r+Jn_-KxOU6>5{>i{4^_7ary0p|uuwr}{ zhxA3esF+RK{OUwEvSD|WSd6_Gnod>o5=v_6UW&|)N0qg7;JZSn)y&QZuc7|J{~>R- zBh3R;;N^g+Fm_Ej7wNdZPy1gH^gp&3m?!_OXz{-mn=9q}zY_nO@c)zuz;r0U>mmUl z>VFojKSi`Z4ZJ_L^sSz|H}=gptq3GGr5i?CD?3IjB%c~LPIMz0jYf6hec+>a6B=7T zyC4djwCJtg3YvK-1->5nFM5msm}mbXwjPE4uP?2X^#7^p|KyYuFb zAQnwfOr#Nl#3@w7dQma77n!J-K{ko5#a?eGuH<#B+{QsTve?-rc;G+vqc+oU6H^@cHM>yVWNlmQq>?8;RreR10iUmpPsHZDB3&K|4PlvQ~~Q%HXNx7|-iBn_P3jmC@mR+#=b7d8EVbE%B~_8j*A z-CnZSPa6fEzn%qyM&Qys3${`Zf-ya< zI0%EQ9`0XsoEUe5@II?HQrAjwwHVDPP(BF&%NQvZ2UdS^El){}+oI2=65?)%qsR;V zN;)q+00+D)r40QI%Kv%fe~R+|^4hxY|Gl7KY-rr`MquGOkXk9V(z5 zx+YnOy}-Y?!9DlFi7sLs#TO9?(dQ5QSIH{E${)+pmui%6S^r}u{{^)`dHNrK{+IqA z-;Vz0Sy+nKrUjZVQ!$w?C?;c=Cp2L`BBK~nCuE^6i;X2&(eor+4pa9iY)+~45tKg4 z+89+o#_cK6>|c96dR^-dTORK6C6`Y$`lDfD>)_;2PT%&ZzI4lX=&w>5cRMs z$j4W&LHnameH?X;-|jnI;uCCA&J(JYe8IdtE2|~w8@jeyr$#NJZ zdVTpP5#&J$U7)jhf_Fhh!1pJgXKM&c-PAPLLxp($lIyt zD`xJZ!b#+K`=aSB3ZH_=XFZ?3)-UU_log!e}S z&;LLr87ugY-d(|=bc{nM>vL8yl~>NkQ8x`j@79U2z-s&6-$T5^(>ng?#W$avE1W#9 zegX|t#$gc_G2#4=;`<(UWet^avqa~q-gOXmu#_y6{8WZsE17de*#fc77tbXx4fMBd zNrhlQ7Cox8fOp)UPfoW1x)@9MtuQCki4rFj4LpC#@AfF?E1DU>l_Vm z$HQQSqN}0|82Gd3+S-=Rab3c_TgE^Gf8^8&aX+}V)G_UW0n12RV5su^yOAccwZWw% zi(vc6aJIjPZ8lQ}ai`6Qcs!IMbq&#hiNRe@3mD{&S&U3iL;qhy{IgpGtn%Mdb6Jo7 zu)Mxp+JCdPWbeQu`aggz)$KBU>vVX;#$RyeI})URCjeBHw5oJ}?P zZ+doUG@W@?X~7TXaeols&!1^#>|IY;w-5isnM`z(qMYH>4aI!ZfSW`{E_lF2$(U?(TB z*X8SJCQ#IjtEm}VRWp{ZW_rq+aZHtk)isGwcXs~#W=zS5S2S0Ucw$*Y_)H}?g!m0? z8Y^vXQlzhr#dz#gsK$Dmn~cI}kipZbf`uy?VZtX^1!|~egsLBN6(Uf>0IgGKJv)}w zl;u{9dTK&>K{BjJ%q&%u;qH+5l~QMoMuT8W68BOH3c1;M??hg-*}xi%tuS=%(bume z5@t4n^QW-so7JMQjo)+(mGBE@t(XZcd=)jY5btM%saMtkTGTowu*UnX0S6T~Ca}Q8 zQ2-WFBhmo9p5JELMC;jY^swKJZ|Zt`=WgQm%9tzQpc_=#*~kKcHYjrqs{O#_qSfor z#J&Eo-$L_E6$$Wpv0|-MU1_7v{KYMAI#PX2nSfF;o;g-NKFFmUkV_g!6A~9eOIW)2 zNsyY^*Q&@U7!ff~kdmB z=ACF}bYy3!y98meVygsB$H-O{;H3(3QU%zj;=E2V2B!!!mdAl?y;G1SUD&N#=(26w zwr#7+wr$(CZChQo%`UsD%huZU{ePS|`(od&$eWcBnK|cp$MZ~0L&%^uFnO(N$nMlJ z;|WIP+We6F4GENR#Q+JG2of$gPNlL1sRX|yG$wOq;!JydQUUi)QCWf=UwYfctBiD;1C-ZGgUjX05@hZ=4Ang?_U_Iz-6YFqI&%Zn z$0Yuk5q2CrTxcFHAR1@|$c)haWW(Sn!ki-O{C7IY6R_yhpwhIxZi9-{_GEGMR4B5U z)7>Q<1oZjn(nTn*2ls_fEmQFDav&zZSo5(HU>2@WmKsAQ{F01Ovi3RZ4kJ&iT@L%{ z8CjYJs$`><#>PNuM?{|9DDWC~Fk!w`Szx#n+c*X%OL5@_m~n|Bt#N0I|5C&0E4Hu7 zy%wLG$^6D0!1h5y^cOsNoj%1Mcf63VU4JM(qjTA)(P*F~6o9d#)K96&Chc2a;T%AA z^)C>G+ZPw+T1auw`_HvC8w6!6xRpk`OFZm~#+fR8(HngUfns-6tn}df? zf>)8%;`ft-&4=6_Dq|O?s;o~Km-bJHEY;b=fXfZZg$h$mgE}7^@z-T2zCl&ds`w#S zhS$YT$H9)=GWwLyyJC4ppr-z_PD624ZT(1vzK7R*v3Y<8lHmP;fBnUsfO`7m=Pm;f zz+A5e9Xmk{nXl%=32Hz^1!O%`PUu!#qa}tqW@%ECup|MB9)^OHX|ryPqN}PuUhC}Y zet&-qVsbHADSj4xPNH~gY}PLM3~V zK*<_N%s3-u(ehh{nQ#NWKQ|3|9OvvlW=_+Fh5KQ40f2~bojvNx04bcr!D14$q;Mu7 z29+uN@s6g(EM*bmC%o3%ABhrP)$H$k9hUb||Iq9o+HnXsSaA3#UwLyv6o~hA`8mx~ zzcTNNNQ~gg4~^FsT|L$MFl8w!hMA5v-&)^95KBMhlqLjJcFD*|GqP47?|$VVil_||Y%Dh5|k~S@9xhsk}r2y+=4S~I`(3APe#vSjk*A7NX6R_;$!pMgk7Ij zx_RI)EvaEqBn2Mq`TcV>N5OFZSgRehnshY%gX*AutMb6U)|f8#(m6Go#pltfG6w+#AWEu3PQ_SE*j9=)zbC* z-d|xHz*i8QJM{b={`@@hGoM%B!J-Mj$*KOpobw(S1Pa&N^UC#<{)g=^hS<##{c;H2 zmePyHF#PEQYCrsAQ_X_IJos2%h?=4z@@ulI10`LUoqs)=Xzl>6hXuLdd zqo<$!`Dc1JooVxqo8hzpwgU$P`(lg_PocxPDY-MY= zV2nV5o0O;PBiDe3(te@ZQ^n#4&Gm;Sg2E!LvNTTME zO2TEg58CSyYV0^3;i?|#{Z7bia`yKC7s0C7Ze$TsSIq=aGZS?6$S4xTmOSR+xbvr# z99}o`n#-*&uKk4A5s~yo0=k6u0uq{NvDLM8tf;ic&M#&nT~Fpg)5popPp1crkw1c9 zuCC4n5H*Wwm(8cAE z{rgZS&j%XCD`XW2YX??cEhW|~Gs}FD4^gXh3;Na6lwqZ%s>jf)-xUB23(?z18)~7? zq`#%=z(R{+U`7Qbs~M{L$s#vrVsqZG;$>2CW#REe1}T7o5H|U!GL(F-gWyZ}%Yj{w z?ZPoo=XMF1PfkY9T9f^LA+aR3_XNlO=*grE{gKVsq3KC3eMR->h_rQb-9-TIS6}ES z#uLcQ0-*l#n_%Xt)JzJHpYT0L57=62LX`p?8keie0h|Eae@zeiDXVux@>f$)uNt1#23tdt9c?P4ty&bK@KEksd9(>?`v=SM-y z9r|}Q9-Sb9-|tn|)#eO!N6gT1TvYWsTeNDlX~(eWMqwD1L7aZQCf;VOAF438bLXg% zs~diKrFbQpKk@5*fUe9*pv%#xUBV0zB4q3~(lKNU3A4R*Cbj;5t5cKfknXg~XEVz< z#6)A~7_46DUhK(*?I~q+LY9dO_mA2K99gnT_J5ivTeP)wNa@5^T|&yPPf6W`U->ns zSB0EDPq;v>8_RjoION8rH_kPOjnOi%#>n45ouR6H+;mStADUr<&OvKy+%}^VPvxyq zPl7a)sk8!%Mv8O#K>$BvSQwvv?S9E?066EULOrHCkh_g^fES_N@nNo-Bdm!BhXKaH9`8UFh z+%DehP*>*>CtKG?vy(RYmBBvi@S)=U`r8#H*$qozS zO7ixsPt1q{M$+oA~z zZ-Ckw+Vr>Gd=WrCl8+q!%`ZDQ*|5en7OC^kjk5PJQXbxe0Z%aoiBZSiDeqmTQq+4f zr}3$Kz7DQ?XXGvM(tVt=Bjxl9en{7!!(jHf1pqvI%Fp7wodO~}k8v+zWv$VN^Op_t z9K0xk8t<|PfO2p|>4fQwo1iPf=vgA`BORpE2>JW6jqUf-UezPxWS(lo>k_AL`mekt zwsLRF_$WS8dn+ml;K;gw-?9(_3Tf_n6?meSzkN@p-H1PuN~UFZsGFUhHI&m#^(65R z{G1NfFAX|>@93#u`LfVrzzh4t4qeTUmqM{5z;Ccp-nlk(5$)7sfE9iYhB$z9h~%Jn zV$`@Vm?1CCC-(uNpd7SBGIBW=5u`Zo-0%_$iRtEA$?4G%Z?*asArr1`N#E@MvB7}Kgv%`)@p(ttLqC#Hm0Q^GxC}9NuM6gF>o;OTB0)@iLOEp z6((j=IC%pB5w5*#fee=ucj`_<$eF%HUC~iFOE~P0(2Lk@^qya{5A;F*TsWTl%(NJh z!oSnU9@;WpG_^(ScH&O_ZIEx`I$y3t_))vFZ>h(s^ijxoQW5|k3cecc4YpqvPJ~cr zx=2mJ)T^n$jAT5!lamRQFL6PIDfDK&GX5hfwu%zG7w#xSJLasjpFvwOs7tG|64juw zn-oUOY^Y$RvU_u(S(Tj>4i=g_-^(tL$T&l*bF0&_?0MQ;hcMapC7$tw>tSy*aLoyTAd5&sc6>bka6`u7Kf08`k z=0F4V319eE(-i!ic)ocbg${5xbu9gfZ(42uk=`OE8t*E)35R2e71|U7PZ>9%(f&M} zWd53g3GZFWd#G3NsLuUu5LzZG5RKTd)(rj`q$WTd%(zuvlkA z=_G9SZhr+IcfkSO)Nv(gU13!4piFb>GFp)Jj6ypRE2-kG zQcm_sebf=dszoZw_|ELuu~y8(a*vF{icNi_vs9STY$~2~Fa#=c>9vq9NQZf#|y+yTxfibW(15jly`D0OGN-j?fq}Po|8C3+K$j8mj?(dC?n1y4@f7 zw9S(WM-fw)m&Z!6Wf}_q2gG_7xw;wi2SS(TjGe|uVd)ZQX>1JXB0kWzA=A)T0#tx{ z@HT?gy?e3kHN?|6b~&}QeVMx1NA66(%aAdh$6?m3nca|g3J(QD7&~%9a`@T&=0w?W z)z!LH8<(_SgiXQ$xb*b|$oZZ+2w!(+LuyofrO`-@6DHe4t}H%ucZt)g+jr~{t34|= zavZ-#T4^=1D{zeR^Aio@n>cN*BA6L64&JXxXv2#3Oe7AlYCUJHI`#LbYSbYLu;N07 z79n39D21K*+l(CXKMThCts>RLX(l!Se~P)w$xIhDTJkicCP=GyiCsx;QbTSg2dkm6 z40=UzGXhrBmlX3ySfQZe$srC4D2ubCqTs?rL#TqgvqyT{h4d2=8W(}HeU092GP|^FX#2q6Dh#fd3&L?S^-Pcfk!^iHZFt**bCA}zqZ4~YCfSM~OFxvmM8l?+?U`_SnHwsAI5rh{` zF4_zNHK-Dm?+amVof`Vvc}!MO-7K?f(4*!%-)rq6HNQdD`RhmxQ)*sN=Q$aF;$^?z z)#$#&2GL9CY-C4()AH#U{NqenH&td|T1fAL5N;9vuxuf$8jm=F{isH&)(%K-Z#Z*S z&#zYHOER-TmWG5qr2okCIU64+<|OLF$nqt#@CqUGA=E9OD$Y8wLCaD)MI1K=7Mye2 zjaa8PmJ+!pib@5X342emgPc`d^QP{cQ3AEl-zRhA7A^%beV`d;@CIU`x# z^f#t3Z=9@(3R^)N=`Lx)ODXsvAG`v0OsmnEI4-nKxtT;sklj!N^ZOLlfZVCm8z@-h zACEh@d__=45MfmM80Yf48^7iHF1P2|qr2Rx6XqbNS0WY`8s?DA3dc%%(*r5eiD%ao z=-UgQnH{l_T>p;rh0F!r;p-{oX@rTMiRsg`mhoKtzj0Y3 z7tZ0i&@4O{)+G54AZJ~Q?5AU#lvFaKsf?+2X#uX2iWj0Zg>ml-GKN%bsC+YT3TG22 z+dztux!%C&6dgckHJ!JB@7>d5zJ8*9#-6Hd2Y&gohs1Zx-?wnf`5-99qYJkeKlmgP zd1cnyKSY>N1GuJpp?X4$o)rp+TM2CAn=l>uEwe(v(zs`JHpP!V*;9iX^_UvPT5A6KUH#|)ii5b)5h`x#pxb?YU6f9 z>U~CX0{TFSH0B54LE*w%nMRUoyWSPLB=8xLEn3A!D!XqnC^8PXh^*c+@VJGsvL7O7 z!fm0HL77ifp=DGRKS$?y)$piH?<#D03e_B$IcFs?SM?vF`U1nP2|a^z%rG<%i~NhRPMk2rGyXWkDn^aY4R4mmpA{OpD41|WwEGttm(>6U?(JGHz&VCv3>25bKpv|j2Ca_E#sI0pbm3OJ( z6xUqIE_?;g)A2uZo_kmL_sGv@lp7c5vG}b*SU0RQ3v4dKtnFExc)CiDXK-BM`13FU%J+ua_er~E~XGVpLL z?+crGN%G=+6(bmTBMJRctcnu}2U1ci?2r@M95I{sSYs*f)C}$3aQMur%J@ z9}T-v-&+;ZD>N!*P?W~)H}$F<@+{ORBD=OrT2M3?rj0B>s{8aXqOEOjY7<#QoarLi zY6ZTk+`^&>yjwzKPexv*gu;U@fI8pf}OLTommk^x?;`q$?ni4u8a`>iM_ivz)BAmt%w? zMEAuyV9gQQrybXBh#_^SJWT5P-{9YL@P~(j+q{Q|dS`oSK3~ay05iq_3V*i_6nWdlsleK(>f0qTHkU+V3j20S#%GsT=|S38 zT{0HL3-$^4Cb-)u_iar<`yiu7h!m&ebwWwr!n?{+^UgXHT7J7GU^Y}I? z+8~9JUng1qA$iW?70n4R(7fy6msz5HoPTD6Y98PhDhE{34)OA_Oy}AY2UKiVo8AsW zWFx&))P8Uu52U5>2xiu%J9|GqkacF!>kF|FW$ z_Y@B0#ZcoB>LVyo@D3^0JkmaL^~DuuGqQIvLgnT!QdejUP9O$wzaPLgL?;C+w@kr6w{ z92mK7u{axY==@|c3OkG2EGe^k2)jzruXvZ8X0Ag^;WAI!pN18CpH(d z3F>yLw;^EjkHq@qj&E)wZHO#S9zo#|dm{?!9Y?0>?gEitwGs)iqpVX_*+vhe08B`) zlujmbNbW3LU!Ml&cTi)!tAne;K=phqlx5{Q)9%=v+@AQu5ae7k-yDav!#0>fF?LKb z>$H>-`a|?5mc?zImMeEI_k<;u(|a`U?uh$nvK)D8MK}VtlV}Yz|^s3BWdGICMLHzyyf$X^*U0*_+R0Ez7e1$ ztC_^hKENr)y4~Ul+jG7oRLWXR|GgU&%|5vY|BXL@#0C;2TTRXmDxXcJ+M51u6Hr3L z@+V+z!{J=E9Fq_7I&PZSMoE5A6TEMlk0$I8*B6t$xcXMOq8U?gIv53 z#T#!Ksu9KbzCpI5c*XG9Tc)Q6OqP}I$2$kb|9~PqJ8Y@^0LmKEWwL8_1K_~_fOrSq zeCvBU`I+*XyLx)o9s%+a0NI(Bc)h3KZAodFP?sKm92nTb#g%rN5talDc$H=YiW((Q zk71>Zr3;lRQ}?J3=5U72eEIc z{_sqs{**&K)_Aarjyf>ofFsv3C|KzDWYMJ~L6DOn;@7%oje#98^V70}zguS45D#j& ziea<0HLX*D%Lfas2u{iTx3Im9!nCp680EAfUS2f~Dr3+=a2QnjVLF`xvnIP5l&^1O zNxEvX|4C8Px^By-N!gDrK|8Rgj&?_dJA;-2p%?IwarTTEd-=jy*;jI&2V_fex60IU zE<1-swhI+1uZCSSKtQ&p5;ya)HwU<7ld?Vk>EOV;egBb@rL_e>jx~krs~Vq_(++k} ztrGA&07X{w$6QQX5;;C5t%z3kZB~dIBQ8Y#?nOWPZjXC$-`c`}_>lN_`24-2q{}9T zWjhHdlckL%;GLtUdmZ?kClFuH?QsXJ?}5viFvzUrst~9g7|DsT1D}}^qD`mop=tx*Y>*iICpeE6!yCI3>Dx@8Q>_z zdqlEdLWa%7qdf68d0qUJMSrUjY!qp;QnJS^$%`4j z$;lkcS^|op34vDR4FKA@+E!KX`K==(Ps)IY$7g~2hEOSH*J!%iy{W&;Hi4vN*=rl; zh6j(yq6ka*bY+Tll9HWZ(--MwV%hH}q1i8}GvJ$u^1GU$io27ZR%|$;9%ta$MJg-; zpmckXrmF9omxjb@b{Czik@@lWo-S_ku}%jfV$BBm9Xc;d*x7W2UEolPbfkpe&~<*U zMW7TVDAIC5&_Ky2#DVvr>3|E-@Q%}MF4~z;Ncq*#4Ep;iM$4?Bv;NUpVsyFc1>^$r zWK24tr4qR3YGyfXh3;cq46dAJc5e`zTOG5xVcl1&vnL(yrbo^}V%M-oa8B7-ohhfl zxe%b%e=p(M08XwdcaAuxij6vUpkG)k#BYh#Ht5 zj!@c*@7Z7S6KD5(S4UH8;Q&xmN1OHxD31j=H#o2F0Ooi8aPD{kEGbY1Z*!ep2@X9O zeq-*MJ01h3gRr(bDZH7!XIHyrEo`bs2JI%uXekHIL1u0!L4&dU5f# zXYk5#1a-2yBOJyi1{+bl%U*HO|0%0q3QAZ%(F`XwG#t%RptjT|vk`1cBfC(|$SY#~ z@^JLpynkEU$@Psd!(QwOqhFvQ}TAOoa&< zRGZZ^|3CJaB*wUoubiKcqEkp@Ji-=QjoKD57rON+*A}(a>U>z^obc9klvJ?+=8_xb zMu&KWWzo>ZAi&XIry{wO@NwD9VRG-;MA5fM(=?!qtp&<&$0mm^uNb{bb%+0**J`Za zNpNJs`sN}U|L+t5fr~{k0l^t}488tCraEe(asydeq^y#5aH&hlSO%xY3L0NYp^-{$ zhfPI?iynkZj&wWeN^{v6L#Kr>EH*mJ5|P3?m5rBXiID1?M>99iv{6Mq_o=$%hjTXx z8ZLHVF6K_)zYK?5_tn<6svu~ciWS!7cZsT2lL|7*aqU6XiLY%@Ig@Eux{8@nx0#@S zX{l~9X>QW0{zM59baUnLIH9NoO>&Y(jeq>u5D#XiRYO#Hl<}POk0`g*$&1`O@mu>F zNM>$_gb+PhGg;j4RH{_AV8?+os;0zoNK6B>w(u~bHw5=OztBAVTJQaR&}^w9DhoJ> z8)epekc4PT90JhMEgn;7wqgE|ViiZ$W=C+zR=UnR`+SacjuahTy(z`uY5Zz#_I3I^ z9kXo-R7c;f0t@fEE{1Dq>G<6*l&UP6YnsX%ncA8xTiGNhzPg`y?@M@ck!|ylM7gWuJ(<|%z`y5~?2_)=9L;p!+_PfQ?C+-lip`*3-DUhB$ zMe|cHKmQV#_`a|@*9`M$)YiW$!*E`mTb5bCeH_~6ypxlCtng2EsX$W;MWA2NMyqy| zV|K7t7Hj%nGsSjql9Jrj;A4l5F^k(82)e98A>n2}va5jUHwDZ4oXB_QtG}h@7+@H< zWEik3{25+OO2v>}#v4?@i=;L&YTCjWXWH-8q(kZ2!o9De&Byo$zf~VP)t;uTzb&&B zPIZJ=4f1VpG%wvg-Sl+9Bpu97kg55q;)q~08DIf2E-<`azmx<(UrWbueY0=XTm+P- z1Mr2I3mf{WCTR2i$&r;Q;>Zae^2al#{+g{3Cfg@fX5WZ*=afU$@`#M^_%&@Qd}opK zS-&kESp(bHXe1GFXq{KGyF$Z=^$Yv%rgb-r6d>!UC~C!^#Ie3U7%4p9tqZFH#Z z?ZgDB)=Y*)H@r6^nUI5-N5OF3TQZ?D$3=f8h1yL&HCD4DzkB%@A_qE?ZDHg?uEi?9=Ik8 zm^7YD(okAD2?0A&5x6%L`H;L8WjlOF^4xl0peGp=*u*uXEl`=F%y8qTJmIoJ*lKC5 zXSizXzt+V+^_@g|gr3>cnmpA{cJChf1&`G&Frr;L?%?)Gn3o!5>5~+<@k@jb0C8U%UHFBP; zFmR$ruJe<@LJQOqigFoMGI^J@`aP>TDc6dN)FSOa@~Y&7dY=mtwe|!e9K6NkcQg+g zWvS0bN-aG}jY8r+dTP-+)_vLo^_<6u@ixe^b7^_LIetoQf%n-x<2I&YYhC(sg(|Hx z*}Dd~{}0Z)1D=}03Q=@K9BI4v+w*4ny=cM89i>LzS(!!!z0*1kGNLX!9S^>9TqVe7 z3vbU5tgU$5hkL}5$eB?L&|f+bU|rK#lLpkA7XWPiFBREHJVMioWmjCVmItsnd}W z$b9MtdG0&3z~6;)pvW5=<};C(F5>Suyh>DU8X>2=^A6D@yHu|o2wbT=$$PwG>3B7d zNf+?fFzt)rr^4bvBg>tKAfYn>EA<{t2)N6*_5Y#qa(j6Lc}Q52HdHRRg+E{BVH&*+ zGK*p3X4T(J^4ghEKcFk{Hr9kIbGxZisQe#|8Z4kp;1)Ze!YZ48xVw`d?#}c-?rukz z*|28d(G%jlw;-h>FU8HV2QYG4`azgp9YD2C{32xWj3b3D;3?J@y^~BUzB}Va2 zL1^t#mKf~l9FWEa*d2LVDNXwBlYeK($s`6UXa<)!BW}ABsp4g1L<)=zk)HUg_V+L+$9dOGi^Zk@N? za|{;8b?N4#U9R#QeW^7ecExv=*4^d4FQQv}`n1EIh4}IKsSIaW$|p|q6FR61>=hn0Zc@O_w^4+1K=5lBpuk>G)b88#h(iaizbSU+xH zfzBygJk*{^kYzx+P0lZeB_Jf?2Jnviqi9%+f=TlA19}V~ zTQhkl^vn@%G{Ys%Bqs`zaX)rC%}fLbt0=$C5%;2hb8CQ01RxUJvAo?_a(}3#AEc$H zsbmwdwz@X;LZEO@;(Z5LgsIEfLE3fnTcSSsjSLn3@G&s3uP!DJB8HgpTb2~MkyjcN zw&`FlSm=yYjd@33?GIC3I}Kb*DeR{$7Nv#oSN`$4!Z$ME>32Ol8vxLH{Pg1wN&b{Q z-1+%>zq`#koE!Qb)G*#Ua~VXUSyJMjVdfUVi3&l@_Tq*LzJlA%r&rupsae+}tz~@q z#~V@Li^o5G(K!Lu*xvj8bo`h!dgZ_RJZwhYKUU!JHWU5`wLbWMvR0TO>`K;h(XBUJe>ez;s8rSAUP4H*%gA_ZjJo)Vm|M})}&sq zjgpiHUMjp3&th2Dp(cYbqVLhy$GrgO77Z%-DKqTW;6HIlkO@H7Av;0Z$Ctw>}Kx z2y0}uf{Qtgn$*_vUnCtxu;6fz$|885lL#-HS>F03cyOpID`p)P?FZ*Yzj_D(E8I{> zL}ZEHL8ByvHpx&U7&{7%gBI)^a(E|1u)hwitI(&#QRckjoy}<4?RM6ZTrE0_WcsV2 z3R0;;DF4`8v7(&F1;ROtR;SrH)5F*v;wMb*UccF6Jph_BxeAdd7~}jI=I@M{Uxc)} z-@OeYd=}p5LKxVX1-x94wlfUbk@D|Y$n#ZuC7Br48MAnK829emPfw%&qXG=8JH}?x-!71MtO+f{2L^gHCK->c~83W;xNM zvQ*o^PY{1EN$jAafi^ankUS@QNhQfZnyzRc&7L(T#YWe(o25(knORrg*uL*pn6fJFzg#kVPnldL%0c!*e1i3-`{e7Y)r)?(QnJ&rsQ3ER97u_^rG$Ci53>*( ze#+sQE#tTq&b=tbe1yCNK~rf7j2Iq)@hifsATu1Gdb9B95WA(|<`%vxQTHT92(ARk z8-tD$^T+;Wg%f6Tn_52?&!&Dzp1&ocs`9Xl4`p}eZgijW`#K0YGFjTKOiCZ&fAEQS z=tDz;T|u?08j7CKxU!=%3fo348^l7|T*i?>dBl_sbjw+iVL%-94#vZ%f+-N#Z#kC? zg{I_BB!{Qk2sAJw%@zYCl);2OJkmIjeNU7$IdB3WO1N$Kkuo&CKN{(aIwErGHj*P~ zsQU)2Lo90PDPDDh9_RuwxGQ@h!CHW?p}UGH$747A`qdsp!Wfqw7144F>bkP>R`X+T zI;?%(ncXMn{hjvP-F-~i$DzZ2^V=ZQq2ocu+kZ}Zzv8QpC;N7SOknJvZjztJOFxjX zX5SuqxV|vM=)92Opr?=VZibR6T!Vo9PKm#J>R;tl_U zh{vC9`_2j%OLs?9E?wA&^y3+7`&F4gny>KgVLy9fQnipC;oHzgoviI>m81KNc=>Cx zqCNYd1pWt>$5~ZrhkZJnl)xE^&6yk_(`Jw{w?k3wYdWUTj%~))xe#s@P=@y-*9HQ^ zHJwA!`%gO~o1iMF19%>rBS9Y&Z@L`ahd7v2dD{=3)svWEne%PrCb%;RxmDf@Yc z8F%7SJ=887v72z;CNYkVTk`nkg>7QmGS*)R*6g9e?3!dU#8{Vc0#}#5))IVp2~s>< z$_$u>EDe^~y%uYC;loKyzK5^6SHc-;xFS}JHNrJyYkwzwJHS^=CG`Sis3}|=0T`zCb@tOx6|LZ7sKK|EH9xr2PZTZXdeG}N}a_QmU-s|hw;J?go zcXOl3tz@nDxxxSK3OIT-^7g+udv&Ppb*@eJAjI5asU61X*O&tiD03?p*0GV`?q8CDcR=JmqA2TGG@a99g!t-k32uWC4 z^OBB5;6Bn{?uCMR57N=G<#5SsIafjA@-3(Pa5y4&wNv!)xCxrdxzyd^t)_&m!Du%f zhOiZc%_K)%5pzt4wKXLn+o2zKBE`-`+SaL&!2N-@NbEtedb)+GfpC6z;i+=gi~D=F zgg*_t*xF_Cf=W8;5*W!%-n!p%;wOUxe-X|Ncid=K9nrN%Fyk3#uZpam5H2#_mIvW@ zjJqSQSFW*H!eL^>pCV~i2kzl%3u~9jJm+k755xm&-0viH4$B?=ZAU;hXKy1*;`cMx z7u+sVXc-2;56DlG+oEq5Bz_^2A20fbqeB=qBD1R37s9Za4J9DM#vP;A`YY+)}`#4yc7AZ&%AF1G-%N1_#X@s5R+WA5c+?#F+k1K5 z`=S^>zrs8;X8j}G_TD}B&MoSm0Ppbk6%B#idi&8xEl>1P2P&jAuuFC*40*wdeA2=! zLwWJdjmiIL(|vKh0i01B)wZ1#O}Xz3(6(~eB9Y?jt*z~DjX9kRP&Xwo)Z)Eo86HuT z#bD`)c5sSsYJ^Mzx9tSYwR$bir(!0??e>sf9|;$oG1kXo67!l3Y>}{V_|qS`#Viby zwMS6lX`n4)uXFQIH}T+keaG(J>wl<~zYz2ycs!>TyWt1n<7#QrAMyA$oVZH5&F}@4 zEiFIA{+1c4;v$O`+@7CjZ1vM5u}h|)`0X{nKtAR*OF+AbHN}t1xye$Z^AAqVJHKnx z8Eb=EApI0kjAa4XRd5QtH<;U}DF788^0_dmsq~KHY$Bv-8UNT*SKoWw>(0ExM2&Vq zo{NNTuD={ztQNTlF}V*OS1j*YG048DX&8`9$-^>lc)OQGD#Ln7l!8*h0==&%>*r?s z4t6<`5!jMOJ(4nFRW42UphX+Ai-v=h+@bHhnYpEbif@qNq)iOE)?OaknurU{($Aev z^dq6boCZ|^8iT=qVf@RxS#Ue#W89k)1fj&^v@9RHn;*ELu#a#dfg2tX^UY6{ONho? zM@)Uk2T4|25u;rR-HdXJ)4Om<8uLcPYRVfCFEu}hy6zLY>qfb1ij`y#P@qgPi#WC8 zq+fcE0Y;X|#g*cLvlD>EWgU$}fqHfgjj7i;1pOZLk_9U=-$R%XTC7(Cd$ z`H$`X0v*zR=t8w)b@RT=Lge`=4qJjxVIc;j2te@7%6)L-iprLyLz8l=B3ImH7RCXA z%_|q_0SfT?Y4~`#eaIbaH-&ktDYlk={Xlf>r6fDr4_fSZ|2dZk9u(qDUS)_h31tY; znw26&n(00H`8nkf~AFZ1s9k$;iZk307XbXPf?k6 z_;OA@^=4#DzJ1n@h-Es<$bUUvP}K&Ka87t1dy;%gE5Q~YhASs)eRnDR1&#RRM~9xloW~|qp4g&i5%mJoFERRZPt0_0=U)@0g7jr z12kCW%I{9plC+T|>h&h-Gbw)}zoa8ZsC zXbw$7veMWV z`t^mBL{i|#jf8VNi^m_XaI^Dz@sL!Jm%pNo;R>`?Be{Jx=TLYZG3_ZK9i=6TUC|W5 zABm&$UY$=z3$YyCSO;gQ@H9!q&1vylv33QRBy2v_^gJb37W2X?7U+~idE2tIIutAq zDlo65A->1jCG&WugOrO{N6QHQS8McJ?1pw z6l%rYP6?si=+e4fr*RN^vtCkAVoh2lL3q-SS>gL|7cj~Bj4$R3|FO*6!TLjEQB%!Km5w`fq#)4DX{x+P&a1&lxsrdAhDN(+m75ED;Ehnp@u`t zwN9WRvIN{gkH;eN)k1;&C~2KUHk!Hu0GI7N7(7p{BWnn~Mwx2s`mEfQ`{}Bhv=VXS zR>3Amb!u+@Nw-$TZxlnNC7ja^|HNfP(wSd!kbybXdufOgs66>h_n(}C^5rP7Uzom~ z19x!np3+bR#u%X4PpNM zr9U2(6vC@qKSx!kI9MRQSpL-k5MamPGTrnS2}9uQngd?k}aH%taC?#J@I@5_a7q- zW76N)#J;`2qbJ6gkEK*wMok--*lpMwyV(4|P9&8jLdT=;n&_;Z^2+2jCG(kdGs*+Y z(p4sT2 zcPv3li7yxU5kKk7HFJAm5>YHZ*&cX;k1hYC(?!^|^GGtYB3)~)glkyNzEkj$!M=8g z$5y&CLSNH=a+`AjYiUn$*udYt~AQkoPx zkkp{X?jeLgpTm4&0M@49gPdlC zAs-0Au_V{<{mw?&WzsEmGus1OG4?mg zjvj$h{JxLiyR0U4v6*ABxXgMU&&pa?+zE3kOhf8rgR)5`WpCL{XMsM+A+SnryP#DH zors-ddq$AYu7D5hek_9168Y;+Rb6B_K!)GcnB53W9&~3*rm)PFIP4>)A@S20*ZOiH zCfML*PkFFhnsKzPD>1hnkF%g&8Z80(dC!62g8Z;CX(|Ca@T+hyy?}(Lr=xS2jMB93@nw28M9&_!adDGo5XA=1o#ybie(gORdR-_8<%X!o-JvxbF(G63{q-egC=JtvLnMz-MvIG zBup&0pB8d9o|pi)pm?npi*Y+Wz)=}5U8~X82=>2mT>0LV*^dmBFbma6F`Rug@i zDDjIz|6#sdj%SNH^jQ-jpl^Zs?%}B^Nt9Uu;)*@%FCmD)t#2V<&n0oLI;D%Z{>xvn zJi_KKQQX}0dq~=DPv5E{uw#(%=lQU)R&!Lu(A5cSA#vp1X1y6%HI+eWPrJv3HYFq# z!d^N=0)LJZxorC)y~TNa>9VA-Nc{kTp>^(G@);{iBpTf&bAdcK+_7rnSOPaAZr9;| z?ClHpptv(%7YxxZRVTnTH#W~+EZ*Z@0 zFoP?s*63SL{L1-KBEsf%3uWhus6lLPl5mO2(myB^yM9rK;eN@*m(RzQC<#YIaYhsu zlH9haXIvQ9rE|$(i=rk0tIPRm*$YpI!9dPfjlZcf2m|&QD_B5_Me5WKNO5;zNtTIV zFyKHAwnROwHZ7ExF_C9OF&EbREgIzN62vOI$+0}D1V}$5|Cs4=DM^d`=QZbjmtoD> z_9F3YyNm0E94TD;H>vKE?Hk`=?78+r3E5c`F<2J1xJ)WKT}{;hTc1ec<5s7WC%@+o zDXcOB>k_^^SNYBrXelTJ1LJd@7;rM5O>5|KpKBEp`a=IWJp&vO4Ec|`)zhD0JV*Oa z_WOids<##gqC#9lk$P7wbX$EkE#)Wpn$Sl+{)}k3{_wXL#Kf4^(s_*^ZrqUfkuHNG zUX8^7-n*!@n1+xKiD7$8k>kI6o@Ld<71~vH?X{j`R=U!*m_vp_6Wm`}msto>3pIaA zQVHG`Fe;VM%vg~>(w{qcNqX=s@F zz5Yz$LLU&Ou4$24A2pmRyPSLQV<-5u)91r<{uS*U=~Ymii#GaFeThUFXB;GY&?h9f zSw$Ey4?+w`lI-mD&aI6W057C`wmsrTwZJ|dwELCxXMNmXD#~vsgv;5c$Jmatgh74G z?Sm@2Xil*mDRcm%N^pya3ESoRM)~o{6%-d~x6NhuEJ&sK|FHEAz?C&!*l29qb|$tp z$z)>Nwr$(CF|lpiwrxA-=KcQqtM0A3wW_+;?(W@nPVe66XRY=0R*#RDULej_BoZ5r zcn~K#nU4NTwB%cLKaQ{P=BoVjci$S{Y;ycNZV3DYC?sPxwjH^;6!^LTBCBv23kc{P7KDwqSN&Pmk z6O-co$b1>o8XDPV;KyqI#X9PKWE@a@E(6&!HPylOpv_PEkyq^h@=FP>`=?1A@+=`8 zW+OQ0sJ5@q8-3d7|<^m!@P~O~<7DL$Xj#IZ|hQGToijAYoT^x{`F7 zYS|-Xj~x!Q&-)RWMa!xUy#jqq|``|9~IIz%ysrl!GH41unU=`nYX$kpd} zCY}2oO1C>;Dy7IultS?B?Pc<~42L3}F4xJvkx~gjUFof$M3FDU)f(__TcZ>4w3Bml z{SEh&t0MQab(D{88JS{x5FTk7j`N{Ixwn}u3-{=!TH3s(eT;y~W0Llg485gq+a#62 zEv;nTDyGlXjpd@|)x2T=LC(D1rt!2|iZY-o?&|_Ac;W<*%J8BS_OzqZ;|2Xhm`m`p z{{_pI+%O=pN&VQ6WAWdRd(~MXZpvBda_e4Fg7#u4$*$T!q0B9(T=xvC6-4N;pWB z0olq#Xb2~4mB6_*fSay$@8oj8_xqCLEFiT8KsfwE_?YYq$N+Me-Z@tG2fwe-MNosG zQU`KNlgCjqBMkh;M|P=aqgluPuKl8*8a_pQsp@>mL;eaYxq5Ym5kcyCwf0%^IZWM8 zz1088ID3H#==!#wh=U z5{6I#{Ly(HalHA zTpTHsY4@1Xx2P6NM%GGdqRX*r&APj$&ZscOi_PL@ zEz8nsZ=>&9?JT6KMtnt|Yb+4ZUVVLh;*SBC9Y_H0jL#Y|phimIdxQQX^&WXGwco+x zt9Ce3W3P;&X2rDuwXC`=)LjmC4{umO+y?+q(^C^ zNz998)}w_XgdybR%UinC8FeRJ+*NvJag3<)Q(S00=Ie6W9$q7(zu45>nYWPb*&I9s z`w4E&!YMIy4QvB+%Hg`Uf;0d!L&z~v`=Q58a6(Zkkiw{SXq?obQkvIR?Ag_2xP&8p z2hQ2FJrFvBWQN6k96qGW(U6OSNAb69#VYg;ekd;6px#|{# z_byfR!v<-`FjdGR{+q1J_Lhl?JrZuDnc&s%actu>;3dD|{QRT&mV)2@q-W*(&j$L& zRA{2Sv3pL^Rjzud`V`28G|*}@hfcH88$B?Lb?fARp*OZXR_Z(1qVSQld1k+9rxb~=DnN9Q zl9)GO9iweLmf)Pvcl&r9c4+;ohSX@=0W;-HPa{3{-Z4&oa(#QKxXYz@`)wKfwa^HN zE)Y5Jx{90?S0Fx9;J76R{wpIq9Je4T1p66c3;0yr*p89>qTdbEkp75Okzvn(_?|fP zWmtILiCkeI`tAV%}ay;k~q^4TPjG`=8GXjwsZ?1L8X5vAXQ|amHFa}g8<$X$P zU$Q8d^%wADWAybKK?5~kv4gOz!r(PPP`>2$5LuMfBod##iz;j35{NgOyju2@4lXvx z=~rI-t*>rUlGC#am6W4mhL;{ZTf8?$ZmBo(GQMKj4rLe^x_MJb;RU63L|Ti(%YbiG1_d1qPh*Hu<~Q*#f)P(0%@C$&p%D(adkegEVh5lh=3=XO!e(UCaMn@iN1nt%aE zQ6R@2zUYltO|kD6?#)={P_*v`W^8mV+;KzXK;VN>9Le|B`NZAPN5w$HLgd6l;K9N~ zq>~8WSa9F?d^DHZTJUqJm*B^m)}*dLV-T{0%+TlO|Bl<{5&6*m=ik9Zmz;Z$sKH8byBfX><{}OnnfNwWl zzdemh#l?moC%mJNrS8kc38BKeIBko#w{d?`ud;@4AtWmxYmHka`3zG^6=Nerqv2Tv zmpF3wu#f&oqu~-}D~@EqlJNA4053nJopI-i=(m!9w>=r%B&}u{!HTj)(SGoZ=zE7S zI6pcc!nB7mTzn*PW=;~O2Ri?+R~fZREPN#*G{Un3btY#-$c~ICR5$`94xEP*hA$d9vq4kbI%#LL^&M~G0Q{#1}PrKpxn0?;&@ZXfL!_7wq+G3 zNhL31Ljj~pYD#;D@p{YgYl_uOJ=G4_YqE#y(`^1mxB5`fjU$6R>A3;;WjtI(TfXM( zH@5^oJRE_!CN0BDd?dgM!9=K@IWkEt$L?yRm&nFdHz}MH5Hx_!@9&c4*AN_R;Kz^ttly|S?!-z?kU6^B=^+GA zU1tdHeaSw*lvjFyvtcN8HDAq$ad+}HC;xI0oX_o*PB8f5btC)o`1(?$_qZJ@@%Mr0 zyn~+osdrASd@`_z#SR4V7d@P&Zj9`vop2P*y3lL`lnKIH47_?9am;0u43 z8#Cl96YCR-BnL}OR5t;8dGzGr-!+a8OSHoNnIsyp6(e|8GhabDTuNrp6yq&0O7<^m zS6QbAsV8Dz6@|5mCMX#*=>6dJbN~MQ^>CN)&&MP8sao-uUEJON>*M|D=i%wrUEfjs z&Tc@{>wA@y)=7G_EsOz=!lFM!bIBcH`nxJE;AANhvu5EYL?l-y393L$wKI z-xS*k0V~XGt!jwdFg0;Ai@~I#xZvuTeoUg ztr?@?vW(3ssCT!flfmfX;@gAvhIrrKc2>Br->cod!n^*Dj5%`$$ny*ld1O*5KIOWuJ@733mSc7>w(Ar?w*aUE&6&oo1ij)Adl0fZ zDg2jb2o146!1rg{v_ib0$m=AQa<(XhbP}P6>Bc#j!jrJHW0jo_@x}AH5mCCwhIR~% z=zu#!KQYxl8ZHnWCBT96`RB<*Dg!aV5&SMUP%RRD#&`MOUIuqN-|#kN0DLv(JnUa< z-P5w3AADiOwylG4PiJ;v7*{yu2CKbfaRa}j*w8Z(Mz z^C)oL|M9uf|4|Lv9ygy5i%Y2FW~lC= z2;PeSS8r-9(uSk5sKJcmtI%QC(eGJ7dIItVoZrkwaY*u@)H`!tQQ5gZ^ZiR%bN4%w zeQ4Ih^d;!#p59jwv3Qu4E5th6qz*B3PBR!U878cm?C7kkvtlt5D-@I>)%(^4ThrLL zs~ky>m3>p_{=D z!m(94zy7>NPK1YAWiRg?s1Z+&q%|l!%ftGw52&E1>4FK;=jhKAfi>2=89Qu)xn8@E za>wc<9BKx1N#+a5zLI?A_0()}mmqs%ww$(sM|%${bRS8!*>Otbg(%)PELbZyI#{aj@UF4u#Tn`{0@_xG9>nfEIC_)$E}7Y4bYUFbU`^KrxZiv$0Hjj5?Ep zWtdHz$1R*tUI{*At+7O^!0)#Sb=b#O$^MISWZD|6y{Z!-D2aJtE8_d!V!pbW@Bb5- z$DN4pVxO&-V_Ai{MOtz;%JyE#&NVOQI03V#bGs|0*^$C@?z}1#>k|lnbu9Eip+?GT z=3Yf+Mk;x_@X(CX9Ubs&OGd8kKYkNwRG- z1$DD$!0b=PaK%ZcvQ`ZfTfg)GAfeC+5B~;KPcJmNZzfNx*1tr@+(zg z7}6>3vTzmohggioRhxchtjlJD&C_YxPcxnAQ%U;(e;u7?@CiY#FF)W3n{2NJ%v{&Wz{(>1e%;{M02Rh{9jK}C85mVoZ8KSs+bG5 zEIM=w~nXNV>4Y9|yml89LdsmWl&EU%_pAsHgs<1kgOCL1qd!MU{ zmN*{z%SrfVN?n*C-iPR-f*0%OLF2MC?|_qEm_O)t83kP?O2BqtlnSE+k}yR$p%#hM(|D^xXCq5)dk-?DMP_EvS>d5@}NDe*sr^x7UFh%s{a*+BO7mCwNqPq z`h9y)`h?5jFyfd(J@-CKO5>}Q^pTeUp(KJ@K2tl&sD=Yl|ElI@eqB}l@mtDTW)4gB ztza%;X++Lq?#(K$erB<8ih2v)!aM5v!n>1dXEBE>MpTchy&jKalwFUly&h*9Yq@~d zQa=q!r4Y8FPOhNoY&pwq^(v1}QMLyAYovB1h?mxGt4G?ffucCXjfpN=kXyW?_-lMB zPCHf2|D(Bo` z=(fvd3jQl=~{jqn-qpjvVcqhPW`5Kaewxfrpy}P_B*zllXu6x;2%W*|}3Cp-a z`om&@Rj|q^V+?1y+$m%HK2(LgsyI@`E3&oD@|W66_#D~X-r|$ym4tmg)f?KGmc}{ToGih1 zmLm$zPwWP9)#Hk8&+>;_#0(%MKPtys6gU+vx|TGeZAjeVX?zR%tJ{dP5n#-fl|hu_Aj)Nb2KwO71n4V}q-U_- zUD7pa5SuE`a^m1PUQ`zczAP0uAkXHy;r6U4_AX#tt4{v zv5kb$DL8un+)Pp{C)JT>U+&H$SKO|DUbt=ij8$q*1{v5C5J6m(O{R!94ZWwwUzR_7 zjPf-{s$Q(^;`O>>!><>g3KU&_yGU1?aD=G<8l{Zm=XIQ^K=uUWzzn=iz(t9aEO+F< z3a%^jpnjKNg^(bzRl;$uL;TrTH%Aa9@^klh=g4)>hXSjmtG!yUqeJrtss^vt=BN%P zL8|EELGvH&heq>P%R%}%^QT9;7CI`B{2;iW&brivki(iXmrOAI|0&M_N!^s1do(!Z zms)!ULXw|fmBSh$QA>)|*R zxDJV6F)>wX%Vc$hzzCVGCCjO+mXrZb=@vAUVXXRH;Rhb2vI#DuUfiPB0}Gk2S7K1> zIH*18nJITc!G|ZM?YF4E5u!AWE>=06N*dZiXI5E970E&nOJb}8a>+=&NJ{wlg$P`v zjri!m8V?qtVsrhV5h-}nZuR;D|BoWcy2r)wzQB6O1?Ct0&`6ghDjBcnA%=sdC1)qp z2M&(;e-!P4fQ?f*N62_J9#7S9lYH?Bxkwagd6zmI>EFqd7Qx?(q&gM3D4V+rLk>oN z3PqNPcm>`3Zr$qp3$OESkZ_6E1+941>*OEgxWwV(aERD)Di_08%yYcZ5c|_)*`mhE z#aCjWS$9bFCcG3hOF~OoVBKF=0hZAr{lqgF} zMo$)>+NhHlv(t6#UKanXw6VcoCfG>Jgj4==MlST3E^nH1VO?N<_H(hv5u!+~>ecxN zTnsd6@T4&GEJ%GC5<7-T`4e`>p5wA*-JBnXYBUpX%!elv$7d6Q!j`niOV|m_kF!Zc zeGN2~w}{pA^X8Fn(1A}xd0K3YSA7AQ!3jK3E7Qr19Dj)n@NL24y0Yx@xEBmpZA6_@ zRcC6yv);d6K2o!|8nIT?L8R2Gsp`fs?Bsg4cXIRcbhYvdaPoJ7omIk2 zU=qe6#K!s&w@)JZdU5j=W!c>Vk9OA;+uQlLJK1~L!TkGSfd=^a+^X{}WD#m>5oGD= zWM_5pC?N7tKd&x3Jniki6e41te-yN9cJSd5c)!{`-R*wv9-iKxb_OGSbMp7Jc5?G` zz5ao_iVHPHw}Hz^F6!@5^j+^WH-Pxw0g-Rp4^=aLq`G4K zakCSh{|mg|Fc1!?8C)I{(6*2vP;|bxT-?DtF_~~oB*{s|k6`(>@_y+iBLhKDR&ufhe!0=zX!~RE=CG_$6eZ!hq*WDu6DR`+wvoa)1 zLta2JJMY7V$2?vl7c?0p*(FCp7wEtIXVXWhit!JSlgRbnAGh&s?;!fI(uEv>6PKFk zs`4l6@*}$Ptt)ej^^tDN#wu&Wh-=O3eDs}bhuNJizGS9DM?LW$8NFsag#AC7bUiob zIAXgnD?!2CM9Vg7*f4`;nmJOmF8DYxPLETP2&>N-Rj8R)Xc!cUIJgqboLk=fwIcQJ z1AmD=1_epib1PPUdJqU7%-asX9q>*R|&db_}ize z%=KQ-r0rj{joJ-SZ=h3f-F@x0hxrmHbNRK(L*IYy3wzuaXE99h7P}=gH+y=m!m#zbP^C+OOSWDC(ANX61FK7B0+VJKdr-4XeJQ{aDd zVHckjVis#16jW8GT#!V|y$mYS?#TG@r-!`Hz@Llndy*ta^<4WimUW@Ug?JHszwnRb zF7rixgFz<2{zHr414?$umB?QOl{4okLkp-a?_~HnA6G4emLc_O#{Vbn;p+?5p%oR- za)*ZdPt;S0_r@jvyO7cK+e7CRfXiv4|Y-esb7GgMN8>yfEmi2MtoNuh*d&X9{6wdHf`hB_gHNY3wM^e`$g*! z!Tld~D$NrS%_BiMi;GgEdK1C`^?j`+$ps$?s`7AwhKPL~v;WqvVj>=P$sf$GI#44u zM-n#v3PKe*5-2n%zhf-bp<4^AEtOqxg^^j9F1|6cD7P8Ki?cflZ}X% zb-|ifd)a3O+F!ht@dxMSNAS>0!b*jQaX8`h1-lwrTHe%MX@`gp-Ae>wbp5vfQhC_< zajD^CZuf|x$XVUm(Ii%(RLe@3DGH{WuRU7j`7X+0*a9xR(w$(dAMox9ZoiF6KKvd! z!3n~)sa0UOVo_c6NRDO?U`O%_ z-R+q43flFoRs;#S=^g{^dtqkr+x46xAbLgUdl}z=1=}H3>TWa+R&+(zQnov{3GRoK z*%CVMbznj$1D&uJ6+Rc-$kYo}gj|GBN($y(wDB%ihOA1a$z>U7?23-XeDfjXC6zTO zVL2=)dq41a6v|;?dy2$fmX=xv@fF*m9#ug6R{3HQd6zoo;234&_qKuLW#aSt!Hm0) zj=Z+_XLDPmXlFDvmuBdyEI^*h ziy^hctC}1`Cqj_8=gX^Pg6O6>b1MwRTv0)a}19g|oKBseASTqf` z*zNws;$)|LT+r=#J>kM@zl(M?sUUckjzIxZY|1UTCg%Z><+lq4MoGj8oZG&Ez$>zg zeU3qbS`8w2sCb9elqTl}D?@3=?Y{t>B_sP_^Jnx*bDsdA&0AZ3mZ$~M;iI<-(uU9O z!e3KXsrsiNE2zS5?6(UCk$ik0FjCq01X!BVo-F9E@_RfGiVFc~LTaLVe|m5xG=Ta{ zJ;d&0&9@&5A+tEog~lRLU?Xl4Ja*Bp1%#?&d=ZGMW5>ErsP@$6@((P@850~2KYc;| zH%ST?$VxwX7)?(x{s=Y<3^SVKTdSo%B~DbcGwmW-6jp}GF2WxG^QpS~V_QXkt?Bgz z|E_R;)Gc!!1Y0@lzZzx}FACOVf_IeY<8C&9O_iFAFU2Z}bap)E=C0>A+;ZG>^l;7J z=TE?FY60&6*Oct!$Gffw`6x$a{>i7e#`e0;d)J^}lvC{md%c&QJp4Y&e~NzQ)23?I zTN5<dpYKv)8U=Pmc(!|5Ee^0x#4ur3>WKvBWX#2I!Guk#!A-`{Vbfi8Uudw5U zB9GkB9+Y&n>(&d7jnysDUhgG6HmwY>R^x6C_+hdyko=|@AXx=sMByyZXwYyD#72tBrwe2`N?4*S(WBb zM(~5Y_bO-x1O;p`OtA{tf|G@hpiHs99xx0DtZDY`*unczWe2{>`___dY6-HWfn9l9 z4C<^{yvTybDq#)M5cDv2;2BN4Otd3~bf%R#0$D zwU9V32NW0N90zRiNBa=08s_!Tsz5D9imllK9Xuc=&{cO3<|QaNkux!JfX@_ZxFpoM;gfowCQGyrOsv;GvlL+aIkqYQht zx_qj%--S*xl1mW!3qjtd{aaDK0TRmwdte55AbWYcqd?b`Jk&2l?R#zoA@quh2AP0< z&2MQu_t{7`(jjzsd7ZPVR4zx|%)>B`vPT1#VtGN`foOI@ppdO!ho|6^04#u84$)7_ zIqw^GbhD@mM&`2)Qs(ohF9g*WC+js3)%T5?HtTgFe}s+au4S4nDF4)~3Nl7oS>J+_ zT{&4{Z*@^(5F0O3c64>BIZ*eOhU=(4$k7v?ZKc0= zF1^lB9RK4YZG76CW3L;KGeKBTSq!nbdR;NG(7xf?W&J*0*=fwmzolXuTShWn`Q`>{ z`XtE9%U5Mj)AW_kWbz)Rtw8F~OfvbQ9Xq>uuQ4Q@Z8*3^DVEp?Yv1Bi;eEh~A?8B+ z14h0UUYw>OjgVUgWvxT6M8ltlh&i!DiU!whZVK9HSO}i^KO9r+8c0v&rHkHNqx zo6&ZeVJ5*3R`i1wao1Hvj&0uiS^EFTN~k3ts}IUA&7O%A5H^DQV1d@ahJdTuB;lN07lttmTS&b?C$U1F!>+~|eY=U|1s zmqYM|`IJTxIudiA8R$U*=|tNC<>*rkhn)j^_Y1qN%BmO#2LDL2{}wzP^#WYn^k0#M zoGCs#C_j-rHk9pOu|Th)1u=I{Cd9IRXK<;1z0l9TDY%55@zj?G_Q2K-N{B4=#QK0? zMMG)U=gtF-2B$W1ER$2MdFjOHC0$aQj&K4xk15kuqD)vO7IE<$242*1J(cciUcN?! zTbzfA{R4ED_aKo{|pAe6qC2RIALoB602kzSP;d3HRHv#!Z?g z69Zj3+@d}QnfXC8W%;4Xg1kHfi}WcPsm5fj0V4HHX%P^BU%L?qH{nlIG0mBoq*cK= zOZ`j{16=YQ(JzCjcgC@QIwd?9mC`{BZ>XQ?A5oH8<_rfb70v;-u!G9)5KwqO2LGf$ zwJ#E-7U?Qlf z3i84N{@;q(fC+hq(l}nl9}j0E?~f5>3mf4p#L8}(wxGbwr^OMmazoIjx^8ica(Z^u zdFe({V_ba}cO8)eb|u&q*Zt_F-luF2)TSEJ2AjW2iiO8zig(M^Zxc*>0$W6#xX@XH5NDyH(XkyZTh2?J%-Ez1Mud1uSK5khQR9=Yrt=M*N5 zF4K%?MS#?Dpq;AA*Jn{hZNr%GMtbPdcGNOgm`XNxxs8x2^Pc5IfeZBCN(Frk#oMYP zA5L8q>!SqPHD$|90;;?d7*;ai#`sCA8L|!Y%Endg>(i?V{=?bGmFzh2Rj zzdy8-_ymml+ecdA^T?a`~V6 z=oinC1L^ctjgs@>I2B#&`2B{}Fe{k=tN=71Yop}zK3<_=GFRP3dsab31^S{Kt8GX$ zP(ss-ysFCqR%d9O)^;zs@!Dc6_&!LB2ytA)k(R)i{6bp0MVYQSrA}#0f;LT8{lcm# zQg;kT^B5+nz86Cjp)ew~kzPL_xm1c@$KU%rpL_WCKcpr1l=SWh<|JDEXXRpT! zEfg3dM57*JBi+3O={%3TcliAG`cx&C=)=?_k3|~o5Y;8E3jYO~wd~?!<#&bA>B{4K zaLKC)yp5i0i|`+k)b_geYx1ZIIvHB6oPU$B%Itq!ph-IW?{WhECU55=0&W!cFx3gC{rIZaSRYp)frd$XCXhIQ63khySpdaAYd?6jJH~8l(5-Q z6vqnu7qwnqc>eb$IGMDQ5jc@Kh%j`MvogFe^iSO&;$Kw3XTfLL&`V--kbeXT6wASf zKUxCCPrC#PZVH+I9kg?+iD$?OtQ);Tqfq8lh6wfuIX`#UY!E&QUAyrQHUC*Qve4Kn z0=8CPB2D#>lV6GkctW%Q?}L&epZ)+J&J32VaRy4kD2(L{Y|2G(2*6RJZWnSUP8VLyNI&rCy6TaQf9V(H zNki&1OdH&I<5RSDwIyLu~lavlm&sX4`1(A8LR36MR z4?a}H$KbM~W=FyMj43H+dYR~SFXH08<+eq(`RvQz>>#vN_IkwM<%#^8f~}+im9?hm#ihEl-X7x7wh9sw@!mbKJ9resDNb3><*627p;WK?wF_ro8Azp(lE%3X~k zJKid=y4SS;(t%Mj#p@xzzE`^a6@Qa;h;GwIfv!Fq5H9*0?v^x2$p+N8uQ;~y zZ4)SzD3Z)De!oqCd>VM5ekUHXu^& z{Cy+A1COx6q(V#;7e0dXan}%ghGz@I+QPK%5;6#Ai4P1j0K98d@Il(w4+!pIdJI9x za{3@L1=_l+>Sl>*!{kew+nuk9n^wprgy0@2I^r z#vd?iuwK<2N3q%l97K!r^o_D#{XjP6q^Oz@b8(U0)D^@V;(6@r&4)EjXIXCR@XKKb z9;>swrpId2tBXIty%~qwVJjz&IHEee*s#cKs{k726CX(;3p+6Pomwe8yNP_f^!361 zMwDtKhh`)l=mkc0gAK88;|_ATlH`@WW!=$5#X4zCycujsm-)uP9s=&n^r&y$7ljQW z(w}nc&EeG1K1%@MhHdk07oy&s$pyo0gE_3C4LY%#Pfaa77Kb*Y*w5b6V9QogyjEV}&ol^Ho&Llm za4efv-dL`r`oBTs*fF3n-Us4?J9Pk4DtQo0$;Y&8d#H{^D&F;pwj!9gj`#qQzU7)O zf_dlT3B88c7jeg;r|$?SZ}BYZ>n9}7=#a&}ye{vL6rUfCl^fV;lJ_Yq845m_#0OyO zA%0l@n_%o!iIsL=pnbuH8BXqH~)6O2h}tl!k{#Zi{<)HSBhpY+zL zl|UVzlhwX%Nrpv)$TEJ1{>@Wg$6UE4ESCf%0iIu?K}6Ov(t>o3#Z+-ax7@G-Sxc%8 z##FTHuQDCIIyH+lLlpm>PjZt$K@e_yCvX-&;5r%)p^g?{R6?r4o}X9fwjpzNFNo9C zOI9|z_iJZ-Om{vO+Hn;EFMBVpo)cjUzhYfD$WqDe_Y3`egd}EOu(!cF?*+w-g&C`YPP&4C!`}gg zw!pJ=lbp@6w~O|KF;+8=1P~hcJJftSCr@sZ>vj~qDp;!vAlZK7in+VduaJa~;qJEU zfmJB@mr~}6^#grIgpxcZHaJ#b4f+DIt-9r|?>e6uEpDgX!#xW$K>X<4M|(O2cWL=C zVx}W=K^1;IhXPUhin^T);iGj|`mRAvS*C||zN7pRLLtjVU%MS6_f=xgh<#3v#I-{b z8%39<(>J4lPtn(^j4qE;DN{#=zc?8=-%M=8i31+9{J}Adw{guu@xG_;D|@4Pr$_*%ri))zOaeh?Ju>Kq!+Vw zd|oqcXs%9x)Hs*{#DEYGCK$QD#lq=Jp#F70 z9qAkAwO?V?sp55u7G=Y!Ap(S_oapG<3Fe;482okxEi^QXHQPwrs6_%;kKF?=_bMy_L6)ss9@WP+w zgFg($kEmTyE=8xQk7AO9;ZjQkn3|eA0$)YJR?H$nwRTdAN3+I%y}Ep`lG_kUKMCR; zt@1rXwk)T}GRzmGA#i_1CDjU=)lx9VqrmN%LWOkoOeGlz)Tnpj?ca| z=9J->8a4n?m@iCfalhg%zx?}(Y_~hCcK_1ps;U|H^OTFAe!7rjQMU=x0K_x3e z7iQbx^p1i8TcQ_6fE+oX>s5M&E+jWCk`^dhgS?glkLwzFp0aB@Yi`vmZOO8Sp*Oxt z6^`CTI~gJkbgE^!sY9N)aY*INs2z4Y6}fQURsEb8mpmKWXB_XQw6<_d_*&|1oCCqZ z_)hqH;D^9$3yF?a)VB1g30osK;8|4xj#1qGb zyj8&C*{gP}6%gg&T`P#KS8qzXi34lS~UdK^C*^vd#oSq&@Fruq@VMm(|tDnSwQIcp$fXu zh*U&m!*3JIEv_TBW^JiNqR;iON^f?dE1bWm4J7!2z+ImLm8>FV9rdxsS#i>o0gW=A zDG*qsr(AV9L(WYPCP-sPHJX!-FO}^l2rJYM{nu%7Fa%KnD*RLqDV9(1f1OaR)LB{Y zYb&Hrlpg+noKTzouM;Yr*bl8cp1m@n(n(2PNT8JhmduVV5wKHn4~$EE;?Gw1Q} zlZkxeCYeBlV4WOEvMtf^Z9Nn5Mr?R846*^^^~rs@b|VM~+=@ku$#qokhh6?{)Q8GN zD`0tu6sUjPNut*<4$UyWHQV4#QMBqe!|0RGXuu6euwH?#l*V?I( z9QiTWPRw2wfeCphmg@whq>~B3ZW!A3H@9iGd83v`>7Iq|L`=s2(xg5@jIt_n_d<~K zlhS{C04OuJv;NMQC^7^j`Zx2;)(c_!8~g-{Kj49p6B(KBs{hfRe+JLyJAr`0ILEwl z*Ugw3c%hsf>+EHOe#^#1B86%b>T?i3LHQ`M!(+kR$(YXaqTwRQ42Bj4|K-X06LBR6 z(Oesfs?E|mudi~4aToZUINq;IB1{dq9f;Cc!hF{aJLcDxq!C)2Q%No?lXzVjR;Dw$gj#A+yZnFHUmn*VTsRaQbnsnNaD8?ls%*xTB* zF+tL6RWGZ8_d4NI)ilHiJiAmFEuItSEl`luQ|g#HlNqKD|12*@1YI%tr*NZr8|tvA zP7ufezmwa====%B{jI0VbI(m~n3=)(i2sK|tz^dcT=@SJmIG=0k0O{0scBoh#vJ-~ zcC^d0cW3+B$h_CWlt`wX$^z4pyvklblLLN#;GAE*asjiiyWeu6>+B3ca8!i;naYIC zLP#+p0{I-wO3vqntRwXTCZgMcZ#zfG%7*ackFuYKafJ+Kp%MNUnR9rtwIwEL_r7q6 z5WZONzuA%`O3E81GP31OBss+LhVrENsBQnvRw{X24k*lf3vHY@7fgEoBTQZno4v!t z9NX9p!>2=|{*jRU^WV>(|C~Di@#^I+oc~_#`Hx1YJbW8J3F6qkz+S2I2?TpPl5gcn z)@QDPT`^^~T3?P2VkaAvyz9d-im5*wPO$!c5G5DXI~-qd9)R^4Kz^&SqDaa92HLhR z42f+2N|T?WJgLOH-}X~epo;e5jU;nevPlODdGVcjDU^te;g4&tC%5Qe1Ik?Fb)OAAA@ znHD8!Xx;>|n3on1%QKo^%d;X)Q5|F?D@4kAzEAIcVUp$BXe+BhlnkWGQ2);U1m2FXWOoKn7^i~2{{*^F^ zx8kgRl)--!%OPK`M@Q-JaOb${jH2T>Lclzi!8HwrOrY_fOt2%T*0Y_8nyD7eUU- z2JtiZxt7V)eW7nz>DHXN&$8y6gu&)5{FFU+d5PIFz2xISXk7viLMhyOh)4hlFp>N% z4;9jqy`?%TLPoNAAvQ=>xT-Qg@Q@fj5L!!-k9E^o z`+sFm*Y7N6o&l)*3Hpr+XT~|w>(My}fX$BoclI3lZgXau0G>ZzzG>mC=^YOBrc1wM z^JITyPmuMHGczAf{*+jo%(;YtbUy+%^zU-uQZ4CLItbs6v3GW7ho^bM{71(ny?BG@ Z_g7M52_AUhfv1bl{|CIwj)?$<4*;zy=KBBu diff --git a/package-lock.json b/package-lock.json index e4415976..f4b0afba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/52c9a1aec1580d7539e9d8425dacd50c0f9b4a73.tar.gz", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/6cd64a17df299d2804a913c1367726a022a6df9a.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", @@ -2686,8 +2686,8 @@ }, "node_modules/@mat3ra/esse": { "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/esse/archive/52c9a1aec1580d7539e9d8425dacd50c0f9b4a73.tar.gz", - "integrity": "sha512-l6lPUMif5D3FqmhOKPlDbJCVhVSDEjr7gLeCiWlNUAqHCvDuR1d+czdKhSP9hL4m8WHfLVIrhJ5ViSMvuf4ZoA==", + "resolved": "https://github.com/Exabyte-io/esse/archive/6cd64a17df299d2804a913c1367726a022a6df9a.tar.gz", + "integrity": "sha512-IZ8hLoj0yYaP1M0jJQloufrAY4qWHuZe7JTYFuIyiw2uAqQ03mD4oTW0dftMdVdRkwPp6sXGxqv6Sgpc9/HfZg==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 4aed057a..3de142ef 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/52c9a1aec1580d7539e9d8425dacd50c0f9b4a73.tar.gz", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/6cd64a17df299d2804a913c1367726a022a6df9a.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index e5658eed..80e94669 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -30,7 +30,7 @@ import { UnitType } from "./enums"; import { type WorkflowSchemaMixin, workflowSchemaMixin } from "./generated/WorkflowSchemaMixin"; import Subworkflow from "./Subworkflow"; import { MapUnit } from "./units"; -import { type AnyWorkflowUnit, UnitFactory } from "./units/factory"; +import { type AnyWorkflowUnit, type AnyWorkflowUnitSchema, UnitFactory } from "./units/factory"; import { getDefaultDescription, getHumanReadableProperties, @@ -77,14 +77,46 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { return Subworkflow.repair(subworkflow); }); + const invalidSubworkflows = subworkflows.filter((subworkflow) => { + return !new Subworkflow(subworkflow).isValid(); + }); + + const units = workflowData.units.map((unit): AnyWorkflowUnitSchema => { + const subworkflow = invalidSubworkflows.find( + (subworkflow) => subworkflow._id === unit._id, + ); + + if (subworkflow) { + return { + type: UnitType.error, + _id: unit._id, + name: unit.name || "error", + flowchartId: unit.flowchartId, + originalUnit: unit, + preProcessors: unit.preProcessors || [], + postProcessors: unit.postProcessors || [], + monitors: unit.monitors || [], + results: unit.results || [], + reason: "Invalid subworkflow", + }; + } + + return unit; + }); + + const validSubworkflows = subworkflows.filter((subworkflow) => { + return !invalidSubworkflows.map(({ _id }) => _id).includes(subworkflow._id); + }); + const workflows = workflowData.workflows.map((nested) => { return Workflow.repair(nested as WorkflowSchema); }); return { ...workflowData, - subworkflows, + subworkflows: validSubworkflows, workflows, + units, }; } diff --git a/src/js/units/factory.ts b/src/js/units/factory.ts index 0e70399b..1ee9f938 100644 --- a/src/js/units/factory.ts +++ b/src/js/units/factory.ts @@ -23,9 +23,13 @@ import MapUnit from "./MapUnit"; import ReduceUnit from "./ReduceUnit"; import SubworkflowUnit from "./SubworkflowUnit"; -export type AnyWorkflowUnit = MapUnit | SubworkflowUnit | ReduceUnit; +export type AnyWorkflowUnit = MapUnit | SubworkflowUnit | ReduceUnit | ErrorUnit; -export type AnyWorkflowUnitSchema = MapUnitSchema | SubworkflowUnitSchema | ReduceUnitSchema; +export type AnyWorkflowUnitSchema = + | MapUnitSchema + | SubworkflowUnitSchema + | ReduceUnitSchema + | ErrorUnitSchema; export type AnySubworkflowUnit = | ExecutionUnit @@ -115,6 +119,8 @@ export class UnitFactory { return new SubworkflowUnit(config); case UnitType.reduce: return new ReduceUnit(config); + case UnitType.error: + return new ErrorUnit(config); default: throw new Error(`Unknown unit type: ${config.type}`); } diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 3f3adb4e..0353d7b0 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -8,6 +8,7 @@ import { } from "@mat3ra/code/dist/js/entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; +import type { ErrorUnitSchema, ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; import { Material } from "@mat3ra/made"; import { ApplicationRegistry, WorkflowStandata } from "@mat3ra/standata"; import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; @@ -15,11 +16,25 @@ import { expect } from "chai"; import type { JSONSchema7 } from "json-schema"; import type { WorkflowRenderContext } from "src/js/Workflow"; -import { Subworkflow, Workflow } from "../../src/js"; +import { Subworkflow, UnitFactory, Workflow } from "../../src/js"; import { UnitType } from "../../src/js/enums"; import type { WorkflowSchema } from "../../src/js/workflows/types"; import workflowHashes from "../fixtures/workflow_hashes.json"; +function invalidExecutionUnit(flowchartId: string) { + return { + type: UnitType.execution, + name: "exec", + flowchartId, + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + input: [], + context: [], + }; +} + interface OrderedMaterial extends OrderedInMemoryEntityInSet, InMemoryEntityInSet {} class OrderedMaterial extends Material implements OrderedInMemoryEntityInSet { @@ -294,4 +309,121 @@ describe("Workflow", () => { }); }); }); + + describe("repair", () => { + let defaultApplication: ExecutionUnitSchema["application"]; + + before(() => { + JSONSchemasInterface.setSchemas(esseSchemas as JSONSchema7[]); + }); + + beforeEach(() => { + ApplicationRegistry.setDriver(new StandataDriver()); + const app = new ApplicationRegistry().getDefaultApplication(); + if (!app) { + throw new Error( + "ApplicationRegistry.getDefaultApplication() returned no application", + ); + } + defaultApplication = app; + }); + + it("converts invalid execution unit to error inside subworkflow", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const invalid = invalidExecutionUnit("fc-exec"); + workflowConfig.subworkflows[0].units = [invalid as never]; + + const result = Workflow.repair(workflowConfig); + + expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); + expect((result.subworkflows[0].units[0] as ErrorUnitSchema).originalUnit).to.deep.equal( + invalid, + ); + }); + + it("leaves valid execution unit unchanged inside subworkflow", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const unit = UnitFactory.createDefaultSubworkflowUnit( + "execution", + defaultApplication, + ).toJSON(); + workflowConfig.subworkflows[0].units = [unit]; + + const result = Workflow.repair(workflowConfig); + + expect(result.subworkflows[0].units[0]).to.deep.equal(unit); + }); + + it("repairs only invalid execution units inside subworkflow", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const validUnit = UnitFactory.createDefaultSubworkflowUnit("assignment").toJSON(); + const invalidExecution = invalidExecutionUnit("fc-bad"); + workflowConfig.subworkflows[0].units = [validUnit, invalidExecution as never]; + + const result = Workflow.repair(workflowConfig); + + expect(result.subworkflows[0].units[0]).to.deep.equal(validUnit); + expect(result.subworkflows[0].units[1].type).to.equal(UnitType.error); + }); + + it("repairs invalid execution units in subworkflows and nested workflows", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const invalidExecution = invalidExecutionUnit("fc-nested"); + + workflowConfig.subworkflows[0].units = [invalidExecution as never]; + + const nestedSubworkflow = structuredClone(workflowConfig.subworkflows[0]); + nestedSubworkflow._id = "nested-subworkflow-id"; + nestedSubworkflow.units = [invalidExecution as never]; + + workflowConfig.workflows = [ + { + ...structuredClone(workflowConfig), + _id: "nested-workflow-id", + subworkflows: [nestedSubworkflow], + workflows: [], + }, + ]; + + const result = Workflow.repair(workflowConfig); + + expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); + expect(result.workflows[0].subworkflows[0].units[0].type).to.equal(UnitType.error); + }); + + it("allows hydration after repair for converted execution units", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + workflowConfig.subworkflows[0].units = [invalidExecutionUnit("fc-hydrate") as never]; + + const document = Workflow.repair(workflowConfig); + + expect(() => new Workflow(document)).to.not.throw(); + }); + + it("converts invalid subworkflow unit to error and drops subworkflow", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const originalUnit = workflowConfig.units[0]; + const subworkflowId = workflowConfig.subworkflows[0]._id; + + workflowConfig.subworkflows[0] = { + ...workflowConfig.subworkflows[0], + model: { + ...workflowConfig.subworkflows[0].model, + type: "not-a-valid-model-type" as never, + }, + }; + + const result = Workflow.repair(workflowConfig); + + expect(result.subworkflows).to.have.lengthOf(0); + expect(result.units).to.have.lengthOf(1); + expect(result.units[0].type).to.equal(UnitType.error); + expect(result.units[0]._id).to.equal(subworkflowId); + + const errorUnit = result.units[0] as ErrorUnitSchema; + expect(errorUnit.reason).to.equal("Invalid subworkflow"); + expect(errorUnit.originalUnit).to.deep.equal(originalUnit); + expect(() => new Workflow(result)).to.not.throw(); + }); + }); }); diff --git a/tests/js/repair.test.ts b/tests/js/repair.test.ts deleted file mode 100644 index f0fbd245..00000000 --- a/tests/js/repair.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; -import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; -import type { - ErrorUnitSchema, - ExecutionUnitSchema, - SubworkflowSchema, -} from "@mat3ra/esse/dist/js/types"; -import { ApplicationRegistry } from "@mat3ra/standata"; -import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; -import { expect } from "chai"; -import type { JSONSchema7 } from "json-schema"; -import type { AnySubworkflowUnitSchema } from "src/js/units/factory"; - -import { ExecutionUnit, Subworkflow, UnitFactory, Workflow } from "../../src/js"; -import { UnitType } from "../../src/js/enums"; - -function invalidExecutionUnit(flowchartId: string) { - return { - type: UnitType.execution, - name: "exec", - flowchartId, - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - input: [], - context: [], - }; -} - -describe("static repair", () => { - let defaultApplication: ExecutionUnitSchema["application"]; - - before(() => { - JSONSchemasInterface.setSchemas(esseSchemas as JSONSchema7[]); - }); - - beforeEach(() => { - ApplicationRegistry.setDriver(new StandataDriver()); - const app = new ApplicationRegistry().getDefaultApplication(); - if (!app) { - throw new Error("ApplicationRegistry.getDefaultApplication() returned no application"); - } - defaultApplication = app; - }); - - describe("ExecutionUnit.repair", () => { - it("converts structurally invalid execution unit to error unit data", () => { - const invalid = invalidExecutionUnit("fc-exec"); - - const repaired = ExecutionUnit.repair(invalid as never); - - expect(repaired.type).to.equal(UnitType.error); - expect((repaired as ErrorUnitSchema).originalUnit).to.deep.equal(invalid); - }); - - it("returns valid execution unit data unchanged", () => { - const unit = UnitFactory.createDefaultSubworkflowUnit( - "execution", - defaultApplication, - ).toJSON(); - - const repaired = ExecutionUnit.repair(unit); - - expect(repaired).to.deep.equal(unit); - }); - }); - - describe("Subworkflow.repair", () => { - it("repairs only invalid execution units", () => { - const validUnit = UnitFactory.createDefaultSubworkflowUnit("assignment").toJSON(); - const invalidExecution = invalidExecutionUnit("fc-bad"); - - const subworkflow = Subworkflow.defaultConfig; - const subworkflowData: SubworkflowSchema = { - ...subworkflow, - units: [validUnit, invalidExecution as unknown as AnySubworkflowUnitSchema], - }; - - const result = Subworkflow.repair(subworkflowData); - - expect(result.units[0]).to.deep.equal(validUnit); - expect(result.units[1].type).to.equal(UnitType.error); - }); - }); - - describe("Workflow.repair", () => { - it("repairs invalid execution units in subworkflows and nested workflows", () => { - const workflowConfig = structuredClone(Workflow.defaultConfig); - const invalidExecution = invalidExecutionUnit("fc-nested"); - - workflowConfig.subworkflows[0].units = [invalidExecution as never]; - - const nestedSubworkflow = structuredClone(workflowConfig.subworkflows[0]); - nestedSubworkflow._id = "nested-subworkflow-id"; - nestedSubworkflow.units = [invalidExecution as never]; - - workflowConfig.workflows = [ - { - ...structuredClone(workflowConfig), - _id: "nested-workflow-id", - subworkflows: [nestedSubworkflow], - workflows: [], - }, - ]; - - const result = Workflow.repair(workflowConfig); - - expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); - expect(result.workflows[0].subworkflows[0].units[0].type).to.equal(UnitType.error); - }); - - it("allows hydration after repair for converted execution units", () => { - const workflowConfig = structuredClone(Workflow.defaultConfig); - workflowConfig.subworkflows[0].units = [invalidExecutionUnit("fc-hydrate") as never]; - - const document = Workflow.repair(workflowConfig); - - expect(() => new Workflow(document)).to.not.throw(); - }); - }); -}); From 9527dbd987ab33a993768d559684450d21c79710 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 8 Jun 2026 21:10:21 +0300 Subject: [PATCH 04/12] chore: fix workflow.repair --- dist/js/Workflow.d.ts | 1 + dist/js/Workflow.js | 11 ++++++- src/js/Workflow.ts | 11 ++++++- tests/js/Workflow.test.ts | 62 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/dist/js/Workflow.d.ts b/dist/js/Workflow.d.ts index be5fbca9..7e26a08c 100644 --- a/dist/js/Workflow.d.ts +++ b/dist/js/Workflow.d.ts @@ -28,6 +28,7 @@ declare class Workflow extends InMemoryEntity implements WorkflowSchema { static readonly defaultConfig: WorkflowSchema; _json: WorkflowSchema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; + private static isValidSubworkflow; static repair(workflowData: WorkflowSchema): WorkflowSchema; subworkflowInstances: Subworkflow[]; unitInstances: AnyWorkflowUnit[]; diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index 83b07bcf..f436051e 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -24,12 +24,21 @@ class Workflow extends entity_1.InMemoryEntity { static get jsonSchema() { return JSONSchemasInterface_1.default.getSchemaById("workflow"); } + // TODO: add static isValid method for InMemoryEntity + static isValidSubworkflow(subworkflow) { + try { + return new Subworkflow_1.default(subworkflow).isValid(); + } + catch (_a) { + return false; + } + } static repair(workflowData) { const subworkflows = workflowData.subworkflows.map((subworkflow) => { return Subworkflow_1.default.repair(subworkflow); }); const invalidSubworkflows = subworkflows.filter((subworkflow) => { - return !new Subworkflow_1.default(subworkflow).isValid(); + return !Workflow.isValidSubworkflow(subworkflow); }); const units = workflowData.units.map((unit) => { const subworkflow = invalidSubworkflows.find((subworkflow) => subworkflow._id === unit._id); diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index 80e94669..bfa5767f 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -72,13 +72,22 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { return JSONSchemasInterface.getSchemaById("workflow"); } + // TODO: add static isValid method for InMemoryEntity + private static isValidSubworkflow(subworkflow: SubworkflowSchema): boolean { + try { + return new Subworkflow(subworkflow).isValid(); + } catch { + return false; + } + } + static repair(workflowData: WorkflowSchema): WorkflowSchema { const subworkflows = workflowData.subworkflows.map((subworkflow) => { return Subworkflow.repair(subworkflow); }); const invalidSubworkflows = subworkflows.filter((subworkflow) => { - return !new Subworkflow(subworkflow).isValid(); + return !Workflow.isValidSubworkflow(subworkflow); }); const units = workflowData.units.map((unit): AnyWorkflowUnitSchema => { diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 0353d7b0..e974cc7c 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -400,6 +400,68 @@ describe("Workflow", () => { expect(() => new Workflow(document)).to.not.throw(); }); + it("repairs legacy subworkflow missing model without throwing", () => { + const legacyShellWorkflow = { + name: "Bash test", + subworkflows: [ + { + name: "bash subworkflow", + application: { + name: "shell", + version: "4.2.46", + build: "Default", + isDefault: true, + summary: "Shell Script", + shortName: "sh", + }, + units: [ + { + type: UnitType.execution, + name: "test workflow", + head: true, + application: { + name: "shell", + version: "4.2.46", + build: "Default", + isDefault: true, + shortName: "sh", + summary: "Shell Script", + }, + results: [], + monitors: [{ name: "standard_output" }], + preProcessors: [], + postProcessors: [], + input: [], + context: [], + }, + ], + isDraft: false, + properties: [], + }, + ], + units: [ + { + name: "bash subworkflow", + type: UnitType.subworkflow, + head: true, + monitors: [], + results: [], + preProcessors: [], + postProcessors: [], + }, + ], + workflows: [], + properties: [], + } as unknown as WorkflowSchema; + + const result = Workflow.repair(legacyShellWorkflow); + + expect(result.subworkflows).to.have.lengthOf(0); + expect(result.units[0].type).to.equal(UnitType.error); + expect((result.units[0] as ErrorUnitSchema).reason).to.equal("Invalid subworkflow"); + expect(() => new Workflow(result)).to.not.throw(); + }); + it("converts invalid subworkflow unit to error and drops subworkflow", () => { const workflowConfig = structuredClone(Workflow.defaultConfig); const originalUnit = workflowConfig.units[0]; From b0b438b930a13377ab41e3d8b6e37c1717dce759 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 8 Jun 2026 22:37:17 +0300 Subject: [PATCH 05/12] update: improve error unit --- dist/js/Workflow.js | 5 ++++- src/js/Workflow.ts | 5 ++++- tests/js/Workflow.test.ts | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index f436051e..7f7d3f92 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -48,7 +48,10 @@ class Workflow extends entity_1.InMemoryEntity { _id: unit._id, name: unit.name || "error", flowchartId: unit.flowchartId, - originalUnit: unit, + originalUnit: { + unit, + subworkflow, + }, preProcessors: unit.preProcessors || [], postProcessors: unit.postProcessors || [], monitors: unit.monitors || [], diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index bfa5767f..b29f26b3 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -101,7 +101,10 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { _id: unit._id, name: unit.name || "error", flowchartId: unit.flowchartId, - originalUnit: unit, + originalUnit: { + unit, + subworkflow, + }, preProcessors: unit.preProcessors || [], postProcessors: unit.postProcessors || [], monitors: unit.monitors || [], diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index e974cc7c..62102f01 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -484,7 +484,10 @@ describe("Workflow", () => { const errorUnit = result.units[0] as ErrorUnitSchema; expect(errorUnit.reason).to.equal("Invalid subworkflow"); - expect(errorUnit.originalUnit).to.deep.equal(originalUnit); + expect(errorUnit.originalUnit).to.deep.equal({ + unit: originalUnit, + subworkflow: workflowConfig.subworkflows[0], + }); expect(() => new Workflow(result)).to.not.throw(); }); }); From 052ad525661216cdf3888ba833c0cf17a6f11390 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 8 Jun 2026 23:30:36 +0300 Subject: [PATCH 06/12] update: repair ConditionUnit --- dist/js/Subworkflow.js | 8 +++++++- dist/js/units/ConditionUnit.d.ts | 3 ++- dist/js/units/ConditionUnit.js | 23 +++++++++++++++++++++ src/js/Subworkflow.ts | 10 ++++++++- src/js/units/ConditionUnit.ts | 26 ++++++++++++++++++++++-- tests/js/Workflow.test.ts | 35 +++++++++++++++++++++++++++++++- 6 files changed, 99 insertions(+), 6 deletions(-) diff --git a/dist/js/Subworkflow.js b/dist/js/Subworkflow.js index cc77176e..e3127115 100644 --- a/dist/js/Subworkflow.js +++ b/dist/js/Subworkflow.js @@ -23,7 +23,13 @@ class Subworkflow extends entity_1.InMemoryEntity { } static repair(subworkflowData) { const units = subworkflowData.units.map((unit) => { - return unit.type === enums_1.UnitType.execution ? units_1.ExecutionUnit.repair(unit) : unit; + if (unit.type === enums_1.UnitType.execution) { + return units_1.ExecutionUnit.repair(unit); + } + if (unit.type === enums_1.UnitType.condition) { + return units_1.ConditionUnit.repair(unit); + } + return unit; }); return { ...subworkflowData, units }; } diff --git a/dist/js/units/ConditionUnit.d.ts b/dist/js/units/ConditionUnit.d.ts index 79f1b077..6e5e601e 100644 --- a/dist/js/units/ConditionUnit.d.ts +++ b/dist/js/units/ConditionUnit.d.ts @@ -1,6 +1,6 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ConditionUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ConditionUnitSchema, ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; import { type ConditionUnitSchemaMixin } from "../generated/ConditionUnitSchemaMixin"; import BaseUnit from "./BaseUnit"; type Schema = ConditionUnitSchema; @@ -13,5 +13,6 @@ declare class ConditionUnit extends ConditionUnit_base implements Schema { static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; constructor(config: ConditionUnitConfig); getHashObject(): object; + static repair(unitData: Partial): ConditionUnitSchema | ErrorUnitSchema; } export default ConditionUnit; diff --git a/dist/js/units/ConditionUnit.js b/dist/js/units/ConditionUnit.js index bb752ce3..1ad77cb2 100644 --- a/dist/js/units/ConditionUnit.js +++ b/dist/js/units/ConditionUnit.js @@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const JSONSchemasInterface_1 = __importDefault(require("@mat3ra/esse/dist/js/esse/JSONSchemasInterface")); +const utils_1 = require("@mat3ra/utils"); const enums_1 = require("../enums"); const ConditionUnitSchemaMixin_1 = require("../generated/ConditionUnitSchemaMixin"); const BaseUnit_1 = __importDefault(require("./BaseUnit")); @@ -32,6 +33,28 @@ class ConditionUnit extends BaseUnit_1.default { getHashObject() { return { statement: this.statement, maxOccurrences: this.maxOccurrences }; } + static repair(unitData) { + var _a, _b, _c, _d; + try { + return new ConditionUnit(unitData).toJSON(); + } + catch (error) { + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, + type: enums_1.UnitType.error, + status: enums_1.UnitStatus.error, + flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), + reason: JSON.stringify(error), + next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", + head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, + originalUnit: unitData, + }; + } + } } (0, ConditionUnitSchemaMixin_1.conditionUnitSchemaMixin)(ConditionUnit.prototype); exports.default = ConditionUnit; diff --git a/src/js/Subworkflow.ts b/src/js/Subworkflow.ts index 452074b6..55ab62b7 100644 --- a/src/js/Subworkflow.ts +++ b/src/js/Subworkflow.ts @@ -94,7 +94,15 @@ class Subworkflow extends InMemoryEntity implements SubworkflowSchema { static repair(subworkflowData: SubworkflowSchema): SubworkflowSchema { const units = subworkflowData.units.map((unit) => { - return unit.type === UnitType.execution ? ExecutionUnit.repair(unit) : unit; + if (unit.type === UnitType.execution) { + return ExecutionUnit.repair(unit); + } + + if (unit.type === UnitType.condition) { + return ConditionUnit.repair(unit); + } + + return unit; }); return { ...subworkflowData, units }; diff --git a/src/js/units/ConditionUnit.ts b/src/js/units/ConditionUnit.ts index 64af2b17..acd3265c 100644 --- a/src/js/units/ConditionUnit.ts +++ b/src/js/units/ConditionUnit.ts @@ -1,9 +1,10 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ConditionUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ConditionUnitSchema, ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; +import { Utils } from "@mat3ra/utils"; -import { UnitType } from "../enums"; +import { UnitStatus, UnitType } from "../enums"; import { type ConditionUnitSchemaMixin, conditionUnitSchemaMixin, @@ -45,6 +46,27 @@ class ConditionUnit extends (BaseUnit as Base) implements Schema { getHashObject(): object { return { statement: this.statement, maxOccurrences: this.maxOccurrences }; } + + static repair(unitData: Partial): ConditionUnitSchema | ErrorUnitSchema { + try { + return new ConditionUnit(unitData as Schema).toJSON(); + } catch (error: unknown) { + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: unitData.name ?? UnitType.error, + type: UnitType.error, + status: UnitStatus.error, + flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), + reason: JSON.stringify(error), + next: unitData.next ?? "", + head: unitData.head ?? false, + originalUnit: unitData, + }; + } + } } conditionUnitSchemaMixin(ConditionUnit.prototype); diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 62102f01..041a8952 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -8,7 +8,11 @@ import { } from "@mat3ra/code/dist/js/entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import esseSchemas from "@mat3ra/esse/dist/js/schemas.json"; -import type { ErrorUnitSchema, ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { + ConditionUnitSchema, + ErrorUnitSchema, + ExecutionUnitSchema, +} from "@mat3ra/esse/dist/js/types"; import { Material } from "@mat3ra/made"; import { ApplicationRegistry, WorkflowStandata } from "@mat3ra/standata"; import StandataDriver from "@mat3ra/standata/dist/js/StandataDriver"; @@ -354,6 +358,35 @@ describe("Workflow", () => { expect(result.subworkflows[0].units[0]).to.deep.equal(unit); }); + it("repairs legacy condition unit missing then and else via Workflow.repair", () => { + const workflowConfig = structuredClone(Workflow.defaultConfig); + const legacyCondition = { + name: "condition", + type: UnitType.condition, + input: [], + results: [], + preProcessors: [], + postProcessors: [], + statement: "true", + maxOccurrences: 100, + application: defaultApplication, + flowchartId: "e71f01a98db152d645e787b8", + monitors: [], + head: false, + next: "03b383bf35936d1d54d015ad", + }; + + workflowConfig.subworkflows[0].units = [legacyCondition as never]; + + const result = Workflow.repair(workflowConfig); + const condition = result.subworkflows[0].units[0] as ConditionUnitSchema; + + expect(condition.type).to.equal(UnitType.condition); + expect(condition.then).to.equal(""); + expect(condition.else).to.equal(""); + expect(() => new Workflow(result).validate()).to.not.throw(); + }); + it("repairs only invalid execution units inside subworkflow", () => { const workflowConfig = structuredClone(Workflow.defaultConfig); const validUnit = UnitFactory.createDefaultSubworkflowUnit("assignment").toJSON(); From 0fd2f898fa501bcd5f8dcd5e2b375fd949a458fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82=D0=B8?= =?UTF-8?q?=D0=BD=20=D0=94=D0=B2=D0=BE=D1=80=D0=BD=D0=B8=D0=BA?= Date: Tue, 9 Jun 2026 17:56:22 +0300 Subject: [PATCH 07/12] chore: cleanup repair logic --- dist/js/units/BaseUnit.d.ts | 7 +++++- dist/js/units/BaseUnit.js | 25 +++++++++++++++++++++ dist/js/units/ConditionUnit.js | 22 +------------------ dist/js/units/ExecutionUnit.js | 21 +----------------- src/js/units/BaseUnit.ts | 40 ++++++++++++++++++++++++++++++++-- src/js/units/ConditionUnit.ts | 22 ++----------------- src/js/units/ExecutionUnit.ts | 21 ++---------------- 7 files changed, 75 insertions(+), 83 deletions(-) diff --git a/dist/js/units/BaseUnit.d.ts b/dist/js/units/BaseUnit.d.ts index a6a89011..b9349fa9 100644 --- a/dist/js/units/BaseUnit.d.ts +++ b/dist/js/units/BaseUnit.d.ts @@ -7,11 +7,14 @@ import { Taggable } from "@mat3ra/code/dist/js/entity/mixins/TaggableMixin"; import type { NameResultSchema } from "@mat3ra/code/dist/js/utils/object"; import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { StatusSchema, WorkflowBaseUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ErrorUnitSchema, StatusSchema, WorkflowBaseUnitSchema } from "@mat3ra/esse/dist/js/types"; import { type BaseUnitSchemaMixin } from "../generated/BaseUnitSchemaMixin"; import { type StatusSchemaMixin } from "../generated/StatusSchemaMixin"; import { type RuntimeItemsUILogic } from "./mixins/RuntimeItemsUILogicMixin"; type Schema = WorkflowBaseUnitSchema; +type RepairableUnitConstructor> = new (config: C) => { + toJSON(): US; +}; type Base = typeof InMemoryEntity & Constructor & Constructor & Constructor & Constructor & Constructor & Constructor & Constructor & Constructor; declare const BaseUnit_base: Base; declare class BaseUnit extends BaseUnit_base implements Schema { @@ -35,5 +38,7 @@ declare class BaseUnit extends BaseUnit_base implemen isInStatus(status: StatusSchema["status"]): boolean; clone(extraContext: object): this; setRepetition(repetition: number): void; + static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema; + static repairUnit>(UnitClass: RepairableUnitConstructor, unitData: C): US | ErrorUnitSchema; } export default BaseUnit; diff --git a/dist/js/units/BaseUnit.js b/dist/js/units/BaseUnit.js index 773f6524..9ab159c7 100644 --- a/dist/js/units/BaseUnit.js +++ b/dist/js/units/BaseUnit.js @@ -58,6 +58,31 @@ class BaseUnit extends entity_1.InMemoryEntity { setRepetition(repetition) { this.repetition = repetition; } + static toErrorUnitSchema(unitData, error) { + var _a, _b, _c, _d; + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, + type: enums_1.UnitType.error, + status: enums_1.UnitStatus.error, + flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), + reason: JSON.stringify(error), + next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", + head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, + originalUnit: unitData, + }; + } + static repairUnit(UnitClass, unitData) { + try { + return new UnitClass(unitData).toJSON(); + } + catch (error) { + return BaseUnit.toErrorUnitSchema(unitData, error); + } + } } (0, TaggableMixin_1.taggableMixin)(BaseUnit.prototype); (0, HashedEntityMixin_1.hashedEntityMixin)(BaseUnit.prototype); diff --git a/dist/js/units/ConditionUnit.js b/dist/js/units/ConditionUnit.js index 1ad77cb2..627c34a9 100644 --- a/dist/js/units/ConditionUnit.js +++ b/dist/js/units/ConditionUnit.js @@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const JSONSchemasInterface_1 = __importDefault(require("@mat3ra/esse/dist/js/esse/JSONSchemasInterface")); -const utils_1 = require("@mat3ra/utils"); const enums_1 = require("../enums"); const ConditionUnitSchemaMixin_1 = require("../generated/ConditionUnitSchemaMixin"); const BaseUnit_1 = __importDefault(require("./BaseUnit")); @@ -34,26 +33,7 @@ class ConditionUnit extends BaseUnit_1.default { return { statement: this.statement, maxOccurrences: this.maxOccurrences }; } static repair(unitData) { - var _a, _b, _c, _d; - try { - return new ConditionUnit(unitData).toJSON(); - } - catch (error) { - return { - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, - type: enums_1.UnitType.error, - status: enums_1.UnitStatus.error, - flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), - reason: JSON.stringify(error), - next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", - head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, - originalUnit: unitData, - }; - } + return BaseUnit_1.default.repairUnit(ConditionUnit, unitData); } } (0, ConditionUnitSchemaMixin_1.conditionUnitSchemaMixin)(ConditionUnit.prototype); diff --git a/dist/js/units/ExecutionUnit.js b/dist/js/units/ExecutionUnit.js index afe701aa..c1891e7d 100644 --- a/dist/js/units/ExecutionUnit.js +++ b/dist/js/units/ExecutionUnit.js @@ -35,26 +35,7 @@ class ExecutionUnit extends BaseUnit_1.default { this.name = this.name || this.flavor.name || ""; } static repair(unitData) { - var _a, _b, _c, _d; - try { - return new ExecutionUnit(unitData).toJSON(); - } - catch (error) { - return { - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, - type: enums_1.UnitType.error, - status: enums_1.UnitStatus.error, - flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), - reason: JSON.stringify(error), - next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", - head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, - originalUnit: unitData, - }; - } + return BaseUnit_1.default.repairUnit(ExecutionUnit, unitData); } setApplication({ application, executable, flavor, executableName, flavorName, }) { var _a, _b; diff --git a/src/js/units/BaseUnit.ts b/src/js/units/BaseUnit.ts index fd5a24a3..042b96d8 100644 --- a/src/js/units/BaseUnit.ts +++ b/src/js/units/BaseUnit.ts @@ -19,10 +19,14 @@ import { Taggable, taggableMixin } from "@mat3ra/code/dist/js/entity/mixins/Tagg import type { NameResultSchema } from "@mat3ra/code/dist/js/utils/object"; import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { StatusSchema, WorkflowBaseUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { + ErrorUnitSchema, + StatusSchema, + WorkflowBaseUnitSchema, +} from "@mat3ra/esse/dist/js/types"; import { Utils } from "@mat3ra/utils"; -import { UnitStatus } from "../enums"; +import { UnitStatus, UnitType } from "../enums"; import { type BaseUnitSchemaMixin, baseUnitSchemaMixin } from "../generated/BaseUnitSchemaMixin"; import { type StatusSchemaMixin, statusSchemaMixin } from "../generated/StatusSchemaMixin"; import { @@ -32,6 +36,10 @@ import { type Schema = WorkflowBaseUnitSchema; +type RepairableUnitConstructor> = new (config: C) => { + toJSON(): US; +}; + type Base = typeof InMemoryEntity & Constructor & Constructor & @@ -103,6 +111,34 @@ class BaseUnit extends (InMemoryEntity as Base) imple setRepetition(repetition: number) { this.repetition = repetition; } + + static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema { + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: unitData.name ?? UnitType.error, + type: UnitType.error, + status: UnitStatus.error, + flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), + reason: JSON.stringify(error), + next: unitData.next ?? "", + head: unitData.head ?? false, + originalUnit: unitData, + }; + } + + static repairUnit>( + UnitClass: RepairableUnitConstructor, + unitData: C, + ): US | ErrorUnitSchema { + try { + return new UnitClass(unitData).toJSON(); + } catch (error: unknown) { + return BaseUnit.toErrorUnitSchema(unitData as Partial, error); + } + } } taggableMixin(BaseUnit.prototype); diff --git a/src/js/units/ConditionUnit.ts b/src/js/units/ConditionUnit.ts index acd3265c..42b4c924 100644 --- a/src/js/units/ConditionUnit.ts +++ b/src/js/units/ConditionUnit.ts @@ -2,9 +2,8 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; import type { ConditionUnitSchema, ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; -import { Utils } from "@mat3ra/utils"; -import { UnitStatus, UnitType } from "../enums"; +import { UnitType } from "../enums"; import { type ConditionUnitSchemaMixin, conditionUnitSchemaMixin, @@ -48,24 +47,7 @@ class ConditionUnit extends (BaseUnit as Base) implements Schema { } static repair(unitData: Partial): ConditionUnitSchema | ErrorUnitSchema { - try { - return new ConditionUnit(unitData as Schema).toJSON(); - } catch (error: unknown) { - return { - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - name: unitData.name ?? UnitType.error, - type: UnitType.error, - status: UnitStatus.error, - flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), - reason: JSON.stringify(error), - next: unitData.next ?? "", - head: unitData.head ?? false, - originalUnit: unitData, - }; - } + return BaseUnit.repairUnit(ConditionUnit, unitData); } } diff --git a/src/js/units/ExecutionUnit.ts b/src/js/units/ExecutionUnit.ts index cffe4c47..69bb8bd1 100644 --- a/src/js/units/ExecutionUnit.ts +++ b/src/js/units/ExecutionUnit.ts @@ -15,7 +15,7 @@ import { createProvider, } from "../context/providers"; import type ConvergenceParameter from "../convergence/ConvergenceParameter"; -import { UnitStatus, UnitType } from "../enums"; +import { UnitType } from "../enums"; import { type ExecutionUnitSchemaMixin, executionUnitSchemaMixin, @@ -73,24 +73,7 @@ class ExecutionUnit extends (BaseUnit as Base) implements Schema { } static repair(unitData: Partial): ExecutionUnitSchema | ErrorUnitSchema { - try { - return new ExecutionUnit(unitData as Schema).toJSON(); - } catch (error: unknown) { - return { - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - name: unitData.name ?? UnitType.error, - type: UnitType.error, - status: UnitStatus.error, - flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), - reason: JSON.stringify(error), - next: unitData.next ?? "", - head: unitData.head ?? false, - originalUnit: unitData, - }; - } + return BaseUnit.repairUnit(ExecutionUnit, unitData as ExecutionUnitConfig); } setApplication({ From 602cd15c4c34e17e84d2e65abba8d7ddd3dd2b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82=D0=B8?= =?UTF-8?q?=D0=BD=20=D0=94=D0=B2=D0=BE=D1=80=D0=BD=D0=B8=D0=BA?= Date: Tue, 9 Jun 2026 19:08:49 +0300 Subject: [PATCH 08/12] chore: improve error unit --- dist/js/Workflow.d.ts | 2 +- dist/js/Workflow.js | 43 ++++++++++++++++++++---------- dist/js/units/BaseUnit.js | 15 ++++++----- src/js/Workflow.ts | 55 +++++++++++++++++++++++++++------------ src/js/units/BaseUnit.ts | 8 +++++- tests/js/Workflow.test.ts | 8 ++++-- 6 files changed, 91 insertions(+), 40 deletions(-) diff --git a/dist/js/Workflow.d.ts b/dist/js/Workflow.d.ts index 7e26a08c..11192b97 100644 --- a/dist/js/Workflow.d.ts +++ b/dist/js/Workflow.d.ts @@ -28,7 +28,7 @@ declare class Workflow extends InMemoryEntity implements WorkflowSchema { static readonly defaultConfig: WorkflowSchema; _json: WorkflowSchema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; - private static isValidSubworkflow; + private static getSubworkflowValidationError; static repair(workflowData: WorkflowSchema): WorkflowSchema; subworkflowInstances: Subworkflow[]; unitInstances: AnyWorkflowUnit[]; diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index 7f7d3f92..29241479 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const entity_1 = require("@mat3ra/code/dist/js/entity"); +const in_memory_1 = require("@mat3ra/code/dist/js/entity/in_memory"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); const HasDescriptionMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasDescriptionMixin"); const HashedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"); @@ -24,29 +25,44 @@ class Workflow extends entity_1.InMemoryEntity { static get jsonSchema() { return JSONSchemasInterface_1.default.getSchemaById("workflow"); } - // TODO: add static isValid method for InMemoryEntity - static isValidSubworkflow(subworkflow) { + static getSubworkflowValidationError(subworkflow) { + // Two checks, same order as the old isValid() path (construct + validate), but split so we + // keep AJV errors when hydration would fail first: + // 1. validateData — JSON Schema on raw persisted subworkflow (no Application/ModelFactory/units). + // Surfaces structured AJV errors (e.g. missing model) before the constructor runs. + // 2. new Subworkflow().validate() — hydration (app, model, units) then schema on the instance. + // Catches schema-valid JSON that still cannot be built (unknown model, bad units, etc.). try { - return new Subworkflow_1.default(subworkflow).isValid(); + Subworkflow_1.default.validateData({ ...subworkflow }); + new Subworkflow_1.default(subworkflow).validate(); + return null; } - catch (_a) { - return false; + catch (error) { + if (error instanceof in_memory_1.EntityError || error instanceof Error) { + return error; + } + return new Error(String(error)); } } static repair(workflowData) { const subworkflows = workflowData.subworkflows.map((subworkflow) => { return Subworkflow_1.default.repair(subworkflow); }); - const invalidSubworkflows = subworkflows.filter((subworkflow) => { - return !Workflow.isValidSubworkflow(subworkflow); - }); + const invalidSubworkflows = subworkflows + .map((subworkflow) => { + const error = Workflow.getSubworkflowValidationError(subworkflow); + return error ? { subworkflow, error } : null; + }) + .filter((entry) => entry !== null); const units = workflowData.units.map((unit) => { - const subworkflow = invalidSubworkflows.find((subworkflow) => subworkflow._id === unit._id); - if (subworkflow) { + const invalidEntry = invalidSubworkflows.find(({ subworkflow }) => subworkflow._id === unit._id); + if (invalidEntry) { + const { subworkflow, error } = invalidEntry; + const errorUnit = units_1.BaseUnit.toErrorUnitSchema(unit, error); return { - type: enums_1.UnitType.error, + ...errorUnit, _id: unit._id, - name: unit.name || "error", + name: unit.name || errorUnit.name, flowchartId: unit.flowchartId, originalUnit: { unit, @@ -56,13 +72,12 @@ class Workflow extends entity_1.InMemoryEntity { postProcessors: unit.postProcessors || [], monitors: unit.monitors || [], results: unit.results || [], - reason: "Invalid subworkflow", }; } return unit; }); const validSubworkflows = subworkflows.filter((subworkflow) => { - return !invalidSubworkflows.map(({ _id }) => _id).includes(subworkflow._id); + return !invalidSubworkflows.some(({ subworkflow: invalid }) => invalid._id === subworkflow._id); }); const workflows = workflowData.workflows.map((nested) => { return Workflow.repair(nested); diff --git a/dist/js/units/BaseUnit.js b/dist/js/units/BaseUnit.js index 9ab159c7..6358d576 100644 --- a/dist/js/units/BaseUnit.js +++ b/dist/js/units/BaseUnit.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const entity_1 = require("@mat3ra/code/dist/js/entity"); +const in_memory_1 = require("@mat3ra/code/dist/js/entity/in_memory"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); const HashedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"); const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"); @@ -59,19 +60,21 @@ class BaseUnit extends entity_1.InMemoryEntity { this.repetition = repetition; } static toErrorUnitSchema(unitData, error) { - var _a, _b, _c, _d; + var _a, _b, _c, _d, _e; + const detailsError = error instanceof in_memory_1.EntityError ? (_a = error.details) === null || _a === void 0 ? void 0 : _a.error : undefined; + const reasonPayload = detailsError !== null && detailsError !== void 0 ? detailsError : (error instanceof Error ? { message: error.message, name: error.name } : error); return { results: [], preProcessors: [], postProcessors: [], monitors: [], - name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, + name: (_b = unitData.name) !== null && _b !== void 0 ? _b : enums_1.UnitType.error, type: enums_1.UnitType.error, status: enums_1.UnitStatus.error, - flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), - reason: JSON.stringify(error), - next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", - head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, + flowchartId: (_c = unitData.flowchartId) !== null && _c !== void 0 ? _c : utils_1.Utils.uuid.getUUID(), + reason: JSON.stringify(reasonPayload), + next: (_d = unitData.next) !== null && _d !== void 0 ? _d : "", + head: (_e = unitData.head) !== null && _e !== void 0 ? _e : false, originalUnit: unitData, }; } diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index b29f26b3..19fa62d2 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -1,4 +1,5 @@ import { type NamedInMemoryEntity, InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import { EntityError } from "@mat3ra/code/dist/js/entity/in_memory"; import { type Defaultable, defaultableEntityMixin, @@ -29,7 +30,7 @@ import type { JobExternalContext } from "./context/providers/by_application/espr import { UnitType } from "./enums"; import { type WorkflowSchemaMixin, workflowSchemaMixin } from "./generated/WorkflowSchemaMixin"; import Subworkflow from "./Subworkflow"; -import { MapUnit } from "./units"; +import { BaseUnit, MapUnit } from "./units"; import { type AnyWorkflowUnit, type AnyWorkflowUnitSchema, UnitFactory } from "./units/factory"; import { getDefaultDescription, @@ -72,12 +73,24 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { return JSONSchemasInterface.getSchemaById("workflow"); } - // TODO: add static isValid method for InMemoryEntity - private static isValidSubworkflow(subworkflow: SubworkflowSchema): boolean { + private static getSubworkflowValidationError( + subworkflow: SubworkflowSchema, + ): EntityError | Error | null { + // Two checks, same order as the old isValid() path (construct + validate), but split so we + // keep AJV errors when hydration would fail first: + // 1. validateData — JSON Schema on raw persisted subworkflow (no Application/ModelFactory/units). + // Surfaces structured AJV errors (e.g. missing model) before the constructor runs. + // 2. new Subworkflow().validate() — hydration (app, model, units) then schema on the instance. + // Catches schema-valid JSON that still cannot be built (unknown model, bad units, etc.). try { - return new Subworkflow(subworkflow).isValid(); - } catch { - return false; + Subworkflow.validateData({ ...subworkflow }); + new Subworkflow(subworkflow).validate(); + return null; + } catch (error: unknown) { + if (error instanceof EntityError || error instanceof Error) { + return error; + } + return new Error(String(error)); } } @@ -86,20 +99,29 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { return Subworkflow.repair(subworkflow); }); - const invalidSubworkflows = subworkflows.filter((subworkflow) => { - return !Workflow.isValidSubworkflow(subworkflow); - }); + const invalidSubworkflows = subworkflows + .map((subworkflow) => { + const error = Workflow.getSubworkflowValidationError(subworkflow); + return error ? { subworkflow, error } : null; + }) + .filter( + (entry): entry is { subworkflow: SubworkflowSchema; error: EntityError | Error } => + entry !== null, + ); const units = workflowData.units.map((unit): AnyWorkflowUnitSchema => { - const subworkflow = invalidSubworkflows.find( - (subworkflow) => subworkflow._id === unit._id, + const invalidEntry = invalidSubworkflows.find( + ({ subworkflow }) => subworkflow._id === unit._id, ); - if (subworkflow) { + if (invalidEntry) { + const { subworkflow, error } = invalidEntry; + const errorUnit = BaseUnit.toErrorUnitSchema(unit, error); + return { - type: UnitType.error, + ...errorUnit, _id: unit._id, - name: unit.name || "error", + name: unit.name || errorUnit.name, flowchartId: unit.flowchartId, originalUnit: { unit, @@ -109,7 +131,6 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { postProcessors: unit.postProcessors || [], monitors: unit.monitors || [], results: unit.results || [], - reason: "Invalid subworkflow", }; } @@ -117,7 +138,9 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { }); const validSubworkflows = subworkflows.filter((subworkflow) => { - return !invalidSubworkflows.map(({ _id }) => _id).includes(subworkflow._id); + return !invalidSubworkflows.some( + ({ subworkflow: invalid }) => invalid._id === subworkflow._id, + ); }); const workflows = workflowData.workflows.map((nested) => { diff --git a/src/js/units/BaseUnit.ts b/src/js/units/BaseUnit.ts index 042b96d8..edf17e18 100644 --- a/src/js/units/BaseUnit.ts +++ b/src/js/units/BaseUnit.ts @@ -1,4 +1,5 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import { EntityError } from "@mat3ra/code/dist/js/entity/in_memory"; import { type Defaultable, defaultableEntityMixin, @@ -113,6 +114,11 @@ class BaseUnit extends (InMemoryEntity as Base) imple } static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema { + const detailsError = error instanceof EntityError ? error.details?.error : undefined; + const reasonPayload = + detailsError ?? + (error instanceof Error ? { message: error.message, name: error.name } : error); + return { results: [], preProcessors: [], @@ -122,7 +128,7 @@ class BaseUnit extends (InMemoryEntity as Base) imple type: UnitType.error, status: UnitStatus.error, flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), - reason: JSON.stringify(error), + reason: JSON.stringify(reasonPayload), next: unitData.next ?? "", head: unitData.head ?? false, originalUnit: unitData, diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 041a8952..23524f8e 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -491,7 +491,8 @@ describe("Workflow", () => { expect(result.subworkflows).to.have.lengthOf(0); expect(result.units[0].type).to.equal(UnitType.error); - expect((result.units[0] as ErrorUnitSchema).reason).to.equal("Invalid subworkflow"); + const legacyErrorReason = JSON.parse((result.units[0] as ErrorUnitSchema).reason); + expect(legacyErrorReason).to.be.an("array").that.is.not.empty; expect(() => new Workflow(result)).to.not.throw(); }); @@ -516,7 +517,10 @@ describe("Workflow", () => { expect(result.units[0]._id).to.equal(subworkflowId); const errorUnit = result.units[0] as ErrorUnitSchema; - expect(errorUnit.reason).to.equal("Invalid subworkflow"); + const validationErrors = JSON.parse(errorUnit.reason); + expect(validationErrors).to.be.an("array").that.is.not.empty; + expect(validationErrors.some((e: { instancePath?: string }) => e.instancePath)).to.be + .true; expect(errorUnit.originalUnit).to.deep.equal({ unit: originalUnit, subworkflow: workflowConfig.subworkflows[0], From ef12d68849048fb006db2fafaccce072287f978c Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Fri, 12 Jun 2026 19:10:15 +0300 Subject: [PATCH 09/12] chore: cleanup error unit --- dist/js/Subworkflow.d.ts | 1 - dist/js/Workflow.js | 9 +- dist/js/generated/ErrorUnitSchemaMixin.js | 6 - dist/js/units/BaseUnit.js | 33 +- dist/js/units/ErrorUnit.js | 1 - package-lock.json | 438 ++++++---------------- package.json | 6 +- src/js/Workflow.ts | 9 +- src/js/generated/ErrorUnitSchemaMixin.ts | 6 - src/js/units/BaseUnit.ts | 24 +- src/js/units/ErrorUnit.ts | 1 - tests/js/Workflow.test.ts | 17 +- 12 files changed, 186 insertions(+), 365 deletions(-) diff --git a/dist/js/Subworkflow.d.ts b/dist/js/Subworkflow.d.ts index 170e9dd6..9b5b22dd 100644 --- a/dist/js/Subworkflow.d.ts +++ b/dist/js/Subworkflow.d.ts @@ -734,7 +734,6 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { flowchartId: string; next?: string; enableRender?: boolean; - originalUnit: {}; reason: string; } | undefined; findUnitKeyById(id: string): string; diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index 29241479..e96ac2f9 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -59,15 +59,16 @@ class Workflow extends entity_1.InMemoryEntity { if (invalidEntry) { const { subworkflow, error } = invalidEntry; const errorUnit = units_1.BaseUnit.toErrorUnitSchema(unit, error); + const reasonPayload = { + ...JSON.parse(errorUnit.reason), + json: { unit, subworkflow }, + }; return { ...errorUnit, _id: unit._id, name: unit.name || errorUnit.name, flowchartId: unit.flowchartId, - originalUnit: { - unit, - subworkflow, - }, + reason: JSON.stringify(reasonPayload), preProcessors: unit.preProcessors || [], postProcessors: unit.postProcessors || [], monitors: unit.monitors || [], diff --git a/dist/js/generated/ErrorUnitSchemaMixin.js b/dist/js/generated/ErrorUnitSchemaMixin.js index 050ea373..befe9ec7 100644 --- a/dist/js/generated/ErrorUnitSchemaMixin.js +++ b/dist/js/generated/ErrorUnitSchemaMixin.js @@ -10,12 +10,6 @@ function errorUnitSchemaMixin(item) { set type(value) { this.setProp("type", value); }, - get originalUnit() { - return this.requiredProp("originalUnit"); - }, - set originalUnit(value) { - this.setProp("originalUnit", value); - }, get reason() { return this.requiredProp("reason"); }, diff --git a/dist/js/units/BaseUnit.js b/dist/js/units/BaseUnit.js index 6358d576..bdd57155 100644 --- a/dist/js/units/BaseUnit.js +++ b/dist/js/units/BaseUnit.js @@ -60,22 +60,39 @@ class BaseUnit extends entity_1.InMemoryEntity { this.repetition = repetition; } static toErrorUnitSchema(unitData, error) { - var _a, _b, _c, _d, _e; - const detailsError = error instanceof in_memory_1.EntityError ? (_a = error.details) === null || _a === void 0 ? void 0 : _a.error : undefined; - const reasonPayload = detailsError !== null && detailsError !== void 0 ? detailsError : (error instanceof Error ? { message: error.message, name: error.name } : error); + var _a, _b, _c, _d; + let reasonPayload; + if (error instanceof in_memory_1.EntityError && error.details) { + reasonPayload = { + error: error.details.error, + json: unitData, + schema: error.details.schema, + }; + } + else if (error instanceof Error) { + reasonPayload = { + error: { message: error.message, name: error.name }, + json: unitData, + }; + } + else { + reasonPayload = { + error, + json: unitData, + }; + } return { results: [], preProcessors: [], postProcessors: [], monitors: [], - name: (_b = unitData.name) !== null && _b !== void 0 ? _b : enums_1.UnitType.error, + name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, type: enums_1.UnitType.error, status: enums_1.UnitStatus.error, - flowchartId: (_c = unitData.flowchartId) !== null && _c !== void 0 ? _c : utils_1.Utils.uuid.getUUID(), + flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), reason: JSON.stringify(reasonPayload), - next: (_d = unitData.next) !== null && _d !== void 0 ? _d : "", - head: (_e = unitData.head) !== null && _e !== void 0 ? _e : false, - originalUnit: unitData, + next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", + head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, }; } static repairUnit(UnitClass, unitData) { diff --git a/dist/js/units/ErrorUnit.js b/dist/js/units/ErrorUnit.js index 63d12a7f..0ec1078e 100644 --- a/dist/js/units/ErrorUnit.js +++ b/dist/js/units/ErrorUnit.js @@ -19,7 +19,6 @@ class ErrorUnit extends BaseUnit_1.default { preProcessors: [], postProcessors: [], monitors: [], - originalUnit: {}, reason: "", ...config, type: enums_1.UnitType.error, diff --git a/package-lock.json b/package-lock.json index f4b0afba..93d8f2c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/6cd64a17df299d2804a913c1367726a022a6df9a.tar.gz", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/7b8fd3cdb25d9e5ffa20de930becf408dbc0f759.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", @@ -28,6 +28,8 @@ "@mat3ra/tsconfig": "^2024.6.3-0", "@mat3ra/utils": "2025.9.20-0", "@types/nunjucks": "^3.2.6", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", "chai": "^4.3.4", "eslint": "^7.32.0", "eslint-config-airbnb": "^19.0.2", @@ -56,7 +58,7 @@ "peerDependencies": { "@mat3ra/ade": "*", "@mat3ra/code": "*", - "@mat3ra/esse": "*", + "@mat3ra/esse": "file:../esse/mat3ra-esse-0.0.0.tgz", "@mat3ra/ide": "*", "@mat3ra/made": "*", "@mat3ra/mode": "*", @@ -471,6 +473,7 @@ }, "node_modules/@babel/highlight": { "version": "7.25.9", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -484,6 +487,7 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -494,6 +498,7 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", @@ -506,6 +511,7 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", + "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -513,10 +519,12 @@ }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", + "dev": true, "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -524,6 +532,7 @@ }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -531,6 +540,7 @@ }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -2287,7 +2297,6 @@ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "eslint-visitor-keys": "^3.4.3" }, @@ -2307,7 +2316,6 @@ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2321,13 +2329,13 @@ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "0.4.3", + "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -2346,6 +2354,7 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -2360,6 +2369,7 @@ }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "1.0.10", + "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -2367,6 +2377,7 @@ }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -2374,6 +2385,7 @@ }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "3.14.1", + "dev": true, "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -2385,10 +2397,12 @@ }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", + "dev": true, "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/sprintf-js": { "version": "1.0.3", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@exabyte-io/eslint-config": { @@ -2464,6 +2478,7 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.5.0", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", @@ -2476,6 +2491,7 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/load-nyc-config": { @@ -2686,8 +2702,8 @@ }, "node_modules/@mat3ra/esse": { "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/esse/archive/6cd64a17df299d2804a913c1367726a022a6df9a.tar.gz", - "integrity": "sha512-IZ8hLoj0yYaP1M0jJQloufrAY4qWHuZe7JTYFuIyiw2uAqQ03mD4oTW0dftMdVdRkwPp6sXGxqv6Sgpc9/HfZg==", + "resolved": "https://github.com/Exabyte-io/esse/archive/7b8fd3cdb25d9e5ffa20de930becf408dbc0f759.tar.gz", + "integrity": "sha512-EhjMRV0DabAl/uJEm93jjdkaUaO1zYdokktvzU3/IAtgAw0cKAbUZ3Obs4SCiLmWOWGthqvhTMk6oLDz4PxFQg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4185,7 +4201,6 @@ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -4200,7 +4215,6 @@ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 8" } @@ -4211,7 +4225,6 @@ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4220,20 +4233,6 @@ "node": ">= 8" } }, - "node_modules/@pkgr/core": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", - "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "dev": true, @@ -4361,8 +4360,7 @@ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/sprintf-js": { "version": "1.1.4", @@ -4390,7 +4388,6 @@ "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.62.0", @@ -4421,12 +4418,11 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -4440,7 +4436,6 @@ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -4469,7 +4464,6 @@ "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" @@ -4488,7 +4482,6 @@ "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/typescript-estree": "5.62.0", "@typescript-eslint/utils": "5.62.0", @@ -4517,7 +4510,6 @@ "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4532,7 +4524,6 @@ "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", @@ -4556,12 +4547,11 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -4575,7 +4565,6 @@ "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -4598,12 +4587,11 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -4617,7 +4605,6 @@ "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" @@ -4636,7 +4623,6 @@ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4655,6 +4641,7 @@ }, "node_modules/acorn": { "version": "7.4.1", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4665,6 +4652,7 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -4708,6 +4696,7 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -4750,6 +4739,7 @@ }, "node_modules/ansi-colors": { "version": "4.1.3", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4782,6 +4772,7 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4789,6 +4780,7 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4901,7 +4893,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -4979,6 +4970,7 @@ }, "node_modules/astral-regex": { "version": "2.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5214,6 +5206,7 @@ }, "node_modules/callsites": { "version": "3.1.0", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5266,6 +5259,7 @@ }, "node_modules/chalk": { "version": "4.1.2", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -5471,6 +5465,7 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5481,6 +5476,7 @@ }, "node_modules/color-name": { "version": "1.1.4", + "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -5590,6 +5586,7 @@ }, "node_modules/cross-spawn": { "version": "7.0.6", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5720,6 +5717,7 @@ }, "node_modules/deep-is": { "version": "0.1.4", + "dev": true, "license": "MIT" }, "node_modules/default-require-extensions": { @@ -5783,24 +5781,12 @@ "node": ">=0.3.1" } }, - "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "path-type": "^4.0.0" }, @@ -5810,6 +5796,7 @@ }, "node_modules/doctrine": { "version": "3.0.0", + "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" @@ -5849,6 +5836,7 @@ }, "node_modules/enquirer": { "version": "2.4.1", + "dev": true, "license": "MIT", "dependencies": { "ansi-colors": "^4.1.1", @@ -6012,6 +6000,7 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -6022,6 +6011,7 @@ }, "node_modules/eslint": { "version": "7.32.0", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "7.12.11", @@ -6075,37 +6065,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-compat-utils": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz", - "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/eslint-compat-utils/node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-config-airbnb": { "version": "19.0.2", "dev": true, @@ -6197,29 +6156,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-json-compat-utils": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/eslint-json-compat-utils/-/eslint-json-compat-utils-0.2.3.tgz", - "integrity": "sha512-RbBmDFyu7FqnjE8F0ZxPNzx5UaptdeS9Uu50r7A+D7s/+FCX+ybiyViYEgFUaFIFqSWJgZRTpL5d8Kanxxl2lQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "esquery": "^1.6.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": "*", - "jsonc-eslint-parser": "^2.4.0 || ^3.0.0" - }, - "peerDependenciesMeta": { - "@eslint/json": { - "optional": true - } - } - }, "node_modules/eslint-module-utils": { "version": "2.12.1", "dev": true, @@ -6327,81 +6263,6 @@ "node": ">=10" } }, - "node_modules/eslint-plugin-jsonc": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.21.1.tgz", - "integrity": "sha512-dbNR5iEnQeORwsK2WZzr3QaMtFCY3kKJVMRHPzUpKzMhmVy2zIpVgFDpX8MNoIdoqz6KCpCfOJavhfiSbZbN+w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.5.1", - "diff-sequences": "^27.5.1", - "eslint-compat-utils": "^0.6.4", - "eslint-json-compat-utils": "^0.2.1", - "espree": "^9.6.1 || ^10.3.0", - "graphemer": "^1.4.0", - "jsonc-eslint-parser": "^2.4.0", - "natural-compare": "^1.4.0", - "synckit": "^0.6.2 || ^0.7.3 || ^0.11.5" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/eslint-plugin-jsonc/node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eslint-plugin-jsonc/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-jsonc/node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.5.1", "dev": true, @@ -6488,20 +6349,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "dev": true, @@ -6557,6 +6404,7 @@ }, "node_modules/eslint-utils": { "version": "2.1.0", + "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" @@ -6570,6 +6418,7 @@ }, "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { "version": "1.3.0", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=4" @@ -6584,6 +6433,7 @@ }, "node_modules/eslint/node_modules/@babel/code-frame": { "version": "7.12.11", + "dev": true, "license": "MIT", "dependencies": { "@babel/highlight": "^7.10.4" @@ -6591,6 +6441,7 @@ }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -6605,6 +6456,7 @@ }, "node_modules/eslint/node_modules/argparse": { "version": "1.0.10", + "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -6612,6 +6464,7 @@ }, "node_modules/eslint/node_modules/ignore": { "version": "4.0.6", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -6619,6 +6472,7 @@ }, "node_modules/eslint/node_modules/js-yaml": { "version": "3.14.1", + "dev": true, "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -6630,10 +6484,12 @@ }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", + "dev": true, "license": "MIT" }, "node_modules/eslint/node_modules/semver": { "version": "7.7.3", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -6644,10 +6500,12 @@ }, "node_modules/eslint/node_modules/sprintf-js": { "version": "1.0.3", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/espree": { "version": "7.3.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^7.4.0", @@ -6660,6 +6518,7 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "1.3.0", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=4" @@ -6667,6 +6526,7 @@ }, "node_modules/esprima": { "version": "4.0.1", + "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -6678,6 +6538,7 @@ }, "node_modules/esquery": { "version": "1.6.0", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -6734,6 +6595,7 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -6747,7 +6609,6 @@ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -6761,14 +6622,17 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "dev": true, "license": "MIT" }, "node_modules/fast-uri": { "version": "3.1.0", + "dev": true, "funding": [ { "type": "github", @@ -6787,13 +6651,13 @@ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { "version": "6.0.1", + "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" @@ -6850,6 +6714,7 @@ }, "node_modules/flat-cache": { "version": "3.2.0", + "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -6862,6 +6727,7 @@ }, "node_modules/flatted": { "version": "3.3.3", + "dev": true, "license": "ISC" }, "node_modules/for-each": { @@ -6964,6 +6830,7 @@ }, "node_modules/functional-red-black-tree": { "version": "1.0.1", + "dev": true, "license": "MIT" }, "node_modules/functions-have-names": { @@ -7095,6 +6962,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", + "devOptional": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -7105,6 +6973,7 @@ }, "node_modules/globals": { "version": "13.24.0", + "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.20.2" @@ -7137,7 +7006,6 @@ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -7159,7 +7027,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -7185,8 +7052,7 @@ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/growl": { "version": "1.10.5", @@ -7217,6 +7083,7 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7346,13 +7213,13 @@ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.1", + "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -7367,6 +7234,7 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -7543,6 +7411,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7593,6 +7462,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "devOptional": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -7882,6 +7752,7 @@ }, "node_modules/isexe": { "version": "2.0.0", + "dev": true, "license": "ISC" }, "node_modules/isobject": { @@ -8062,6 +7933,7 @@ }, "node_modules/json-buffer": { "version": "3.0.1", + "dev": true, "license": "MIT" }, "node_modules/json-schema": { @@ -8156,10 +8028,12 @@ }, "node_modules/json-schema-traverse": { "version": "1.0.0", + "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "dev": true, "license": "MIT" }, "node_modules/json5": { @@ -8172,87 +8046,6 @@ "node": ">=6" } }, - "node_modules/jsonc-eslint-parser": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.2.tgz", - "integrity": "sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "acorn": "^8.5.0", - "eslint-visitor-keys": "^3.0.0", - "espree": "^9.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - } - }, - "node_modules/jsonc-eslint-parser/node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/jsonc-eslint-parser/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/jsonc-eslint-parser/node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "dev": true, @@ -8269,6 +8062,7 @@ }, "node_modules/keyv": { "version": "4.5.4", + "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -8299,6 +8093,7 @@ }, "node_modules/levn": { "version": "0.4.1", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -8477,10 +8272,12 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", + "dev": true, "license": "MIT" }, "node_modules/lodash.truncate": { "version": "4.4.2", + "dev": true, "license": "MIT" }, "node_modules/log-symbols": { @@ -8683,7 +8480,6 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 8" } @@ -8910,6 +8706,7 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "dev": true, "license": "MIT" }, "node_modules/natural-compare-lite": { @@ -8917,8 +8714,7 @@ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/node-preload": { "version": "0.2.1", @@ -9354,6 +9150,7 @@ }, "node_modules/optionator": { "version": "0.9.4", + "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -9448,6 +9245,7 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -9473,6 +9271,7 @@ }, "node_modules/path-key": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9488,7 +9287,6 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -9619,6 +9417,7 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -9662,6 +9461,7 @@ }, "node_modules/progress": { "version": "2.0.3", + "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -9679,6 +9479,7 @@ }, "node_modules/punycode": { "version": "2.3.1", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9703,8 +9504,7 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", @@ -9791,6 +9591,7 @@ }, "node_modules/regexpp": { "version": "3.2.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9857,6 +9658,7 @@ }, "node_modules/require-from-string": { "version": "2.0.2", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9895,6 +9697,7 @@ }, "node_modules/resolve-from": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -9926,7 +9729,6 @@ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -9939,6 +9741,7 @@ }, "node_modules/rimraf": { "version": "3.0.2", + "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -9970,7 +9773,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "queue-microtask": "^1.2.2" } @@ -10136,6 +9938,7 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -10146,6 +9949,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10474,6 +10278,7 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -10500,6 +10305,7 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10510,6 +10316,7 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -10528,25 +10335,9 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/synckit": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", - "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@pkgr/core": "^0.3.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" - } - }, "node_modules/table": { "version": "6.9.0", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "ajv": "^8.0.1", @@ -10561,10 +10352,12 @@ }, "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", + "dev": true, "license": "MIT" }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10572,6 +10365,7 @@ }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -10587,6 +10381,7 @@ }, "node_modules/table/node_modules/string-width": { "version": "4.2.3", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -10612,6 +10407,7 @@ }, "node_modules/text-table": { "version": "0.2.0", + "dev": true, "license": "MIT" }, "node_modules/through": { @@ -10803,7 +10599,6 @@ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tslib": "^1.8.1" }, @@ -10819,11 +10614,11 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -10842,6 +10637,7 @@ }, "node_modules/type-fest": { "version": "0.20.2", + "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -11072,6 +10868,7 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -11091,6 +10888,7 @@ }, "node_modules/v8-compile-cache": { "version": "2.4.0", + "dev": true, "license": "MIT" }, "node_modules/v8-compile-cache-lib": { @@ -11144,6 +10942,7 @@ }, "node_modules/which": { "version": "2.0.2", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -11243,6 +11042,7 @@ }, "node_modules/word-wrap": { "version": "1.2.5", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index 3de142ef..04c3f155 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/6cd64a17df299d2804a913c1367726a022a6df9a.tar.gz", + "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/7b8fd3cdb25d9e5ffa20de930becf408dbc0f759.tar.gz", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", @@ -50,6 +50,8 @@ "@mat3ra/standata": "2026.5.28-0", "@mat3ra/tsconfig": "^2024.6.3-0", "@mat3ra/utils": "2025.9.20-0", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", "@types/nunjucks": "^3.2.6", "chai": "^4.3.4", "eslint": "^7.32.0", @@ -76,7 +78,7 @@ "peerDependencies": { "@mat3ra/ade": "*", "@mat3ra/code": "*", - "@mat3ra/esse": "*", + "@mat3ra/esse": "file:../esse/mat3ra-esse-0.0.0.tgz", "@mat3ra/ide": "*", "@mat3ra/made": "*", "@mat3ra/mode": "*", diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index 19fa62d2..97fbe39a 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -117,16 +117,17 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { if (invalidEntry) { const { subworkflow, error } = invalidEntry; const errorUnit = BaseUnit.toErrorUnitSchema(unit, error); + const reasonPayload = { + ...JSON.parse(errorUnit.reason), + json: { unit, subworkflow }, + }; return { ...errorUnit, _id: unit._id, name: unit.name || errorUnit.name, flowchartId: unit.flowchartId, - originalUnit: { - unit, - subworkflow, - }, + reason: JSON.stringify(reasonPayload), preProcessors: unit.preProcessors || [], postProcessors: unit.postProcessors || [], monitors: unit.monitors || [], diff --git a/src/js/generated/ErrorUnitSchemaMixin.ts b/src/js/generated/ErrorUnitSchemaMixin.ts index 75aa9a08..dd89d7b6 100644 --- a/src/js/generated/ErrorUnitSchemaMixin.ts +++ b/src/js/generated/ErrorUnitSchemaMixin.ts @@ -16,12 +16,6 @@ export function errorUnitSchemaMixin( set type(value: ErrorUnitMixinSchema["type"]) { this.setProp("type", value); }, - get originalUnit() { - return this.requiredProp("originalUnit"); - }, - set originalUnit(value: ErrorUnitMixinSchema["originalUnit"]) { - this.setProp("originalUnit", value); - }, get reason() { return this.requiredProp("reason"); }, diff --git a/src/js/units/BaseUnit.ts b/src/js/units/BaseUnit.ts index edf17e18..3f704279 100644 --- a/src/js/units/BaseUnit.ts +++ b/src/js/units/BaseUnit.ts @@ -114,10 +114,25 @@ class BaseUnit extends (InMemoryEntity as Base) imple } static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema { - const detailsError = error instanceof EntityError ? error.details?.error : undefined; - const reasonPayload = - detailsError ?? - (error instanceof Error ? { message: error.message, name: error.name } : error); + let reasonPayload: { error: unknown; json: object; schema?: unknown }; + + if (error instanceof EntityError && error.details) { + reasonPayload = { + error: error.details.error, + json: unitData as object, + schema: error.details.schema, + }; + } else if (error instanceof Error) { + reasonPayload = { + error: { message: error.message, name: error.name }, + json: unitData as object, + }; + } else { + reasonPayload = { + error, + json: unitData as object, + }; + } return { results: [], @@ -131,7 +146,6 @@ class BaseUnit extends (InMemoryEntity as Base) imple reason: JSON.stringify(reasonPayload), next: unitData.next ?? "", head: unitData.head ?? false, - originalUnit: unitData, }; } diff --git a/src/js/units/ErrorUnit.ts b/src/js/units/ErrorUnit.ts index 661e2679..4e43263e 100644 --- a/src/js/units/ErrorUnit.ts +++ b/src/js/units/ErrorUnit.ts @@ -28,7 +28,6 @@ class ErrorUnit extends (BaseUnit as Base) implements Schema { preProcessors: [], postProcessors: [], monitors: [], - originalUnit: {}, reason: "", ...config, type: UnitType.error as Schema["type"], diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 23524f8e..219745c9 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -340,9 +340,10 @@ describe("Workflow", () => { const result = Workflow.repair(workflowConfig); expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); - expect((result.subworkflows[0].units[0] as ErrorUnitSchema).originalUnit).to.deep.equal( - invalid, + const subworkflowErrorReason = JSON.parse( + (result.subworkflows[0].units[0] as ErrorUnitSchema).reason, ); + expect(subworkflowErrorReason.json).to.deep.equal(invalid); }); it("leaves valid execution unit unchanged inside subworkflow", () => { @@ -492,7 +493,7 @@ describe("Workflow", () => { expect(result.subworkflows).to.have.lengthOf(0); expect(result.units[0].type).to.equal(UnitType.error); const legacyErrorReason = JSON.parse((result.units[0] as ErrorUnitSchema).reason); - expect(legacyErrorReason).to.be.an("array").that.is.not.empty; + expect(legacyErrorReason.error).to.be.an("array").that.is.not.empty; expect(() => new Workflow(result)).to.not.throw(); }); @@ -517,11 +518,11 @@ describe("Workflow", () => { expect(result.units[0]._id).to.equal(subworkflowId); const errorUnit = result.units[0] as ErrorUnitSchema; - const validationErrors = JSON.parse(errorUnit.reason); - expect(validationErrors).to.be.an("array").that.is.not.empty; - expect(validationErrors.some((e: { instancePath?: string }) => e.instancePath)).to.be - .true; - expect(errorUnit.originalUnit).to.deep.equal({ + const validationReason = JSON.parse(errorUnit.reason); + expect(validationReason.error).to.be.an("array").that.is.not.empty; + expect(validationReason.error.some((e: { instancePath?: string }) => e.instancePath)).to + .be.true; + expect(validationReason.json).to.deep.equal({ unit: originalUnit, subworkflow: workflowConfig.subworkflows[0], }); From d7622c59466387272bca134d3b579396fc7cd84c Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 15 Jun 2026 16:22:20 +0300 Subject: [PATCH 10/12] chore: do not store json schema in error unit --- dist/js/units/BaseUnit.js | 1 - src/js/units/BaseUnit.ts | 3 +-- tests/js/Workflow.test.ts | 25 +++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/dist/js/units/BaseUnit.js b/dist/js/units/BaseUnit.js index bdd57155..5f927f54 100644 --- a/dist/js/units/BaseUnit.js +++ b/dist/js/units/BaseUnit.js @@ -66,7 +66,6 @@ class BaseUnit extends entity_1.InMemoryEntity { reasonPayload = { error: error.details.error, json: unitData, - schema: error.details.schema, }; } else if (error instanceof Error) { diff --git a/src/js/units/BaseUnit.ts b/src/js/units/BaseUnit.ts index 3f704279..aa7042e7 100644 --- a/src/js/units/BaseUnit.ts +++ b/src/js/units/BaseUnit.ts @@ -114,13 +114,12 @@ class BaseUnit extends (InMemoryEntity as Base) imple } static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema { - let reasonPayload: { error: unknown; json: object; schema?: unknown }; + let reasonPayload: { error: unknown; json: object }; if (error instanceof EntityError && error.details) { reasonPayload = { error: error.details.error, json: unitData as object, - schema: error.details.schema, }; } else if (error instanceof Error) { reasonPayload = { diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 219745c9..119a9694 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -1,3 +1,4 @@ +import { EntityError, ValidationErrorCode } from "@mat3ra/code/dist/js/entity/in_memory"; import { type InMemoryEntityInSet, inMemoryEntityInSetMixin, @@ -22,6 +23,7 @@ import type { WorkflowRenderContext } from "src/js/Workflow"; import { Subworkflow, UnitFactory, Workflow } from "../../src/js"; import { UnitType } from "../../src/js/enums"; +import BaseUnit from "../../src/js/units/BaseUnit"; import type { WorkflowSchema } from "../../src/js/workflows/types"; import workflowHashes from "../fixtures/workflow_hashes.json"; @@ -497,6 +499,29 @@ describe("Workflow", () => { expect(() => new Workflow(result)).to.not.throw(); }); + it("does not store JSON schema in error unit reason", () => { + const unitData = { name: "exec", flowchartId: "fc-1" }; + const schema = { + type: "object", + properties: { name: { type: "string" } }, + } as JSONSchema7; + const entityError = new EntityError({ + code: ValidationErrorCode.IN_MEMORY_ENTITY_DATA_INVALID, + details: { + error: [{ instancePath: "/name", message: "required" }], + json: unitData, + schema, + }, + }); + + const errorUnit = BaseUnit.toErrorUnitSchema(unitData, entityError); + const reason = JSON.parse(errorUnit.reason); + + expect(reason).to.have.property("error"); + expect(reason).to.have.property("json").that.deep.equals(unitData); + expect(reason).to.not.have.property("schema"); + }); + it("converts invalid subworkflow unit to error and drops subworkflow", () => { const workflowConfig = structuredClone(Workflow.defaultConfig); const originalUnit = workflowConfig.units[0]; From b66dc98648104b4bb55564e898457c0fcbc4966b Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 15 Jun 2026 23:33:37 +0300 Subject: [PATCH 11/12] chore: move repair logic to utils --- dist/js/Subworkflow.d.ts | 1 - dist/js/Subworkflow.js | 12 --- dist/js/Workflow.d.ts | 2 - dist/js/Workflow.js | 66 ------------ dist/js/index.d.ts | 1 + dist/js/index.js | 4 +- dist/js/units/BaseUnit.d.ts | 7 +- dist/js/units/BaseUnit.js | 44 -------- dist/js/units/ConditionUnit.d.ts | 3 +- dist/js/units/ConditionUnit.js | 3 - dist/js/units/ExecutionUnit.d.ts | 3 +- dist/js/units/ExecutionUnit.js | 3 - dist/js/utils/index.d.ts | 1 + dist/js/utils/index.js | 3 +- dist/js/utils/repair.d.ts | 2 + dist/js/utils/repair.js | 140 +++++++++++++++++++++++++ src/js/Subworkflow.ts | 24 +---- src/js/Workflow.ts | 88 +--------------- src/js/index.ts | 1 + src/js/units/BaseUnit.ts | 59 +---------- src/js/units/ConditionUnit.ts | 6 +- src/js/units/ExecutionUnit.ts | 10 +- src/js/utils/index.ts | 1 + src/js/utils/repair.ts | 171 +++++++++++++++++++++++++++++++ tests/js/Workflow.test.ts | 42 +++----- 25 files changed, 348 insertions(+), 349 deletions(-) create mode 100644 dist/js/utils/repair.d.ts create mode 100644 dist/js/utils/repair.js create mode 100644 src/js/utils/repair.ts diff --git a/dist/js/Subworkflow.d.ts b/dist/js/Subworkflow.d.ts index 9b5b22dd..3c145062 100644 --- a/dist/js/Subworkflow.d.ts +++ b/dist/js/Subworkflow.d.ts @@ -40,7 +40,6 @@ declare class Subworkflow extends InMemoryEntity implements SubworkflowSchema { toJSON: () => SubworkflowSchema & AnyObject; _json: SubworkflowSchema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; - static repair(subworkflowData: SubworkflowSchema): SubworkflowSchema; constructor(config: SubworkflowSchema, _ModelFactory?: typeof ModelFactory); static get defaultConfig(): { _id: any; diff --git a/dist/js/Subworkflow.js b/dist/js/Subworkflow.js index e3127115..6d2f7d39 100644 --- a/dist/js/Subworkflow.js +++ b/dist/js/Subworkflow.js @@ -21,18 +21,6 @@ class Subworkflow extends entity_1.InMemoryEntity { static get jsonSchema() { return JSONSchemasInterface_1.default.getSchemaById("workflow/subworkflow"); } - static repair(subworkflowData) { - const units = subworkflowData.units.map((unit) => { - if (unit.type === enums_1.UnitType.execution) { - return units_1.ExecutionUnit.repair(unit); - } - if (unit.type === enums_1.UnitType.condition) { - return units_1.ConditionUnit.repair(unit); - } - return unit; - }); - return { ...subworkflowData, units }; - } constructor(config, _ModelFactory = mode_1.ModelFactory) { super(config); this.properties = []; diff --git a/dist/js/Workflow.d.ts b/dist/js/Workflow.d.ts index 11192b97..e46dd88e 100644 --- a/dist/js/Workflow.d.ts +++ b/dist/js/Workflow.d.ts @@ -28,8 +28,6 @@ declare class Workflow extends InMemoryEntity implements WorkflowSchema { static readonly defaultConfig: WorkflowSchema; _json: WorkflowSchema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; - private static getSubworkflowValidationError; - static repair(workflowData: WorkflowSchema): WorkflowSchema; subworkflowInstances: Subworkflow[]; unitInstances: AnyWorkflowUnit[]; workflowInstances: Workflow[]; diff --git a/dist/js/Workflow.js b/dist/js/Workflow.js index e96ac2f9..70d39f92 100644 --- a/dist/js/Workflow.js +++ b/dist/js/Workflow.js @@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const entity_1 = require("@mat3ra/code/dist/js/entity"); -const in_memory_1 = require("@mat3ra/code/dist/js/entity/in_memory"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); const HasDescriptionMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasDescriptionMixin"); const HashedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"); @@ -25,71 +24,6 @@ class Workflow extends entity_1.InMemoryEntity { static get jsonSchema() { return JSONSchemasInterface_1.default.getSchemaById("workflow"); } - static getSubworkflowValidationError(subworkflow) { - // Two checks, same order as the old isValid() path (construct + validate), but split so we - // keep AJV errors when hydration would fail first: - // 1. validateData — JSON Schema on raw persisted subworkflow (no Application/ModelFactory/units). - // Surfaces structured AJV errors (e.g. missing model) before the constructor runs. - // 2. new Subworkflow().validate() — hydration (app, model, units) then schema on the instance. - // Catches schema-valid JSON that still cannot be built (unknown model, bad units, etc.). - try { - Subworkflow_1.default.validateData({ ...subworkflow }); - new Subworkflow_1.default(subworkflow).validate(); - return null; - } - catch (error) { - if (error instanceof in_memory_1.EntityError || error instanceof Error) { - return error; - } - return new Error(String(error)); - } - } - static repair(workflowData) { - const subworkflows = workflowData.subworkflows.map((subworkflow) => { - return Subworkflow_1.default.repair(subworkflow); - }); - const invalidSubworkflows = subworkflows - .map((subworkflow) => { - const error = Workflow.getSubworkflowValidationError(subworkflow); - return error ? { subworkflow, error } : null; - }) - .filter((entry) => entry !== null); - const units = workflowData.units.map((unit) => { - const invalidEntry = invalidSubworkflows.find(({ subworkflow }) => subworkflow._id === unit._id); - if (invalidEntry) { - const { subworkflow, error } = invalidEntry; - const errorUnit = units_1.BaseUnit.toErrorUnitSchema(unit, error); - const reasonPayload = { - ...JSON.parse(errorUnit.reason), - json: { unit, subworkflow }, - }; - return { - ...errorUnit, - _id: unit._id, - name: unit.name || errorUnit.name, - flowchartId: unit.flowchartId, - reason: JSON.stringify(reasonPayload), - preProcessors: unit.preProcessors || [], - postProcessors: unit.postProcessors || [], - monitors: unit.monitors || [], - results: unit.results || [], - }; - } - return unit; - }); - const validSubworkflows = subworkflows.filter((subworkflow) => { - return !invalidSubworkflows.some(({ subworkflow: invalid }) => invalid._id === subworkflow._id); - }); - const workflows = workflowData.workflows.map((nested) => { - return Workflow.repair(nested); - }); - return { - ...workflowData, - subworkflows: validSubworkflows, - workflows, - units, - }; - } setTotalRepetitions(totalRepetition) { this.totalRepetitions = totalRepetition; } diff --git a/dist/js/index.d.ts b/dist/js/index.d.ts index 331547d5..fc7e06c8 100644 --- a/dist/js/index.d.ts +++ b/dist/js/index.d.ts @@ -10,4 +10,5 @@ import Workflow from "./Workflow"; export type { OrderedMaterial } from "./context/mixins/MaterialContextMixin"; export type { MaterialsSet } from "./context/mixins/MaterialsSetContextMixin"; export type { AnySubworkflowUnit, DefaultSubworkflowUnitType } from "./units/factory"; +export { repairWorkflow } from "./utils/repair"; export { Subworkflow, Workflow, UnitFactory, TAB_NAVIGATION_CONFIG, UNIT_NAME_INVALID_CHARS, WORKFLOW_STATUSES, BaseUnit, ExecutionUnit, AssertionUnit, AssignmentUnit, ConditionUnit, ErrorUnit, IOUnit, MapUnit, ReduceUnit, SubworkflowUnit, defaultMapConfig, PointsPathFormDataProvider, globalSettings, utils, }; diff --git a/dist/js/index.js b/dist/js/index.js index eb344d0e..01f16dfd 100644 --- a/dist/js/index.js +++ b/dist/js/index.js @@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.utils = exports.globalSettings = exports.PointsPathFormDataProvider = exports.defaultMapConfig = exports.SubworkflowUnit = exports.ReduceUnit = exports.MapUnit = exports.IOUnit = exports.ErrorUnit = exports.ConditionUnit = exports.AssignmentUnit = exports.AssertionUnit = exports.ExecutionUnit = exports.BaseUnit = exports.WORKFLOW_STATUSES = exports.UNIT_NAME_INVALID_CHARS = exports.TAB_NAVIGATION_CONFIG = exports.UnitFactory = exports.Workflow = exports.Subworkflow = void 0; +exports.utils = exports.globalSettings = exports.PointsPathFormDataProvider = exports.defaultMapConfig = exports.SubworkflowUnit = exports.ReduceUnit = exports.MapUnit = exports.IOUnit = exports.ErrorUnit = exports.ConditionUnit = exports.AssignmentUnit = exports.AssertionUnit = exports.ExecutionUnit = exports.BaseUnit = exports.WORKFLOW_STATUSES = exports.UNIT_NAME_INVALID_CHARS = exports.TAB_NAVIGATION_CONFIG = exports.UnitFactory = exports.Workflow = exports.Subworkflow = exports.repairWorkflow = void 0; const PointsPathFormDataProvider_1 = __importDefault(require("./context/providers/PointsPath/PointsPathFormDataProvider")); exports.PointsPathFormDataProvider = PointsPathFormDataProvider_1.default; const settings_1 = require("./context/providers/settings"); @@ -66,3 +66,5 @@ const utils = __importStar(require("./utils")); exports.utils = utils; const Workflow_1 = __importDefault(require("./Workflow")); exports.Workflow = Workflow_1.default; +var repair_1 = require("./utils/repair"); +Object.defineProperty(exports, "repairWorkflow", { enumerable: true, get: function () { return repair_1.repairWorkflow; } }); diff --git a/dist/js/units/BaseUnit.d.ts b/dist/js/units/BaseUnit.d.ts index b9349fa9..a6a89011 100644 --- a/dist/js/units/BaseUnit.d.ts +++ b/dist/js/units/BaseUnit.d.ts @@ -7,14 +7,11 @@ import { Taggable } from "@mat3ra/code/dist/js/entity/mixins/TaggableMixin"; import type { NameResultSchema } from "@mat3ra/code/dist/js/utils/object"; import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ErrorUnitSchema, StatusSchema, WorkflowBaseUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { StatusSchema, WorkflowBaseUnitSchema } from "@mat3ra/esse/dist/js/types"; import { type BaseUnitSchemaMixin } from "../generated/BaseUnitSchemaMixin"; import { type StatusSchemaMixin } from "../generated/StatusSchemaMixin"; import { type RuntimeItemsUILogic } from "./mixins/RuntimeItemsUILogicMixin"; type Schema = WorkflowBaseUnitSchema; -type RepairableUnitConstructor> = new (config: C) => { - toJSON(): US; -}; type Base = typeof InMemoryEntity & Constructor & Constructor & Constructor & Constructor & Constructor & Constructor & Constructor & Constructor; declare const BaseUnit_base: Base; declare class BaseUnit extends BaseUnit_base implements Schema { @@ -38,7 +35,5 @@ declare class BaseUnit extends BaseUnit_base implemen isInStatus(status: StatusSchema["status"]): boolean; clone(extraContext: object): this; setRepetition(repetition: number): void; - static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema; - static repairUnit>(UnitClass: RepairableUnitConstructor, unitData: C): US | ErrorUnitSchema; } export default BaseUnit; diff --git a/dist/js/units/BaseUnit.js b/dist/js/units/BaseUnit.js index 5f927f54..773f6524 100644 --- a/dist/js/units/BaseUnit.js +++ b/dist/js/units/BaseUnit.js @@ -1,7 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const entity_1 = require("@mat3ra/code/dist/js/entity"); -const in_memory_1 = require("@mat3ra/code/dist/js/entity/in_memory"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); const HashedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"); const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"); @@ -59,49 +58,6 @@ class BaseUnit extends entity_1.InMemoryEntity { setRepetition(repetition) { this.repetition = repetition; } - static toErrorUnitSchema(unitData, error) { - var _a, _b, _c, _d; - let reasonPayload; - if (error instanceof in_memory_1.EntityError && error.details) { - reasonPayload = { - error: error.details.error, - json: unitData, - }; - } - else if (error instanceof Error) { - reasonPayload = { - error: { message: error.message, name: error.name }, - json: unitData, - }; - } - else { - reasonPayload = { - error, - json: unitData, - }; - } - return { - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, - type: enums_1.UnitType.error, - status: enums_1.UnitStatus.error, - flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), - reason: JSON.stringify(reasonPayload), - next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", - head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, - }; - } - static repairUnit(UnitClass, unitData) { - try { - return new UnitClass(unitData).toJSON(); - } - catch (error) { - return BaseUnit.toErrorUnitSchema(unitData, error); - } - } } (0, TaggableMixin_1.taggableMixin)(BaseUnit.prototype); (0, HashedEntityMixin_1.hashedEntityMixin)(BaseUnit.prototype); diff --git a/dist/js/units/ConditionUnit.d.ts b/dist/js/units/ConditionUnit.d.ts index 6e5e601e..79f1b077 100644 --- a/dist/js/units/ConditionUnit.d.ts +++ b/dist/js/units/ConditionUnit.d.ts @@ -1,6 +1,6 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ConditionUnitSchema, ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ConditionUnitSchema } from "@mat3ra/esse/dist/js/types"; import { type ConditionUnitSchemaMixin } from "../generated/ConditionUnitSchemaMixin"; import BaseUnit from "./BaseUnit"; type Schema = ConditionUnitSchema; @@ -13,6 +13,5 @@ declare class ConditionUnit extends ConditionUnit_base implements Schema { static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; constructor(config: ConditionUnitConfig); getHashObject(): object; - static repair(unitData: Partial): ConditionUnitSchema | ErrorUnitSchema; } export default ConditionUnit; diff --git a/dist/js/units/ConditionUnit.js b/dist/js/units/ConditionUnit.js index 627c34a9..bb752ce3 100644 --- a/dist/js/units/ConditionUnit.js +++ b/dist/js/units/ConditionUnit.js @@ -32,9 +32,6 @@ class ConditionUnit extends BaseUnit_1.default { getHashObject() { return { statement: this.statement, maxOccurrences: this.maxOccurrences }; } - static repair(unitData) { - return BaseUnit_1.default.repairUnit(ConditionUnit, unitData); - } } (0, ConditionUnitSchemaMixin_1.conditionUnitSchemaMixin)(ConditionUnit.prototype); exports.default = ConditionUnit; diff --git a/dist/js/units/ExecutionUnit.d.ts b/dist/js/units/ExecutionUnit.d.ts index fb28cb01..985a5542 100644 --- a/dist/js/units/ExecutionUnit.d.ts +++ b/dist/js/units/ExecutionUnit.d.ts @@ -1,6 +1,6 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ErrorUnitSchema, ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; import { type AnyContextProvider, type ExternalContext } from "../context/providers"; import type ConvergenceParameter from "../convergence/ConvergenceParameter"; import { type ExecutionUnitSchemaMixin } from "../generated/ExecutionUnitSchemaMixin"; @@ -23,7 +23,6 @@ declare class ExecutionUnit extends ExecutionUnit_base implements Schema { _json: Schema & AnyObject; static get jsonSchema(): import("json-schema").JSONSchema7 | undefined; constructor(config: ExecutionUnitConfig); - static repair(unitData: Partial): ExecutionUnitSchema | ErrorUnitSchema; setApplication({ application, executable, flavor, executableName, flavorName, }: SetApplicationProps): void; setExecutable({ executableName, flavorName }: SetExecutableProps): void; setFlavor(flavorName?: string): void; diff --git a/dist/js/units/ExecutionUnit.js b/dist/js/units/ExecutionUnit.js index c1891e7d..4cabca63 100644 --- a/dist/js/units/ExecutionUnit.js +++ b/dist/js/units/ExecutionUnit.js @@ -34,9 +34,6 @@ class ExecutionUnit extends BaseUnit_1.default { this.setApplication(config); this.name = this.name || this.flavor.name || ""; } - static repair(unitData) { - return BaseUnit_1.default.repairUnit(ExecutionUnit, unitData); - } setApplication({ application, executable, flavor, executableName, flavorName, }) { var _a, _b; const currentExecutable = this.prop("executable"); diff --git a/dist/js/utils/index.d.ts b/dist/js/utils/index.d.ts index 78b2db57..085fe872 100644 --- a/dist/js/utils/index.d.ts +++ b/dist/js/utils/index.d.ts @@ -1,3 +1,4 @@ export * as units from "./units"; export * as workflow from "./workflow"; export * as baseUnits from "./baseUnits"; +export * as repair from "./repair"; diff --git a/dist/js/utils/index.js b/dist/js/utils/index.js index ec81de5d..c3494781 100644 --- a/dist/js/utils/index.js +++ b/dist/js/utils/index.js @@ -33,7 +33,8 @@ var __importStar = (this && this.__importStar) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -exports.baseUnits = exports.workflow = exports.units = void 0; +exports.repair = exports.baseUnits = exports.workflow = exports.units = void 0; exports.units = __importStar(require("./units")); exports.workflow = __importStar(require("./workflow")); exports.baseUnits = __importStar(require("./baseUnits")); +exports.repair = __importStar(require("./repair")); diff --git a/dist/js/utils/repair.d.ts b/dist/js/utils/repair.d.ts new file mode 100644 index 00000000..e9c4864e --- /dev/null +++ b/dist/js/utils/repair.d.ts @@ -0,0 +1,2 @@ +import type { WorkflowSchema } from "../workflows/types"; +export declare function repairWorkflow(workflowData: T): T; diff --git a/dist/js/utils/repair.js b/dist/js/utils/repair.js new file mode 100644 index 00000000..07efc5ae --- /dev/null +++ b/dist/js/utils/repair.js @@ -0,0 +1,140 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.repairWorkflow = repairWorkflow; +const in_memory_1 = require("@mat3ra/code/dist/js/entity/in_memory"); +const utils_1 = require("@mat3ra/utils"); +const enums_1 = require("../enums"); +const Subworkflow_1 = __importDefault(require("../Subworkflow")); +const ConditionUnit_1 = __importDefault(require("../units/ConditionUnit")); +const ExecutionUnit_1 = __importDefault(require("../units/ExecutionUnit")); +function toErrorUnitSchema(unitData, error) { + var _a, _b, _c, _d; + let reasonPayload; + if (error instanceof in_memory_1.EntityError && error.details) { + reasonPayload = { + error: error.details.error, + json: unitData, + }; + } + else if (error instanceof Error) { + reasonPayload = { + error: { message: error.message, name: error.name }, + json: unitData, + }; + } + else { + reasonPayload = { + error, + json: unitData, + }; + } + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: (_a = unitData.name) !== null && _a !== void 0 ? _a : enums_1.UnitType.error, + type: enums_1.UnitType.error, + status: enums_1.UnitStatus.error, + flowchartId: (_b = unitData.flowchartId) !== null && _b !== void 0 ? _b : utils_1.Utils.uuid.getUUID(), + reason: JSON.stringify(reasonPayload), + next: (_c = unitData.next) !== null && _c !== void 0 ? _c : "", + head: (_d = unitData.head) !== null && _d !== void 0 ? _d : false, + }; +} +function repairExecutionUnit(unitData) { + try { + return new ExecutionUnit_1.default(unitData).toJSON(); + } + catch (error) { + return toErrorUnitSchema(unitData, error); + } +} +function repairConditionUnit(unitData) { + try { + return new ConditionUnit_1.default(unitData).toJSON(); + } + catch (error) { + return toErrorUnitSchema(unitData, error); + } +} +function getSubworkflowValidationError(subworkflow) { + // Two checks, same order as the old isValid() path (construct + validate), but split so we + // keep AJV errors when hydration would fail first: + // 1. validateData — JSON Schema on raw persisted subworkflow (no Application/ModelFactory/units). + // Surfaces structured AJV errors (e.g. missing model) before the constructor runs. + // 2. new Subworkflow().validate() — hydration (app, model, units) then schema on the instance. + // Catches schema-valid JSON that still cannot be built (unknown model, bad units, etc.). + try { + Subworkflow_1.default.validateData({ ...subworkflow }); + new Subworkflow_1.default(subworkflow).validate(); + return null; + } + catch (error) { + if (error instanceof in_memory_1.EntityError || error instanceof Error) { + return error; + } + return new Error(String(error)); + } +} +function repairSubworkflow(subworkflowData) { + const units = subworkflowData.units.map((unit) => { + if (unit.type === enums_1.UnitType.execution) { + return repairExecutionUnit(unit); + } + if (unit.type === enums_1.UnitType.condition) { + return repairConditionUnit(unit); + } + return unit; + }); + return { ...subworkflowData, units }; +} +function repairWorkflow(workflowData) { + const subworkflows = workflowData.subworkflows.map((subworkflow) => { + return repairSubworkflow(subworkflow); + }); + const invalidSubworkflows = subworkflows + .map((subworkflow) => { + const error = getSubworkflowValidationError(subworkflow); + return error ? { subworkflow, error } : null; + }) + .filter((entry) => entry !== null); + const units = workflowData.units.map((unit) => { + const invalidEntry = invalidSubworkflows.find(({ subworkflow }) => subworkflow._id === unit._id); + if (invalidEntry) { + const { subworkflow, error } = invalidEntry; + const errorUnit = toErrorUnitSchema(unit, error); + const reasonPayload = { + ...JSON.parse(errorUnit.reason), + json: { unit, subworkflow }, + }; + return { + ...errorUnit, + _id: unit._id, + name: unit.name || errorUnit.name, + flowchartId: unit.flowchartId, + reason: JSON.stringify(reasonPayload), + preProcessors: unit.preProcessors || [], + postProcessors: unit.postProcessors || [], + monitors: unit.monitors || [], + results: unit.results || [], + }; + } + return unit; + }); + const validSubworkflows = subworkflows.filter((subworkflow) => { + return !invalidSubworkflows.some(({ subworkflow: invalid }) => invalid._id === subworkflow._id); + }); + const workflows = workflowData.workflows.map((nested) => { + return repairWorkflow(nested); + }); + return { + ...workflowData, + subworkflows: validSubworkflows, + workflows, + units, + }; +} diff --git a/src/js/Subworkflow.ts b/src/js/Subworkflow.ts index 55ab62b7..e6d25b4a 100644 --- a/src/js/Subworkflow.ts +++ b/src/js/Subworkflow.ts @@ -34,13 +34,7 @@ import { type SubworkflowSchemaMixin, subworkflowSchemaMixin, } from "./generated/SubworkflowSchemaMixin"; -import { - AssignmentUnit, - ConditionUnit, - ExecutionUnit, - SubworkflowUnit, - UnitFactory, -} from "./units"; +import { AssignmentUnit, ConditionUnit, SubworkflowUnit, UnitFactory } from "./units"; import type { AnySubworkflowUnit } from "./units/factory"; type ConvergenceConfig = { @@ -92,22 +86,6 @@ class Subworkflow extends InMemoryEntity implements SubworkflowSchema { return JSONSchemasInterface.getSchemaById("workflow/subworkflow"); } - static repair(subworkflowData: SubworkflowSchema): SubworkflowSchema { - const units = subworkflowData.units.map((unit) => { - if (unit.type === UnitType.execution) { - return ExecutionUnit.repair(unit); - } - - if (unit.type === UnitType.condition) { - return ConditionUnit.repair(unit); - } - - return unit; - }); - - return { ...subworkflowData, units }; - } - constructor(config: SubworkflowSchema, _ModelFactory = ModelFactory) { super(config); this.ModelFactory = _ModelFactory; diff --git a/src/js/Workflow.ts b/src/js/Workflow.ts index 97fbe39a..bdeeb10c 100644 --- a/src/js/Workflow.ts +++ b/src/js/Workflow.ts @@ -1,5 +1,4 @@ import { type NamedInMemoryEntity, InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { EntityError } from "@mat3ra/code/dist/js/entity/in_memory"; import { type Defaultable, defaultableEntityMixin, @@ -30,8 +29,8 @@ import type { JobExternalContext } from "./context/providers/by_application/espr import { UnitType } from "./enums"; import { type WorkflowSchemaMixin, workflowSchemaMixin } from "./generated/WorkflowSchemaMixin"; import Subworkflow from "./Subworkflow"; -import { BaseUnit, MapUnit } from "./units"; -import { type AnyWorkflowUnit, type AnyWorkflowUnitSchema, UnitFactory } from "./units/factory"; +import { MapUnit } from "./units"; +import { type AnyWorkflowUnit, UnitFactory } from "./units/factory"; import { getDefaultDescription, getHumanReadableProperties, @@ -73,89 +72,6 @@ class Workflow extends InMemoryEntity implements WorkflowSchema { return JSONSchemasInterface.getSchemaById("workflow"); } - private static getSubworkflowValidationError( - subworkflow: SubworkflowSchema, - ): EntityError | Error | null { - // Two checks, same order as the old isValid() path (construct + validate), but split so we - // keep AJV errors when hydration would fail first: - // 1. validateData — JSON Schema on raw persisted subworkflow (no Application/ModelFactory/units). - // Surfaces structured AJV errors (e.g. missing model) before the constructor runs. - // 2. new Subworkflow().validate() — hydration (app, model, units) then schema on the instance. - // Catches schema-valid JSON that still cannot be built (unknown model, bad units, etc.). - try { - Subworkflow.validateData({ ...subworkflow }); - new Subworkflow(subworkflow).validate(); - return null; - } catch (error: unknown) { - if (error instanceof EntityError || error instanceof Error) { - return error; - } - return new Error(String(error)); - } - } - - static repair(workflowData: WorkflowSchema): WorkflowSchema { - const subworkflows = workflowData.subworkflows.map((subworkflow) => { - return Subworkflow.repair(subworkflow); - }); - - const invalidSubworkflows = subworkflows - .map((subworkflow) => { - const error = Workflow.getSubworkflowValidationError(subworkflow); - return error ? { subworkflow, error } : null; - }) - .filter( - (entry): entry is { subworkflow: SubworkflowSchema; error: EntityError | Error } => - entry !== null, - ); - - const units = workflowData.units.map((unit): AnyWorkflowUnitSchema => { - const invalidEntry = invalidSubworkflows.find( - ({ subworkflow }) => subworkflow._id === unit._id, - ); - - if (invalidEntry) { - const { subworkflow, error } = invalidEntry; - const errorUnit = BaseUnit.toErrorUnitSchema(unit, error); - const reasonPayload = { - ...JSON.parse(errorUnit.reason), - json: { unit, subworkflow }, - }; - - return { - ...errorUnit, - _id: unit._id, - name: unit.name || errorUnit.name, - flowchartId: unit.flowchartId, - reason: JSON.stringify(reasonPayload), - preProcessors: unit.preProcessors || [], - postProcessors: unit.postProcessors || [], - monitors: unit.monitors || [], - results: unit.results || [], - }; - } - - return unit; - }); - - const validSubworkflows = subworkflows.filter((subworkflow) => { - return !invalidSubworkflows.some( - ({ subworkflow: invalid }) => invalid._id === subworkflow._id, - ); - }); - - const workflows = workflowData.workflows.map((nested) => { - return Workflow.repair(nested as WorkflowSchema); - }); - - return { - ...workflowData, - subworkflows: validSubworkflows, - workflows, - units, - }; - } - subworkflowInstances: Subworkflow[]; unitInstances!: AnyWorkflowUnit[]; diff --git a/src/js/index.ts b/src/js/index.ts index 039fb705..6af70f36 100644 --- a/src/js/index.ts +++ b/src/js/index.ts @@ -22,6 +22,7 @@ import Workflow from "./Workflow"; export type { OrderedMaterial } from "./context/mixins/MaterialContextMixin"; export type { MaterialsSet } from "./context/mixins/MaterialsSetContextMixin"; export type { AnySubworkflowUnit, DefaultSubworkflowUnitType } from "./units/factory"; +export { repairWorkflow } from "./utils/repair"; export { Subworkflow, Workflow, diff --git a/src/js/units/BaseUnit.ts b/src/js/units/BaseUnit.ts index aa7042e7..fd5a24a3 100644 --- a/src/js/units/BaseUnit.ts +++ b/src/js/units/BaseUnit.ts @@ -1,5 +1,4 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { EntityError } from "@mat3ra/code/dist/js/entity/in_memory"; import { type Defaultable, defaultableEntityMixin, @@ -20,14 +19,10 @@ import { Taggable, taggableMixin } from "@mat3ra/code/dist/js/entity/mixins/Tagg import type { NameResultSchema } from "@mat3ra/code/dist/js/utils/object"; import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { - ErrorUnitSchema, - StatusSchema, - WorkflowBaseUnitSchema, -} from "@mat3ra/esse/dist/js/types"; +import type { StatusSchema, WorkflowBaseUnitSchema } from "@mat3ra/esse/dist/js/types"; import { Utils } from "@mat3ra/utils"; -import { UnitStatus, UnitType } from "../enums"; +import { UnitStatus } from "../enums"; import { type BaseUnitSchemaMixin, baseUnitSchemaMixin } from "../generated/BaseUnitSchemaMixin"; import { type StatusSchemaMixin, statusSchemaMixin } from "../generated/StatusSchemaMixin"; import { @@ -37,10 +32,6 @@ import { type Schema = WorkflowBaseUnitSchema; -type RepairableUnitConstructor> = new (config: C) => { - toJSON(): US; -}; - type Base = typeof InMemoryEntity & Constructor & Constructor & @@ -112,52 +103,6 @@ class BaseUnit extends (InMemoryEntity as Base) imple setRepetition(repetition: number) { this.repetition = repetition; } - - static toErrorUnitSchema(unitData: Partial, error: unknown): ErrorUnitSchema { - let reasonPayload: { error: unknown; json: object }; - - if (error instanceof EntityError && error.details) { - reasonPayload = { - error: error.details.error, - json: unitData as object, - }; - } else if (error instanceof Error) { - reasonPayload = { - error: { message: error.message, name: error.name }, - json: unitData as object, - }; - } else { - reasonPayload = { - error, - json: unitData as object, - }; - } - - return { - results: [], - preProcessors: [], - postProcessors: [], - monitors: [], - name: unitData.name ?? UnitType.error, - type: UnitType.error, - status: UnitStatus.error, - flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), - reason: JSON.stringify(reasonPayload), - next: unitData.next ?? "", - head: unitData.head ?? false, - }; - } - - static repairUnit>( - UnitClass: RepairableUnitConstructor, - unitData: C, - ): US | ErrorUnitSchema { - try { - return new UnitClass(unitData).toJSON(); - } catch (error: unknown) { - return BaseUnit.toErrorUnitSchema(unitData as Partial, error); - } - } } taggableMixin(BaseUnit.prototype); diff --git a/src/js/units/ConditionUnit.ts b/src/js/units/ConditionUnit.ts index 42b4c924..64af2b17 100644 --- a/src/js/units/ConditionUnit.ts +++ b/src/js/units/ConditionUnit.ts @@ -1,7 +1,7 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { ConditionUnitSchema, ErrorUnitSchema } from "@mat3ra/esse/dist/js/types"; +import type { ConditionUnitSchema } from "@mat3ra/esse/dist/js/types"; import { UnitType } from "../enums"; import { @@ -45,10 +45,6 @@ class ConditionUnit extends (BaseUnit as Base) implements Schema { getHashObject(): object { return { statement: this.statement, maxOccurrences: this.maxOccurrences }; } - - static repair(unitData: Partial): ConditionUnitSchema | ErrorUnitSchema { - return BaseUnit.repairUnit(ConditionUnit, unitData); - } } conditionUnitSchemaMixin(ConditionUnit.prototype); diff --git a/src/js/units/ExecutionUnit.ts b/src/js/units/ExecutionUnit.ts index 69bb8bd1..009d6786 100644 --- a/src/js/units/ExecutionUnit.ts +++ b/src/js/units/ExecutionUnit.ts @@ -1,11 +1,7 @@ import type { Constructor } from "@mat3ra/code/dist/js/utils/types"; import JSONSchemasInterface from "@mat3ra/esse/dist/js/esse/JSONSchemasInterface"; import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { - ErrorUnitSchema, - ExecutionUnitInputItemSchema, - ExecutionUnitSchema, -} from "@mat3ra/esse/dist/js/types"; +import type { ExecutionUnitInputItemSchema, ExecutionUnitSchema } from "@mat3ra/esse/dist/js/types"; import { ApplicationRegistry, applicationVersionSatisfiesSupportedRange } from "@mat3ra/standata"; import { Utils } from "@mat3ra/utils"; @@ -72,10 +68,6 @@ class ExecutionUnit extends (BaseUnit as Base) implements Schema { this.name = this.name || this.flavor.name || ""; } - static repair(unitData: Partial): ExecutionUnitSchema | ErrorUnitSchema { - return BaseUnit.repairUnit(ExecutionUnit, unitData as ExecutionUnitConfig); - } - setApplication({ application, executable, diff --git a/src/js/utils/index.ts b/src/js/utils/index.ts index 78b2db57..085fe872 100644 --- a/src/js/utils/index.ts +++ b/src/js/utils/index.ts @@ -1,3 +1,4 @@ export * as units from "./units"; export * as workflow from "./workflow"; export * as baseUnits from "./baseUnits"; +export * as repair from "./repair"; diff --git a/src/js/utils/repair.ts b/src/js/utils/repair.ts new file mode 100644 index 00000000..47f3355a --- /dev/null +++ b/src/js/utils/repair.ts @@ -0,0 +1,171 @@ +import { EntityError } from "@mat3ra/code/dist/js/entity/in_memory"; +import type { + ConditionUnitSchema, + ErrorUnitSchema, + ExecutionUnitSchema, + SubworkflowSchema, + WorkflowBaseUnitSchema, +} from "@mat3ra/esse/dist/js/types"; +import { Utils } from "@mat3ra/utils"; + +import { UnitStatus, UnitType } from "../enums"; +import Subworkflow from "../Subworkflow"; +import ConditionUnit from "../units/ConditionUnit"; +import ExecutionUnit from "../units/ExecutionUnit"; +import type { AnyWorkflowUnitSchema } from "../units/factory"; +import type { WorkflowSchema } from "../workflows/types"; + +function toErrorUnitSchema( + unitData: Partial, + error: unknown, +): ErrorUnitSchema { + let reasonPayload: { error: unknown; json: object }; + + if (error instanceof EntityError && error.details) { + reasonPayload = { + error: error.details.error, + json: unitData as object, + }; + } else if (error instanceof Error) { + reasonPayload = { + error: { message: error.message, name: error.name }, + json: unitData as object, + }; + } else { + reasonPayload = { + error, + json: unitData as object, + }; + } + + return { + results: [], + preProcessors: [], + postProcessors: [], + monitors: [], + name: unitData.name ?? UnitType.error, + type: UnitType.error, + status: UnitStatus.error, + flowchartId: unitData.flowchartId ?? Utils.uuid.getUUID(), + reason: JSON.stringify(reasonPayload), + next: unitData.next ?? "", + head: unitData.head ?? false, + }; +} + +function repairExecutionUnit( + unitData: Partial, +): ExecutionUnitSchema | ErrorUnitSchema { + try { + return new ExecutionUnit(unitData as ExecutionUnitSchema).toJSON(); + } catch (error: unknown) { + return toErrorUnitSchema(unitData as Partial, error); + } +} + +function repairConditionUnit( + unitData: Partial, +): ConditionUnitSchema | ErrorUnitSchema { + try { + return new ConditionUnit(unitData as ConditionUnitSchema).toJSON(); + } catch (error: unknown) { + return toErrorUnitSchema(unitData as Partial, error); + } +} + +function getSubworkflowValidationError(subworkflow: SubworkflowSchema): EntityError | Error | null { + // Two checks, same order as the old isValid() path (construct + validate), but split so we + // keep AJV errors when hydration would fail first: + // 1. validateData — JSON Schema on raw persisted subworkflow (no Application/ModelFactory/units). + // Surfaces structured AJV errors (e.g. missing model) before the constructor runs. + // 2. new Subworkflow().validate() — hydration (app, model, units) then schema on the instance. + // Catches schema-valid JSON that still cannot be built (unknown model, bad units, etc.). + try { + Subworkflow.validateData({ ...subworkflow }); + new Subworkflow(subworkflow).validate(); + return null; + } catch (error: unknown) { + if (error instanceof EntityError || error instanceof Error) { + return error; + } + return new Error(String(error)); + } +} + +function repairSubworkflow(subworkflowData: SubworkflowSchema): SubworkflowSchema { + const units = subworkflowData.units.map((unit) => { + if (unit.type === UnitType.execution) { + return repairExecutionUnit(unit); + } + + if (unit.type === UnitType.condition) { + return repairConditionUnit(unit); + } + + return unit; + }); + + return { ...subworkflowData, units }; +} + +export function repairWorkflow(workflowData: T): T { + const subworkflows = workflowData.subworkflows.map((subworkflow) => { + return repairSubworkflow(subworkflow); + }); + + const invalidSubworkflows = subworkflows + .map((subworkflow) => { + const error = getSubworkflowValidationError(subworkflow); + return error ? { subworkflow, error } : null; + }) + .filter( + (entry): entry is { subworkflow: SubworkflowSchema; error: EntityError | Error } => + entry !== null, + ); + + const units = workflowData.units.map((unit): AnyWorkflowUnitSchema => { + const invalidEntry = invalidSubworkflows.find( + ({ subworkflow }) => subworkflow._id === unit._id, + ); + + if (invalidEntry) { + const { subworkflow, error } = invalidEntry; + const errorUnit = toErrorUnitSchema(unit, error); + const reasonPayload = { + ...JSON.parse(errorUnit.reason), + json: { unit, subworkflow }, + }; + + return { + ...errorUnit, + _id: unit._id, + name: unit.name || errorUnit.name, + flowchartId: unit.flowchartId, + reason: JSON.stringify(reasonPayload), + preProcessors: unit.preProcessors || [], + postProcessors: unit.postProcessors || [], + monitors: unit.monitors || [], + results: unit.results || [], + }; + } + + return unit; + }); + + const validSubworkflows = subworkflows.filter((subworkflow) => { + return !invalidSubworkflows.some( + ({ subworkflow: invalid }) => invalid._id === subworkflow._id, + ); + }); + + const workflows = workflowData.workflows.map((nested) => { + return repairWorkflow(nested as WorkflowSchema); + }); + + return { + ...workflowData, + subworkflows: validSubworkflows, + workflows, + units, + }; +} diff --git a/tests/js/Workflow.test.ts b/tests/js/Workflow.test.ts index 119a9694..bf10ac47 100644 --- a/tests/js/Workflow.test.ts +++ b/tests/js/Workflow.test.ts @@ -1,4 +1,3 @@ -import { EntityError, ValidationErrorCode } from "@mat3ra/code/dist/js/entity/in_memory"; import { type InMemoryEntityInSet, inMemoryEntityInSetMixin, @@ -23,7 +22,7 @@ import type { WorkflowRenderContext } from "src/js/Workflow"; import { Subworkflow, UnitFactory, Workflow } from "../../src/js"; import { UnitType } from "../../src/js/enums"; -import BaseUnit from "../../src/js/units/BaseUnit"; +import { repairWorkflow } from "../../src/js/utils/repair"; import type { WorkflowSchema } from "../../src/js/workflows/types"; import workflowHashes from "../fixtures/workflow_hashes.json"; @@ -339,7 +338,7 @@ describe("Workflow", () => { const invalid = invalidExecutionUnit("fc-exec"); workflowConfig.subworkflows[0].units = [invalid as never]; - const result = Workflow.repair(workflowConfig); + const result = repairWorkflow(workflowConfig); expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); const subworkflowErrorReason = JSON.parse( @@ -356,12 +355,12 @@ describe("Workflow", () => { ).toJSON(); workflowConfig.subworkflows[0].units = [unit]; - const result = Workflow.repair(workflowConfig); + const result = repairWorkflow(workflowConfig); expect(result.subworkflows[0].units[0]).to.deep.equal(unit); }); - it("repairs legacy condition unit missing then and else via Workflow.repair", () => { + it("repairs legacy condition unit missing then and else via repairWorkflow", () => { const workflowConfig = structuredClone(Workflow.defaultConfig); const legacyCondition = { name: "condition", @@ -381,7 +380,7 @@ describe("Workflow", () => { workflowConfig.subworkflows[0].units = [legacyCondition as never]; - const result = Workflow.repair(workflowConfig); + const result = repairWorkflow(workflowConfig); const condition = result.subworkflows[0].units[0] as ConditionUnitSchema; expect(condition.type).to.equal(UnitType.condition); @@ -396,7 +395,7 @@ describe("Workflow", () => { const invalidExecution = invalidExecutionUnit("fc-bad"); workflowConfig.subworkflows[0].units = [validUnit, invalidExecution as never]; - const result = Workflow.repair(workflowConfig); + const result = repairWorkflow(workflowConfig); expect(result.subworkflows[0].units[0]).to.deep.equal(validUnit); expect(result.subworkflows[0].units[1].type).to.equal(UnitType.error); @@ -421,7 +420,7 @@ describe("Workflow", () => { }, ]; - const result = Workflow.repair(workflowConfig); + const result = repairWorkflow(workflowConfig); expect(result.subworkflows[0].units[0].type).to.equal(UnitType.error); expect(result.workflows[0].subworkflows[0].units[0].type).to.equal(UnitType.error); @@ -431,7 +430,7 @@ describe("Workflow", () => { const workflowConfig = structuredClone(Workflow.defaultConfig); workflowConfig.subworkflows[0].units = [invalidExecutionUnit("fc-hydrate") as never]; - const document = Workflow.repair(workflowConfig); + const document = repairWorkflow(workflowConfig); expect(() => new Workflow(document)).to.not.throw(); }); @@ -490,7 +489,7 @@ describe("Workflow", () => { properties: [], } as unknown as WorkflowSchema; - const result = Workflow.repair(legacyShellWorkflow); + const result = repairWorkflow(legacyShellWorkflow); expect(result.subworkflows).to.have.lengthOf(0); expect(result.units[0].type).to.equal(UnitType.error); @@ -500,25 +499,16 @@ describe("Workflow", () => { }); it("does not store JSON schema in error unit reason", () => { - const unitData = { name: "exec", flowchartId: "fc-1" }; - const schema = { - type: "object", - properties: { name: { type: "string" } }, - } as JSONSchema7; - const entityError = new EntityError({ - code: ValidationErrorCode.IN_MEMORY_ENTITY_DATA_INVALID, - details: { - error: [{ instancePath: "/name", message: "required" }], - json: unitData, - schema, - }, - }); + const workflowConfig = structuredClone(Workflow.defaultConfig); + const invalid = invalidExecutionUnit("fc-1"); + workflowConfig.subworkflows[0].units = [invalid as never]; - const errorUnit = BaseUnit.toErrorUnitSchema(unitData, entityError); + const result = repairWorkflow(workflowConfig); + const errorUnit = result.subworkflows[0].units[0] as ErrorUnitSchema; const reason = JSON.parse(errorUnit.reason); expect(reason).to.have.property("error"); - expect(reason).to.have.property("json").that.deep.equals(unitData); + expect(reason).to.have.property("json"); expect(reason).to.not.have.property("schema"); }); @@ -535,7 +525,7 @@ describe("Workflow", () => { }, }; - const result = Workflow.repair(workflowConfig); + const result = repairWorkflow(workflowConfig); expect(result.subworkflows).to.have.lengthOf(0); expect(result.units).to.have.lengthOf(1); From 1ab2f3b3eb819a1461cc2c127197be45e0a4cf52 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 16 Jun 2026 15:34:12 +0300 Subject: [PATCH 12/12] chore: esse --- package-lock.json | 373 +++++++++++++++++++++++++++++++++------------- package.json | 2 +- 2 files changed, 271 insertions(+), 104 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93d8f2c6..8e289c43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/7b8fd3cdb25d9e5ffa20de930becf408dbc0f759.tar.gz", + "@mat3ra/esse": "2026.6.16-0", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1", @@ -473,7 +473,6 @@ }, "node_modules/@babel/highlight": { "version": "7.25.9", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -487,7 +486,6 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -498,7 +496,6 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", @@ -511,7 +508,6 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", - "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -519,12 +515,10 @@ }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "dev": true, "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -532,7 +526,6 @@ }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -540,7 +533,6 @@ }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -2335,7 +2327,6 @@ }, "node_modules/@eslint/eslintrc": { "version": "0.4.3", - "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -2354,7 +2345,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -2369,7 +2359,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "1.0.10", - "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -2377,7 +2366,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -2385,7 +2373,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "3.14.1", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -2397,12 +2384,10 @@ }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/sprintf-js": { "version": "1.0.3", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@exabyte-io/eslint-config": { @@ -2478,7 +2463,6 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.5.0", - "dev": true, "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", @@ -2491,7 +2475,6 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/load-nyc-config": { @@ -2701,9 +2684,9 @@ } }, "node_modules/@mat3ra/esse": { - "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/esse/archive/7b8fd3cdb25d9e5ffa20de930becf408dbc0f759.tar.gz", - "integrity": "sha512-EhjMRV0DabAl/uJEm93jjdkaUaO1zYdokktvzU3/IAtgAw0cKAbUZ3Obs4SCiLmWOWGthqvhTMk6oLDz4PxFQg==", + "version": "2026.6.16-0", + "resolved": "https://registry.npmjs.org/@mat3ra/esse/-/esse-2026.6.16-0.tgz", + "integrity": "sha512-SZYwIzWX0G2RaX9uC1bH1531qCi2I2MMNdfKINhG7kweDuZ5Z4jnRBvQopstBfK8QjTSRuxeT4R6iiiT3e+ACg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4233,6 +4216,20 @@ "node": ">= 8" } }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "dev": true, @@ -4641,7 +4638,6 @@ }, "node_modules/acorn": { "version": "7.4.1", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4652,7 +4648,6 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -4696,7 +4691,6 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -4739,7 +4733,6 @@ }, "node_modules/ansi-colors": { "version": "4.1.3", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4772,7 +4765,6 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4780,7 +4772,6 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4970,7 +4961,6 @@ }, "node_modules/astral-regex": { "version": "2.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5206,7 +5196,6 @@ }, "node_modules/callsites": { "version": "3.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5259,7 +5248,6 @@ }, "node_modules/chalk": { "version": "4.1.2", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -5465,7 +5453,6 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5476,7 +5463,6 @@ }, "node_modules/color-name": { "version": "1.1.4", - "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -5586,7 +5572,6 @@ }, "node_modules/cross-spawn": { "version": "7.0.6", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5717,7 +5702,6 @@ }, "node_modules/deep-is": { "version": "0.1.4", - "dev": true, "license": "MIT" }, "node_modules/default-require-extensions": { @@ -5781,6 +5765,17 @@ "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -5796,7 +5791,6 @@ }, "node_modules/doctrine": { "version": "3.0.0", - "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" @@ -5836,7 +5830,6 @@ }, "node_modules/enquirer": { "version": "2.4.1", - "dev": true, "license": "MIT", "dependencies": { "ansi-colors": "^4.1.1", @@ -6000,7 +5993,6 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -6011,7 +6003,6 @@ }, "node_modules/eslint": { "version": "7.32.0", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "7.12.11", @@ -6065,6 +6056,37 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-compat-utils": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz", + "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-compat-utils/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-config-airbnb": { "version": "19.0.2", "dev": true, @@ -6156,6 +6178,29 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-json-compat-utils": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/eslint-json-compat-utils/-/eslint-json-compat-utils-0.2.3.tgz", + "integrity": "sha512-RbBmDFyu7FqnjE8F0ZxPNzx5UaptdeS9Uu50r7A+D7s/+FCX+ybiyViYEgFUaFIFqSWJgZRTpL5d8Kanxxl2lQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esquery": "^1.6.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": "*", + "jsonc-eslint-parser": "^2.4.0 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@eslint/json": { + "optional": true + } + } + }, "node_modules/eslint-module-utils": { "version": "2.12.1", "dev": true, @@ -6263,6 +6308,81 @@ "node": ">=10" } }, + "node_modules/eslint-plugin-jsonc": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.21.1.tgz", + "integrity": "sha512-dbNR5iEnQeORwsK2WZzr3QaMtFCY3kKJVMRHPzUpKzMhmVy2zIpVgFDpX8MNoIdoqz6KCpCfOJavhfiSbZbN+w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.1", + "diff-sequences": "^27.5.1", + "eslint-compat-utils": "^0.6.4", + "eslint-json-compat-utils": "^0.2.1", + "espree": "^9.6.1 || ^10.3.0", + "graphemer": "^1.4.0", + "jsonc-eslint-parser": "^2.4.0", + "natural-compare": "^1.4.0", + "synckit": "^0.6.2 || ^0.7.3 || ^0.11.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-jsonc/node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eslint-plugin-jsonc/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsonc/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.5.1", "dev": true, @@ -6349,6 +6469,20 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "dev": true, @@ -6404,7 +6538,6 @@ }, "node_modules/eslint-utils": { "version": "2.1.0", - "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" @@ -6418,7 +6551,6 @@ }, "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=4" @@ -6433,7 +6565,6 @@ }, "node_modules/eslint/node_modules/@babel/code-frame": { "version": "7.12.11", - "dev": true, "license": "MIT", "dependencies": { "@babel/highlight": "^7.10.4" @@ -6441,7 +6572,6 @@ }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -6456,7 +6586,6 @@ }, "node_modules/eslint/node_modules/argparse": { "version": "1.0.10", - "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -6464,7 +6593,6 @@ }, "node_modules/eslint/node_modules/ignore": { "version": "4.0.6", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -6472,7 +6600,6 @@ }, "node_modules/eslint/node_modules/js-yaml": { "version": "3.14.1", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -6484,12 +6611,10 @@ }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, "license": "MIT" }, "node_modules/eslint/node_modules/semver": { "version": "7.7.3", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -6500,12 +6625,10 @@ }, "node_modules/eslint/node_modules/sprintf-js": { "version": "1.0.3", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/espree": { "version": "7.3.1", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^7.4.0", @@ -6518,7 +6641,6 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=4" @@ -6526,7 +6648,6 @@ }, "node_modules/esprima": { "version": "4.0.1", - "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -6538,7 +6659,6 @@ }, "node_modules/esquery": { "version": "1.6.0", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -6595,7 +6715,6 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -6622,17 +6741,14 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "dev": true, "license": "MIT" }, "node_modules/fast-uri": { "version": "3.1.0", - "dev": true, "funding": [ { "type": "github", @@ -6657,7 +6773,6 @@ }, "node_modules/file-entry-cache": { "version": "6.0.1", - "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" @@ -6714,7 +6829,6 @@ }, "node_modules/flat-cache": { "version": "3.2.0", - "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", @@ -6727,7 +6841,6 @@ }, "node_modules/flatted": { "version": "3.3.3", - "dev": true, "license": "ISC" }, "node_modules/for-each": { @@ -6830,7 +6943,6 @@ }, "node_modules/functional-red-black-tree": { "version": "1.0.1", - "dev": true, "license": "MIT" }, "node_modules/functions-have-names": { @@ -6962,7 +7074,6 @@ }, "node_modules/glob-parent": { "version": "5.1.2", - "devOptional": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -6973,7 +7084,6 @@ }, "node_modules/globals": { "version": "13.24.0", - "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.20.2" @@ -7083,7 +7193,6 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7219,7 +7328,6 @@ }, "node_modules/import-fresh": { "version": "3.3.1", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -7234,7 +7342,6 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -7411,7 +7518,6 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7462,7 +7568,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "devOptional": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -7752,7 +7857,6 @@ }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, "license": "ISC" }, "node_modules/isobject": { @@ -7933,7 +8037,6 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "dev": true, "license": "MIT" }, "node_modules/json-schema": { @@ -8028,12 +8131,10 @@ }, "node_modules/json-schema-traverse": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "dev": true, "license": "MIT" }, "node_modules/json5": { @@ -8046,6 +8147,87 @@ "node": ">=6" } }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.2.tgz", + "integrity": "sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "dev": true, @@ -8062,7 +8244,6 @@ }, "node_modules/keyv": { "version": "4.5.4", - "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -8093,7 +8274,6 @@ }, "node_modules/levn": { "version": "0.4.1", - "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -8272,12 +8452,10 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", - "dev": true, "license": "MIT" }, "node_modules/lodash.truncate": { "version": "4.4.2", - "dev": true, "license": "MIT" }, "node_modules/log-symbols": { @@ -8706,7 +8884,6 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "dev": true, "license": "MIT" }, "node_modules/natural-compare-lite": { @@ -9150,7 +9327,6 @@ }, "node_modules/optionator": { "version": "0.9.4", - "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -9245,7 +9421,6 @@ }, "node_modules/parent-module": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -9271,7 +9446,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9417,7 +9591,6 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -9461,7 +9634,6 @@ }, "node_modules/progress": { "version": "2.0.3", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -9479,7 +9651,6 @@ }, "node_modules/punycode": { "version": "2.3.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9591,7 +9762,6 @@ }, "node_modules/regexpp": { "version": "3.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9658,7 +9828,6 @@ }, "node_modules/require-from-string": { "version": "2.0.2", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9697,7 +9866,6 @@ }, "node_modules/resolve-from": { "version": "4.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -9741,7 +9909,6 @@ }, "node_modules/rimraf": { "version": "3.0.2", - "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -9938,7 +10105,6 @@ }, "node_modules/shebang-command": { "version": "2.0.0", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -9949,7 +10115,6 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10278,7 +10443,6 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -10305,7 +10469,6 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10316,7 +10479,6 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -10335,9 +10497,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/table": { "version": "6.9.0", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "ajv": "^8.0.1", @@ -10352,12 +10530,10 @@ }, "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, "license": "MIT" }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10365,7 +10541,6 @@ }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -10381,7 +10556,6 @@ }, "node_modules/table/node_modules/string-width": { "version": "4.2.3", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -10407,7 +10581,6 @@ }, "node_modules/text-table": { "version": "0.2.0", - "dev": true, "license": "MIT" }, "node_modules/through": { @@ -10618,7 +10791,6 @@ }, "node_modules/type-check": { "version": "0.4.0", - "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -10637,7 +10809,6 @@ }, "node_modules/type-fest": { "version": "0.20.2", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -10868,7 +11039,6 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -10888,7 +11058,6 @@ }, "node_modules/v8-compile-cache": { "version": "2.4.0", - "dev": true, "license": "MIT" }, "node_modules/v8-compile-cache-lib": { @@ -10942,7 +11111,6 @@ }, "node_modules/which": { "version": "2.0.2", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -11042,7 +11210,6 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index 04c3f155..f8674fb0 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/ade": "2026.5.28-0", "@mat3ra/code": "2026.5.27-0", - "@mat3ra/esse": "https://github.com/Exabyte-io/esse/archive/7b8fd3cdb25d9e5ffa20de930becf408dbc0f759.tar.gz", + "@mat3ra/esse": "2026.6.16-0", "@mat3ra/ide": "2026.5.28-0", "@mat3ra/made": "2026.5.28-0", "@mat3ra/mode": "2026.5.29-1",