From 40dca52394317a9bb5bcc5316c811719d72ac944 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 23 Jun 2026 00:44:22 +0300 Subject: [PATCH 01/13] chore: generic InMemoryEntity --- dist/js/basis/basis.d.ts | 13 +- dist/js/basis/basis.js | 9 +- dist/js/basis/constrained_basis.d.ts | 2 +- dist/js/basis/constrained_basis.js | 3 +- dist/js/generated/MaterialSchemaMixin.d.ts | 5 + dist/js/generated/MaterialSchemaMixin.js | 76 +++++ dist/js/lattice/lattice.d.ts | 7 +- dist/js/lattice/lattice.js | 3 +- dist/js/material.d.ts | 80 ++--- dist/js/material.js | 233 ++++++-------- dist/js/tools/material.js | 15 +- dist/js/tools/supercell.d.ts | 2 - dist/js/tools/supercell.js | 6 +- dist/js/tools/surface.js | 4 +- package-lock.json | 36 +-- package.json | 2 +- scripts/generate-mixins.ts | 28 ++ src/js/basis/basis.ts | 28 +- src/js/basis/constrained_basis.ts | 5 +- src/js/generated/MaterialSchemaMixin.ts | 82 +++++ src/js/lattice/lattice.ts | 10 +- src/js/material.ts | 349 +++++++++++---------- src/js/tools/material.ts | 21 +- src/js/tools/supercell.ts | 6 +- src/js/tools/surface.ts | 4 +- tests/js/basis/basis.ts | 13 +- tests/js/parsers/poscar.ts | 20 +- tests/js/tools/supercell.ts | 2 +- 28 files changed, 608 insertions(+), 456 deletions(-) create mode 100644 dist/js/generated/MaterialSchemaMixin.d.ts create mode 100644 dist/js/generated/MaterialSchemaMixin.js create mode 100644 scripts/generate-mixins.ts create mode 100644 src/js/generated/MaterialSchemaMixin.ts diff --git a/dist/js/basis/basis.d.ts b/dist/js/basis/basis.d.ts index 6b36ea59a..ad628ff06 100644 --- a/dist/js/basis/basis.d.ts +++ b/dist/js/basis/basis.d.ts @@ -1,5 +1,5 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { BasisSchema, Coordinate3DSchema, Vector3DSchema } from "@mat3ra/esse/dist/js/types"; +import { BaseInMemoryEntitySchema, BasisSchema, Coordinate3DSchema, Vector3DSchema } from "@mat3ra/esse/dist/js/types"; import { Cell } from "../cell/cell"; import { AtomicCoordinateValue, Coordinates } from "./coordinates"; import { AtomicElementValue, Elements } from "./elements"; @@ -30,7 +30,8 @@ export interface ElementsAndCoordinatesConfig { units?: BasisSchema["units"]; cell?: Cell; } -export declare class Basis extends InMemoryEntity implements BasisSchema { +type BasisEntitySchema = BasisConfig & BaseInMemoryEntitySchema; +export declare class Basis extends InMemoryEntity implements BasisSchema { static defaultConfig: BasisSchema; units: BasisSchema["units"]; cell: Cell; @@ -46,8 +47,8 @@ export declare class Basis extends InMemoryEntity implements BasisSchema { set coordinates(coordinates: BasisSchema["coordinates"]); get labels(): BasisSchema["labels"]; set labels(labels: BasisSchema["labels"]); - toJSON(exclude?: string[]): BasisSchema; - clone(): Basis; + toJSON(exclude?: (keyof BasisConfig)[]): BasisSchema; + clone(): this; removeAllAtoms(): void; get cellRounded(): import("@mat3ra/esse/dist/js/types").Matrix3X3Schema; get elementsArray(): object[]; @@ -55,8 +56,8 @@ export declare class Basis extends InMemoryEntity implements BasisSchema { get coordinatesAsArray(): Coordinate3DSchema[]; get isInCartesianUnits(): boolean; get isInCrystalUnits(): boolean; - toCartesian(): void; - toCrystal(): void; + toCartesian(): this; + toCrystal(): this; getElementByIndex(idx: number): AtomicElementValue; getElementById(id: number): AtomicElementValue; getCoordinateValueByIndex(idx: number): AtomicCoordinateValue; diff --git a/dist/js/basis/basis.js b/dist/js/basis/basis.js index 92b01386e..4f47aa009 100644 --- a/dist/js/basis/basis.js +++ b/dist/js/basis/basis.js @@ -84,8 +84,6 @@ class Basis extends entity_1.InMemoryEntity { set labels(labels) { this._labels = labels_1.Labels.fromObjects(labels || []); } - // TODO: figure out how to override toJSON in the parent class with generic classes - // @ts-ignore toJSON(exclude = ["cell"]) { var _a; return { @@ -96,7 +94,6 @@ class Basis extends entity_1.InMemoryEntity { ...(((_a = this.labels) === null || _a === void 0 ? void 0 : _a.length) ? { labels: this.labels } : {}), }; } - // @ts-ignore clone() { const instance = super.clone(); instance.cell = this.cell.clone(); @@ -127,15 +124,17 @@ class Basis extends entity_1.InMemoryEntity { } toCartesian() { if (this.isInCartesianUnits) - return; + return this; this._coordinates.mapArrayInPlace((point) => this.cell.convertPointToCartesian(point)); this.units = constants_1.ATOMIC_COORD_UNITS.cartesian; + return this; } toCrystal() { if (this.isInCrystalUnits) - return; + return this; this._coordinates.mapArrayInPlace((point) => this.cell.convertPointToCrystal(point)); this.units = constants_1.ATOMIC_COORD_UNITS.crystal; + return this; } getElementByIndex(idx) { return this._elements.getElementValueByIndex(idx); diff --git a/dist/js/basis/constrained_basis.d.ts b/dist/js/basis/constrained_basis.d.ts index ea3e0441a..b075d7a68 100644 --- a/dist/js/basis/constrained_basis.d.ts +++ b/dist/js/basis/constrained_basis.d.ts @@ -15,7 +15,7 @@ export interface ElementsCoordinatesAndConstraintsConfig extends ElementsAndCoor * @extends Basis */ export declare class ConstrainedBasis extends Basis { - _constraints: AtomicConstraints; + private _constraints; constructor(config: ConstrainedBasisConfig); static fromElementsCoordinatesAndConstraints(config: ElementsCoordinatesAndConstraintsConfig): ConstrainedBasis; get constraints(): AtomicConstraintsSchema; diff --git a/dist/js/basis/constrained_basis.js b/dist/js/basis/constrained_basis.js index ce25b469a..88e6a0b08 100644 --- a/dist/js/basis/constrained_basis.js +++ b/dist/js/basis/constrained_basis.js @@ -12,8 +12,7 @@ const helpers_1 = require("./helpers"); class ConstrainedBasis extends basis_1.Basis { constructor(config) { super(config); - const { constraints } = config; - this._constraints = constraints_1.AtomicConstraints.fromObjects(constraints || []); // `constraints` is an Array with ids + this._constraints = constraints_1.AtomicConstraints.fromObjects(config.constraints); // `constraints` is an Array with ids } static fromElementsCoordinatesAndConstraints(config) { const basisConfig = this._convertValuesToConfig(config); diff --git a/dist/js/generated/MaterialSchemaMixin.d.ts b/dist/js/generated/MaterialSchemaMixin.d.ts new file mode 100644 index 000000000..aff45f703 --- /dev/null +++ b/dist/js/generated/MaterialSchemaMixin.d.ts @@ -0,0 +1,5 @@ +import type { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import type { MaterialPropertiesSchema } from "@mat3ra/esse/dist/js/types"; +export type MaterialSchemaMixin = MaterialPropertiesSchema; +export type MaterialInMemoryEntity = InMemoryEntity & MaterialSchemaMixin; +export declare function materialSchemaMixin(item: InMemoryEntity): asserts item is T & MaterialSchemaMixin; diff --git a/dist/js/generated/MaterialSchemaMixin.js b/dist/js/generated/MaterialSchemaMixin.js new file mode 100644 index 000000000..8329b0211 --- /dev/null +++ b/dist/js/generated/MaterialSchemaMixin.js @@ -0,0 +1,76 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.materialSchemaMixin = void 0; +function materialSchemaMixin(item) { + // @ts-expect-error + const properties = { + get formula() { + return this.prop("formula"); + }, + set formula(value) { + this.setProp("formula", value); + }, + get unitCellFormula() { + return this.prop("unitCellFormula"); + }, + set unitCellFormula(value) { + this.setProp("unitCellFormula", value); + }, + get basis() { + return this.requiredProp("basis"); + }, + set basis(value) { + this.setProp("basis", value); + }, + get lattice() { + return this.requiredProp("lattice"); + }, + set lattice(value) { + this.setProp("lattice", value); + }, + get derivedProperties() { + return this.prop("derivedProperties"); + }, + set derivedProperties(value) { + this.setProp("derivedProperties", value); + }, + get external() { + return this.prop("external"); + }, + set external(value) { + this.setProp("external", value); + }, + get src() { + return this.prop("src"); + }, + set src(value) { + this.setProp("src", value); + }, + get scaledHash() { + return this.prop("scaledHash"); + }, + set scaledHash(value) { + this.setProp("scaledHash", value); + }, + get icsdId() { + return this.prop("icsdId"); + }, + set icsdId(value) { + this.setProp("icsdId", value); + }, + get isNonPeriodic() { + return this.prop("isNonPeriodic"); + }, + set isNonPeriodic(value) { + this.setProp("isNonPeriodic", value); + }, + get consistencyChecks() { + return this.prop("consistencyChecks"); + }, + set consistencyChecks(value) { + this.setProp("consistencyChecks", value); + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} +exports.materialSchemaMixin = materialSchemaMixin; diff --git a/dist/js/lattice/lattice.d.ts b/dist/js/lattice/lattice.d.ts index 4ce327782..7b98e0d02 100644 --- a/dist/js/lattice/lattice.d.ts +++ b/dist/js/lattice/lattice.d.ts @@ -1,5 +1,5 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { LatticeSchema, LatticeTypeEnum, LatticeTypeExtendedEnum, LatticeVectorsSchema, Matrix3X3Schema } from "@mat3ra/esse/dist/js/types"; +import { BaseInMemoryEntitySchema, LatticeSchema, LatticeTypeEnum, LatticeTypeExtendedEnum, LatticeVectorsSchema, Matrix3X3Schema } from "@mat3ra/esse/dist/js/types"; import { Cell } from "../cell/cell"; import { UnitCell } from "./unit_cell"; /** @@ -10,7 +10,8 @@ export { defaultNonPeriodicMinimumLatticeSize, diatomicLatticePaddingFactor, mol export declare class LatticeVectors extends Cell implements LatticeVectorsSchema { } export type { LatticeVectorsSchema }; -export declare class Lattice extends InMemoryEntity implements LatticeSchema { +type LatticeEntitySchema = LatticeSchema & BaseInMemoryEntitySchema; +export declare class Lattice extends InMemoryEntity implements LatticeSchema { static defaultConfig: LatticeSchema; a: LatticeSchema["a"]; b: LatticeSchema["b"]; @@ -63,5 +64,5 @@ export declare class Lattice extends InMemoryEntity implements LatticeSchema { * @example {a: true, b: false, c: false, alpha: true, beta: false, gamma: false} */ get editables(): {}; - toJSON(exclude?: string[]): LatticeSchema; + toJSON(exclude?: (keyof LatticeSchema)[]): LatticeSchema; } diff --git a/dist/js/lattice/lattice.js b/dist/js/lattice/lattice.js index 6c442b23f..14612a5f4 100644 --- a/dist/js/lattice/lattice.js +++ b/dist/js/lattice/lattice.js @@ -246,8 +246,7 @@ class Lattice extends entity_1.InMemoryEntity { } return object; } - // @ts-ignore - toJSON(exclude) { + toJSON(exclude = []) { return { ...super.toJSON(exclude), vectors: this.vectors.toJSON(), diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index e9c84d04f..8f1e15a6e 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -1,38 +1,27 @@ -import { type DefaultableInMemoryEntity, InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { type HasConsistencyChecks } from "@mat3ra/code/dist/js/entity/mixins/HasConsistencyChecksMixin"; +import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import { BankableEntity } from "@mat3ra/code/dist/js/entity/mixins/BankableEntityMixin"; +import { type Defaultable } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; import { type HasMetadata } from "@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"; -import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; -import type { AtomicConstraintsSchema, ConsistencyCheck, DerivedPropertiesSchema, FileSourceSchema, LatticeSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { type NamedEntity } from "@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"; +import type { AtomicConstraintsSchema, BasisSchema, ConsistencyCheck, DerivedPropertiesSchema, FileSourceSchema, LatticeSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; import type { BasisConfig } from "./basis/basis"; -import { type ConstrainedBasisConfig, ConstrainedBasis } from "./basis/constrained_basis"; -import { Constraint } from "./constraints/constraints"; +import { ConstrainedBasis } from "./basis/constrained_basis"; +import { type MaterialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; -interface Material extends HasConsistencyChecks, DefaultableInMemoryEntity, Required> { -} -type MaterialSchemaWithConsistencyChecksAsString = Omit & { - consistencyChecks?: ConsistencyCheck[]; -}; -type OptionallyConstrainedBasisConfig = BasisConfig & Partial>; -type Schema = MaterialSchemaWithConsistencyChecksAsString; +export type PartialBy = Omit & Partial>; +type MaterialConfig = PartialBy; export declare const defaultMaterialConfig: MaterialSchema; -declare class Material extends InMemoryEntity implements Schema { +interface BaseMaterial extends MaterialSchemaMixin, BankableEntity, NamedEntity, Defaultable, Required> { +} +declare class BaseMaterial extends InMemoryEntity { +} +declare class Material extends BaseMaterial implements MaterialSchema { static createDefault: () => Material; static get defaultConfig(): MaterialSchema; static constructMaterialFileSource(fileName: string, fileContent: string, fileExtension: string): FileSourceSchema; - get name(): string; - set name(name: string); - get src(): FileSourceSchema | undefined; - set src(src: FileSourceSchema | undefined); + private constraints; + constructor(config: MaterialConfig, constraints?: AtomicConstraintsSchema); updateFormula(): void; - /** - * Gets Bolean value for whether or not a material is non-periodic vs periodic. - * False = periodic, True = non-periodic - */ - get isNonPeriodic(): boolean; - /** - * @summary Sets the value of isNonPeriodic based on Boolean value passed as an argument. - */ - set isNonPeriodic(bool: boolean); /** * @summary Returns the specific derived property (as specified by name) for a material. */ @@ -71,29 +60,16 @@ declare class Material extends InMemoryEntity implements Schema { * @summary Returns the derived properties array for a material. */ getDerivedProperties(): DerivedPropertiesSchema; - /** - * Gets material's formula - */ - get formula(): string; - get unitCellFormula(): string; unsetFileProps(): void; - /** - * @param textOrObject Basis text or JSON object. - * @param format Format (xyz, etc.) - * @param unitz crystal/cartesian - */ - setBasis(textOrObject: string | BasisConfig, format?: string, unitz?: string): void; - setBasisConstraints(constraints: Constraint[]): void; - setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema): void; - get basis(): OptionallyConstrainedBasisConfig; - get Basis(): ConstrainedBasis; + setBasis(basis: BasisConfig): void; + setBasis(basis: string, format: "xyz", unitz?: BasisSchema["units"]): void; + getBasis(constraints?: AtomicConstraintsSchema): ConstrainedBasis; + setLattice(lattice: LatticeSchema): void; + getLattice(): Lattice; /** * High-level access to unique elements from material instead of basis. */ get uniqueElements(): ("H" | "He" | "Li" | "Be" | "B" | "C" | "N" | "O" | "F" | "Ne" | "Na" | "Mg" | "Al" | "Si" | "P" | "S" | "Cl" | "Ar" | "K" | "Ca" | "Sc" | "Ti" | "V" | "Cr" | "Mn" | "Fe" | "Co" | "Ni" | "Cu" | "Zn" | "Ga" | "Ge" | "As" | "Se" | "Br" | "Kr" | "Rb" | "Sr" | "Y" | "Zr" | "Nb" | "Mo" | "Tc" | "Ru" | "Rh" | "Pd" | "Ag" | "Cd" | "In" | "Sn" | "Sb" | "Te" | "I" | "Xe" | "Cs" | "Ba" | "La" | "Ce" | "Pr" | "Nd" | "Pm" | "Sm" | "Eu" | "Gd" | "Tb" | "Dy" | "Ho" | "Er" | "Tm" | "Yb" | "Lu" | "Hf" | "Ta" | "W" | "Re" | "Os" | "Ir" | "Pt" | "Au" | "Hg" | "Tl" | "Pb" | "Bi" | "Po" | "At" | "Rn" | "Fr" | "Ra" | "Ac" | "Th" | "Pa" | "U" | "Np" | "Pu" | "Am" | "Cm" | "Bk" | "Cf" | "Es" | "Fm" | "Md" | "No" | "Lr" | "Rf" | "Db" | "Sg" | "Bh" | "Hs" | "Mt" | "Ds" | "Rg" | "Cn" | "Nh" | "Fl" | "Mc" | "Lv" | "Ts" | "Og" | "X" | "Vac")[]; - get lattice(): LatticeSchema; - set lattice(config: LatticeSchema); - get Lattice(): Lattice; /** * Returns the inchi string from the derivedProperties for a non-periodic material, or throws an error if the * inchi cannot be found. @@ -111,23 +87,15 @@ declare class Material extends InMemoryEntity implements Schema { * @param isScaled Whether to scale the lattice parameter 'a' to 1. */ calculateHash(salt?: string, isScaled?: boolean, bypassNonPeriodicCheck?: boolean): string; - set hash(hash: string); - get hash(): string; - /** - * Calculates hash from basis and lattice as above + scales lattice properties to make lattice.a = 1 - */ - get scaledHash(): string; - get external(): MaterialSchema["external"]; - set external(external: MaterialSchema["external"]); /** * Converts basis to crystal/fractional coordinates. */ - toCrystal(): void; + toCrystal(constraints?: AtomicConstraintsSchema): void; /** * Converts current material's basis coordinates to cartesian. * No changes if coordinates already cartesian. */ - toCartesian(): void; + toCartesian(constraints?: AtomicConstraintsSchema): void; /** * Returns material's basis in XYZ format. */ @@ -164,6 +132,6 @@ declare class Material extends InMemoryEntity implements Schema { * @returns Array of checks results */ getBasisConsistencyChecks(): ConsistencyCheck[]; - toJSON(): MaterialSchema & AnyObject; + toJSON(): MaterialSchema; } export { Material }; diff --git a/dist/js/material.js b/dist/js/material.js index 9952d317b..49f04362b 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -5,16 +5,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.Material = exports.defaultMaterialConfig = void 0; const entity_1 = require("@mat3ra/code/dist/js/entity"); +const BankableEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/BankableEntityMixin"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); -const HasConsistencyChecksMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasConsistencyChecksMixin"); const HasMetadataMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"); +const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"); const crypto_js_1 = __importDefault(require("crypto-js")); const constrained_basis_1 = require("./basis/constrained_basis"); const conventional_cell_1 = require("./cell/conventional_cell"); -const constraints_1 = require("./constraints/constraints"); +const MaterialSchemaMixin_1 = require("./generated/MaterialSchemaMixin"); const lattice_1 = require("./lattice/lattice"); const parsers_1 = __importDefault(require("./parsers/parsers")); const supercell_1 = __importDefault(require("./tools/supercell")); +// TODO: remove in-line type creation +// type OptionallyConstrainedBasisConfig = BasisConfig & +// Partial>; +// interface MaterialOverrides { +// formula: string; +// unitCellFormula: string; +// basis: OptionallyConstrainedBasisConfig; +// lattice: LatticeSchema; +// scaledHash: string; +// isNonPeriodic: boolean; +// } +function parseBasis(textOrObject, format, unitz) { + if (typeof textOrObject === "string") { + if (format !== "xyz") { + throw new Error("Invalid format"); + } + return parsers_1.default.xyz.toBasisConfig(textOrObject, unitz); + } + return { constraints: [], ...textOrObject }; +} exports.defaultMaterialConfig = { name: "Silicon FCC", basis: { @@ -56,7 +77,14 @@ exports.defaultMaterialConfig = { }, metadata: {}, }; -class Material extends entity_1.InMemoryEntity { +class BaseMaterial extends entity_1.InMemoryEntity { +} +(0, MaterialSchemaMixin_1.materialSchemaMixin)(BaseMaterial.prototype); +(0, BankableEntityMixin_1.bankableEntityMixin)(BaseMaterial.prototype); +(0, NamedEntityMixin_1.namedEntityMixin)(BaseMaterial.prototype); +(0, DefaultableMixin_1.defaultableEntityMixin)(BaseMaterial); +(0, HasMetadataMixin_1.hasMetadataMixin)(BaseMaterial.prototype); +class Material extends BaseMaterial { static get defaultConfig() { return exports.defaultMaterialConfig; } @@ -68,35 +96,23 @@ class Material extends entity_1.InMemoryEntity { hash: crypto_js_1.default.MD5(fileContent).toString(), }; } - get name() { - var _a; - return (_a = this.prop("name")) !== null && _a !== void 0 ? _a : this.formula; // if name is not set, use formula, but keep empty string - } - set name(name) { - this.setProp("name", name); - } - get src() { - return this.prop("src"); - } - set src(src) { - this.setProp("src", src); + constructor(config, constraints = []) { + var _a, _b, _c, _d; + super({ + ...config, + formula: (_a = config.formula) !== null && _a !== void 0 ? _a : "", + name: (_c = (_b = config.name) !== null && _b !== void 0 ? _b : config.formula) !== null && _c !== void 0 ? _c : "", + metadata: (_d = config.metadata) !== null && _d !== void 0 ? _d : {}, + }); + this.constraints = []; + this.formula = config.formula || this.getBasis().formula; + this.name = this.name || this.formula; + this.constraints = constraints; } updateFormula() { - this.setProp("formula", this.Basis.formula); - this.setProp("unitCellFormula", this.Basis.unitCellFormula); - } - /** - * Gets Bolean value for whether or not a material is non-periodic vs periodic. - * False = periodic, True = non-periodic - */ - get isNonPeriodic() { - return this.prop("isNonPeriodic", false); - } - /** - * @summary Sets the value of isNonPeriodic based on Boolean value passed as an argument. - */ - set isNonPeriodic(bool) { - this.setProp("isNonPeriodic", bool); + const basis = this.getBasis(); + this.formula = basis.formula; + this.unitCellFormula = basis.unitCellFormula; } /** * @summary Returns the specific derived property (as specified by name) for a material. @@ -108,90 +124,63 @@ class Material extends entity_1.InMemoryEntity { * @summary Returns the derived properties array for a material. */ getDerivedProperties() { - return this.prop("derivedProperties", []); - } - /** - * Gets material's formula - */ - get formula() { - return this.prop("formula") || this.Basis.formula; - } - get unitCellFormula() { - return this.prop("unitCellFormula") || this.Basis.unitCellFormula; + var _a; + return (_a = this.derivedProperties) !== null && _a !== void 0 ? _a : []; } unsetFileProps() { this.unsetProp("src"); this.unsetProp("icsdId"); this.unsetProp("external"); } - /** - * @param textOrObject Basis text or JSON object. - * @param format Format (xyz, etc.) - * @param unitz crystal/cartesian - */ setBasis(textOrObject, format, unitz) { - let basis; - if (typeof textOrObject === "string" && format === "xyz") { - basis = parsers_1.default.xyz.toBasisConfig(textOrObject, unitz); - } - else { - basis = textOrObject; - } - this.setProp("basis", basis); + const { constraints, ...basis } = parseBasis(textOrObject, format, unitz); + this.basis = basis; + this.constraints = constraints; this.unsetFileProps(); this.updateFormula(); } - setBasisConstraints(constraints) { - const basisWithConstraints = { - ...this.basis, - constraints: constraints.map((c) => c.toJSON()), - }; - this.setBasis(basisWithConstraints); - } - setBasisConstraintsFromArrayOfObjects(constraints) { - const constraintsInstances = constraints.map((c) => { - return constraints_1.Constraint.fromValueAndId(c.value, c.id); - }); - this.setBasisConstraints(constraintsInstances); - } - get basis() { - return this.requiredProp("basis"); - } - // returns the instance of {ConstrainedBasis} class - get Basis() { + getBasis(constraints) { const basisData = this.basis; return new constrained_basis_1.ConstrainedBasis({ ...basisData, - cell: this.Lattice.vectors, - constraints: basisData.constraints || [], + cell: this.getLattice().vectors, + constraints: constraints !== null && constraints !== void 0 ? constraints : this.constraints, }); } - /** - * High-level access to unique elements from material instead of basis. - */ - get uniqueElements() { - return this.Basis.uniqueElements; - } - get lattice() { - return this.prop("lattice"); - } - set lattice(config) { - const originalIsInCrystalUnits = this.Basis.isInCrystalUnits; - const basis = this.Basis; + setLattice(lattice) { + const basis = this.getBasis(); + const originalIsInCrystalUnits = basis.isInCrystalUnits; basis.toCartesian(); - const newLattice = new lattice_1.Lattice(config); - basis.cell = newLattice.vectors; - if (originalIsInCrystalUnits) + basis.cell = new lattice_1.Lattice(lattice).vectors; + if (originalIsInCrystalUnits) { basis.toCrystal(); - // Preserve all properties from the original basis to ensure constraints are included - const newBasisConfig = basis.toJSON(); - this.setProp("basis", newBasisConfig); - this.setProp("lattice", config); + } + this.basis = basis.toJSON(); + this.lattice = lattice; this.unsetFileProps(); } - get Lattice() { + getLattice() { return new lattice_1.Lattice(this.lattice); } + // private setBasisConstraints(constraints: Constraint[]) { + // const basisWithConstraints = { + // ...this.basis, + // constraints: constraints.map((c) => c.toJSON()), + // }; + // this.setBasis(basisWithConstraints); + // } + // setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { + // const constraintsInstances = constraints.map((c) => { + // return Constraint.fromValueAndId(c.value, c.id); + // }); + // this.setBasisConstraints(constraintsInstances); + // } + /** + * High-level access to unique elements from material instead of basis. + */ + get uniqueElements() { + return this.getBasis().uniqueElements; + } /** * Returns the inchi string from the derivedProperties for a non-periodic material, or throws an error if the * inchi cannot be found. @@ -218,47 +207,29 @@ class Material extends entity_1.InMemoryEntity { let message; if (!this.isNonPeriodic || bypassNonPeriodicCheck) { message = - this.Basis.hashString + "#" + this.Lattice.getHashString(isScaled) + "#" + salt; + this.getBasis().hashString + + "#" + + this.getLattice().getHashString(isScaled) + + "#" + + salt; } else { message = this.getInchiStringForHash(); } return crypto_js_1.default.MD5(message).toString(); } - set hash(hash) { - this.setProp("hash", hash); - } - get hash() { - return this.prop("hash"); - } - /** - * Calculates hash from basis and lattice as above + scales lattice properties to make lattice.a = 1 - */ - get scaledHash() { - return this.calculateHash("", true); - } - get external() { - return this.prop("external"); - } - set external(external) { - this.setProp("external", external); - } /** * Converts basis to crystal/fractional coordinates. */ - toCrystal() { - const basis = this.Basis; - basis.toCrystal(); - this.setProp("basis", basis.toJSON()); + toCrystal(constraints = []) { + this.basis = this.getBasis(constraints).toCrystal().toJSON(); } /** * Converts current material's basis coordinates to cartesian. * No changes if coordinates already cartesian. */ - toCartesian() { - const basis = this.Basis; - basis.toCartesian(); - this.setProp("basis", basis.toJSON()); + toCartesian(constraints = []) { + this.basis = this.getBasis(constraints).toCartesian().toJSON(); } /** * Returns material's basis in XYZ format. @@ -298,12 +269,13 @@ class Material extends entity_1.InMemoryEntity { */ getACopyWithConventionalCell() { const material = this.clone(); + const lattice = this.getLattice(); // if conventional and primitive cells are the same => return a copy. - if ((0, conventional_cell_1.isConventionalCellSameAsPrimitiveForLatticeType)(this.Lattice.type)) { + if ((0, conventional_cell_1.isConventionalCellSameAsPrimitiveForLatticeType)(lattice.type)) { return material; } - const conventionalSupercellMatrix = conventional_cell_1.PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS[this.Lattice.type]; - const conventionalLatticeType = conventional_cell_1.PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES[this.Lattice.type]; + const conventionalSupercellMatrix = conventional_cell_1.PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS[lattice.type]; + const conventionalLatticeType = conventional_cell_1.PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES[lattice.type]; const config = supercell_1.default.generateConfig(this, conventionalSupercellMatrix); config.lattice.type = conventionalLatticeType; config.name = `${this.name} - conventional cell`; @@ -326,8 +298,8 @@ class Material extends entity_1.InMemoryEntity { getBasisConsistencyChecks() { const checks = []; const limit = 1000; - const basis = this.Basis; - if (this.Basis.elements.length < limit) { + const basis = this.getBasis(); + if (basis.elements.length < limit) { const overlappingAtomsGroups = basis.getOverlappingAtoms(); overlappingAtomsGroups.forEach(({ id1, id2, element1, element2 }) => { checks.push({ @@ -346,17 +318,14 @@ class Material extends entity_1.InMemoryEntity { return checks; } toJSON() { - // validation intoJSON() method will fail if name is not set in _json - this.name = this.name || this.formula; + const lattice = this.getLattice(); + const basis = this.getBasis(); return { ...super.toJSON(), - lattice: this.Lattice.toJSON(), - basis: this.Basis.toJSON(), + lattice: lattice.toJSON(), + basis: basis.toJSON(), isNonPeriodic: this.isNonPeriodic, }; } } exports.Material = Material; -(0, DefaultableMixin_1.defaultableEntityMixin)(Material); -(0, HasConsistencyChecksMixin_1.hasConsistencyChecksMixin)(Material.prototype); -(0, HasMetadataMixin_1.hasMetadataMixin)(Material.prototype); diff --git a/dist/js/tools/material.js b/dist/js/tools/material.js index 1d5dba6b9..037113fe3 100644 --- a/dist/js/tools/material.js +++ b/dist/js/tools/material.js @@ -15,7 +15,7 @@ function scaleOneLatticeVector(material, key = "a", factor = 1.0) { throw new Error("Lattice vectors are undefined"); } lattice.vectors[key] = lattice.vectors[key].map((v) => v * factor); - material.lattice = lattice_1.Lattice.fromVectors(lattice.vectors).toJSON(); + material.setLattice(lattice_1.Lattice.fromVectors(lattice.vectors).toJSON()); } /** * Updates the size of a materials lattice using the minimumLatticeSize function. @@ -23,10 +23,10 @@ function scaleOneLatticeVector(material, key = "a", factor = 1.0) { * @param material {Material} */ function scaleLatticeToMakeNonPeriodic(material) { - material.lattice = lattice_1.Lattice.fromConfigPartial({ - a: material.Basis.getMinimumLatticeSize(), + material.setLattice(lattice_1.Lattice.fromConfigPartial({ + a: material.getBasis().getMinimumLatticeSize(), type: "CUB", - }).toJSON(); + }).toJSON()); } /** * Updates the basis of a material by translating the coordinates @@ -34,11 +34,12 @@ function scaleLatticeToMakeNonPeriodic(material) { * @param material {Material} * */ function translateAtomsToCenter(material) { - const originalUnits = material.Basis.units; + const basis = material.getBasis(); + const originalUnits = basis.units; material.toCartesian(); - const updatedBasis = material.Basis; + const updatedBasis = basis.toCartesian(); const centerOfCoordinates = updatedBasis.centerOfCoordinatesPoint; - const centerOfLattice = math_1.math.multiply(0.5, material.Lattice.vectorArrays.reduce((a, b) => math_1.math.add(a, b))); + const centerOfLattice = math_1.math.multiply(0.5, material.getLattice().vectorArrays.reduce((a, b) => math_1.math.add(a, b))); const translationVector = math_1.math.subtract(centerOfLattice, centerOfCoordinates); updatedBasis.translateByVector(translationVector); material.setBasis(updatedBasis.toJSON()); diff --git a/dist/js/tools/supercell.d.ts b/dist/js/tools/supercell.d.ts index 0afac6c78..60e3f021a 100644 --- a/dist/js/tools/supercell.d.ts +++ b/dist/js/tools/supercell.d.ts @@ -9,8 +9,6 @@ import type { Material } from "../material"; declare function generateNewBasisWithinSupercell(basis: Basis | ConstrainedBasis, cell: Cell, supercell: Cell, supercellMatrix: Matrix3X3Schema): Basis; /** * @summary Generates supercell config for the specified material. - * @param material - * @param supercellMatrix {Number[][]} */ declare function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema): { name: string; diff --git a/dist/js/tools/supercell.js b/dist/js/tools/supercell.js index ac4105b3b..5a699e02d 100644 --- a/dist/js/tools/supercell.js +++ b/dist/js/tools/supercell.js @@ -35,17 +35,15 @@ function generateNewBasisWithinSupercell(basis, cell, supercell, supercellMatrix } /** * @summary Generates supercell config for the specified material. - * @param material - * @param supercellMatrix {Number[][]} */ function generateConfig(material, supercellMatrix) { const det = math_1.math.det(supercellMatrix); if (det === 0) { throw new Error("Scaling matrix is degenerate."); } - const cell = material.Lattice.vectors; + const cell = material.getLattice().vectors; const supercell = cell.cloneAndScaleByMatrix(supercellMatrix); - const newBasis = generateNewBasisWithinSupercell(material.Basis, cell, supercell, supercellMatrix); + const newBasis = generateNewBasisWithinSupercell(material.getBasis(), cell, supercell, supercellMatrix); const newLattice = lattice_1.Lattice.fromVectors({ a: supercell.a, b: supercell.b, diff --git a/dist/js/tools/surface.js b/dist/js/tools/surface.js index 57a0c115f..582ec8bdf 100644 --- a/dist/js/tools/surface.js +++ b/dist/js/tools/surface.js @@ -133,7 +133,7 @@ function getDimensionsScalingMatrix(outOfPlaneAxisIndex, thickness, vx, vy) { function generateConfig(material, millerIndices, numberOfLayers = 1, vx = 1, vy = 1) { if (numberOfLayers < 1) throw new Error("Made.tools.surface.generateConfig: number of layers < 1."); - const cell = material.Lattice.vectors; + const cell = material.getLattice().vectors; const millerScalingMatrix = getMillerScalingMatrix(cell, millerIndices); const millerSupercell = cell.cloneAndScaleByMatrix(millerScalingMatrix); const millerPlanePseudoNormal = cell.convertPointToCartesian(millerIndices); @@ -141,7 +141,7 @@ function generateConfig(material, millerIndices, numberOfLayers = 1, vx = 1, vy const dimensionsScalingMatrix = getDimensionsScalingMatrix(outOfPlaneAxisIndex, numberOfLayers, vx, vy); const supercellMatrix = MULT(dimensionsScalingMatrix, millerScalingMatrix); const supercell = millerSupercell.cloneAndScaleByMatrix(dimensionsScalingMatrix); - const tempBasis = material.Basis.clone(); + const tempBasis = material.getBasis().clone(); const newBasis = supercell_1.default.generateNewBasisWithinSupercell(tempBasis, cell, supercell, supercellMatrix); const newLattice = lattice_1.Lattice.fromVectors({ a: supercell.vectorArrays[0], diff --git a/package-lock.json b/package-lock.json index 621209e4b..449200521 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "@babel/register": "^7.22.15", "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", - "@mat3ra/code": "2026.5.27-0", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", "@mat3ra/esse": "2026.5.27-0", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", @@ -3020,9 +3020,9 @@ "license": "MIT" }, "node_modules/@mat3ra/code": { - "version": "2026.5.27-0", - "resolved": "https://registry.npmjs.org/@mat3ra/code/-/code-2026.5.27-0.tgz", - "integrity": "sha512-uPlUgleg2pRTzCZREnNQrsOjevoePE/wdJ43Eux+3CP4HMrwyA05c2uG/7flLCNQ/fe746j1FcZOeKB6+xECSA==", + "version": "0.0.0", + "resolved": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", + "integrity": "sha512-9EYHv81whrIGBiduVUrewliSgbES9dGILi9Ype77oWmPnJYNRkEIalO9bu493jsz09I0FveHCWzhFYpvkc3v5w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4065,14 +4065,14 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "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": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/pkgr" @@ -5923,9 +5923,9 @@ } }, "node_modules/eslint-compat-utils/node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "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, @@ -8325,9 +8325,9 @@ } }, "node_modules/jsonc-eslint-parser/node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "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, @@ -10650,14 +10650,14 @@ } }, "node_modules/synckit": { - "version": "0.11.12", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", - "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "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.2.9" + "@pkgr/core": "^0.3.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" diff --git a/package.json b/package.json index 12b104644..830762895 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@babel/register": "^7.22.15", "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", - "@mat3ra/code": "2026.5.27-0", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", "@mat3ra/esse": "2026.5.27-0", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", diff --git a/scripts/generate-mixins.ts b/scripts/generate-mixins.ts new file mode 100644 index 000000000..2b64d7a86 --- /dev/null +++ b/scripts/generate-mixins.ts @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +/** + * Script to generate mixin properties from JSON schema. + * + * Usage: + * npm run generate-mixins + */ + +import generateSchemaMixin from "@mat3ra/code/dist/js/generateSchemaMixin"; +import allSchemas from "@mat3ra/esse/dist/js/schemas.json"; +import type { JSONSchema7 } from "json-schema"; + +const SKIP_FIELDS: string[] = []; + +const OUTPUT_PATHS = { + "material/material-properties": "src/js/generated/MaterialSchemaMixin.ts", +}; + +function main() { + const result = generateSchemaMixin(allSchemas as JSONSchema7[], OUTPUT_PATHS, SKIP_FIELDS); + + if (result.errorCount > 0) { + process.exit(1); + } +} + +main(); diff --git a/src/js/basis/basis.ts b/src/js/basis/basis.ts index bbbb9860f..3d559d8fb 100644 --- a/src/js/basis/basis.ts +++ b/src/js/basis/basis.ts @@ -2,7 +2,12 @@ import { getElectronegativity, getElementAtomicRadius } from "@exabyte-io/periodic-table.js"; import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; import { math } from "@mat3ra/code/dist/js/math"; -import { BasisSchema, Coordinate3DSchema, Vector3DSchema } from "@mat3ra/esse/dist/js/types"; +import { + BaseInMemoryEntitySchema, + BasisSchema, + Coordinate3DSchema, + Vector3DSchema, +} from "@mat3ra/esse/dist/js/types"; import { chain, toPairs, uniq, values } from "lodash"; import { Cell } from "../cell/cell"; @@ -71,7 +76,9 @@ const DEFAULT_BASIS_CONFIG = { units: "crystal", }; -export class Basis extends InMemoryEntity implements BasisSchema { +type BasisEntitySchema = BasisConfig & BaseInMemoryEntitySchema; + +export class Basis extends InMemoryEntity implements BasisSchema { static defaultConfig: BasisSchema = DEFAULT_BASIS_CONFIG as BasisSchema; units: BasisSchema["units"]; @@ -155,9 +162,7 @@ export class Basis extends InMemoryEntity implements BasisSchema { this._labels = Labels.fromObjects(labels || []); } - // TODO: figure out how to override toJSON in the parent class with generic classes - // @ts-ignore - toJSON(exclude: string[] = ["cell"]): BasisSchema { + toJSON(exclude: (keyof BasisConfig)[] = ["cell"]): BasisSchema { return { ...super.toJSON(exclude), elements: this.elements, @@ -167,8 +172,7 @@ export class Basis extends InMemoryEntity implements BasisSchema { }; } - // @ts-ignore - override clone(): Basis { + override clone(): this { const instance = super.clone(); instance.cell = this.cell.clone(); return instance; @@ -204,16 +208,18 @@ export class Basis extends InMemoryEntity implements BasisSchema { return this.units === ATOMIC_COORD_UNITS.crystal; } - toCartesian(): void { - if (this.isInCartesianUnits) return; + toCartesian() { + if (this.isInCartesianUnits) return this; this._coordinates.mapArrayInPlace((point) => this.cell.convertPointToCartesian(point)); this.units = ATOMIC_COORD_UNITS.cartesian as BasisSchema["units"]; + return this; } - toCrystal(): void { - if (this.isInCrystalUnits) return; + toCrystal() { + if (this.isInCrystalUnits) return this; this._coordinates.mapArrayInPlace((point) => this.cell.convertPointToCrystal(point)); this.units = ATOMIC_COORD_UNITS.crystal as BasisSchema["units"]; + return this; } getElementByIndex(idx: number): AtomicElementValue { diff --git a/src/js/basis/constrained_basis.ts b/src/js/basis/constrained_basis.ts index 4945cd9df..e401ac087 100644 --- a/src/js/basis/constrained_basis.ts +++ b/src/js/basis/constrained_basis.ts @@ -20,12 +20,11 @@ export interface ElementsCoordinatesAndConstraintsConfig extends ElementsAndCoor * @extends Basis */ export class ConstrainedBasis extends Basis { - _constraints: AtomicConstraints; + private _constraints: AtomicConstraints; constructor(config: ConstrainedBasisConfig) { super(config); - const { constraints } = config; - this._constraints = AtomicConstraints.fromObjects(constraints || []); // `constraints` is an Array with ids + this._constraints = AtomicConstraints.fromObjects(config.constraints); // `constraints` is an Array with ids } static fromElementsCoordinatesAndConstraints( diff --git a/src/js/generated/MaterialSchemaMixin.ts b/src/js/generated/MaterialSchemaMixin.ts new file mode 100644 index 000000000..cd0f43a11 --- /dev/null +++ b/src/js/generated/MaterialSchemaMixin.ts @@ -0,0 +1,82 @@ +import type { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; +import type { MaterialPropertiesSchema } from "@mat3ra/esse/dist/js/types"; + +export type MaterialSchemaMixin = MaterialPropertiesSchema; + +export type MaterialInMemoryEntity = InMemoryEntity & MaterialSchemaMixin; + +export function materialSchemaMixin( + item: InMemoryEntity, +): asserts item is T & MaterialSchemaMixin { + // @ts-expect-error + const properties: InMemoryEntity & MaterialSchemaMixin = { + get formula() { + return this.prop("formula"); + }, + set formula(value: MaterialPropertiesSchema["formula"]) { + this.setProp("formula", value); + }, + get unitCellFormula() { + return this.prop("unitCellFormula"); + }, + set unitCellFormula(value: MaterialPropertiesSchema["unitCellFormula"]) { + this.setProp("unitCellFormula", value); + }, + get basis() { + return this.requiredProp("basis"); + }, + set basis(value: MaterialPropertiesSchema["basis"]) { + this.setProp("basis", value); + }, + get lattice() { + return this.requiredProp("lattice"); + }, + set lattice(value: MaterialPropertiesSchema["lattice"]) { + this.setProp("lattice", value); + }, + get derivedProperties() { + return this.prop("derivedProperties"); + }, + set derivedProperties(value: MaterialPropertiesSchema["derivedProperties"]) { + this.setProp("derivedProperties", value); + }, + get external() { + return this.prop("external"); + }, + set external(value: MaterialPropertiesSchema["external"]) { + this.setProp("external", value); + }, + get src() { + return this.prop("src"); + }, + set src(value: MaterialPropertiesSchema["src"]) { + this.setProp("src", value); + }, + get scaledHash() { + return this.prop("scaledHash"); + }, + set scaledHash(value: MaterialPropertiesSchema["scaledHash"]) { + this.setProp("scaledHash", value); + }, + get icsdId() { + return this.prop("icsdId"); + }, + set icsdId(value: MaterialPropertiesSchema["icsdId"]) { + this.setProp("icsdId", value); + }, + get isNonPeriodic() { + return this.prop("isNonPeriodic"); + }, + set isNonPeriodic(value: MaterialPropertiesSchema["isNonPeriodic"]) { + this.setProp("isNonPeriodic", value); + }, + get consistencyChecks() { + return this.prop("consistencyChecks"); + }, + set consistencyChecks(value: MaterialPropertiesSchema["consistencyChecks"]) { + this.setProp("consistencyChecks", value); + }, + }; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} diff --git a/src/js/lattice/lattice.ts b/src/js/lattice/lattice.ts index 55e6d4c79..8b1c9965e 100644 --- a/src/js/lattice/lattice.ts +++ b/src/js/lattice/lattice.ts @@ -2,6 +2,7 @@ import { HASH_TOLERANCE } from "@mat3ra/code/dist/js/constants"; import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; import { math } from "@mat3ra/code/dist/js/math"; import { + BaseInMemoryEntitySchema, Coordinate3DSchema, LatticeSchema, LatticeTypeEnum, @@ -30,7 +31,9 @@ export class LatticeVectors extends Cell implements LatticeVectorsSchema {} export type { LatticeVectorsSchema }; -export class Lattice extends InMemoryEntity implements LatticeSchema { +type LatticeEntitySchema = LatticeSchema & BaseInMemoryEntitySchema; + +export class Lattice extends InMemoryEntity implements LatticeSchema { static defaultConfig: LatticeSchema = { a: 1, b: 1, @@ -294,11 +297,10 @@ export class Lattice extends InMemoryEntity implements LatticeSchema { return object; } - // @ts-ignore - toJSON(exclude?: string[]): LatticeSchema { + toJSON(exclude: (keyof LatticeSchema)[] = []): LatticeSchema { return { ...super.toJSON(exclude), vectors: this.vectors.toJSON(), - } as LatticeSchema; + }; } } diff --git a/src/js/material.ts b/src/js/material.ts index 6abac3d22..65644c1ef 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -1,16 +1,23 @@ -import { type DefaultableInMemoryEntity, InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { defaultableEntityMixin } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; +import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; import { - type HasConsistencyChecks, - hasConsistencyChecksMixin, -} from "@mat3ra/code/dist/js/entity/mixins/HasConsistencyChecksMixin"; + BankableEntity, + bankableEntityMixin, +} from "@mat3ra/code/dist/js/entity/mixins/BankableEntityMixin"; +import { + type Defaultable, + defaultableEntityMixin, +} from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; import { type HasMetadata, hasMetadataMixin, } from "@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"; -import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; +import { + type NamedEntity, + namedEntityMixin, +} from "@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"; import type { AtomicConstraintsSchema, + BasisSchema, ConsistencyCheck, DerivedPropertiesSchema, FileSourceSchema, @@ -27,25 +34,41 @@ import { PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES, PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS, } from "./cell/conventional_cell"; -import { Constraint } from "./constraints/constraints"; +import { type MaterialSchemaMixin, materialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; import parsers from "./parsers/parsers"; import supercellTools from "./tools/supercell"; -interface Material - extends HasConsistencyChecks, - DefaultableInMemoryEntity, - Required> {} - // TODO: remove in-line type creation -type MaterialSchemaWithConsistencyChecksAsString = Omit & { - consistencyChecks?: ConsistencyCheck[]; -}; +// type OptionallyConstrainedBasisConfig = BasisConfig & +// Partial>; + +// interface MaterialOverrides { +// formula: string; +// unitCellFormula: string; +// basis: OptionallyConstrainedBasisConfig; +// lattice: LatticeSchema; +// scaledHash: string; +// isNonPeriodic: boolean; +// } + +function parseBasis( + textOrObject: string | BasisConfig, + format?: "xyz", + unitz?: BasisSchema["units"], +): ConstrainedBasisConfig { + if (typeof textOrObject === "string") { + if (format !== "xyz") { + throw new Error("Invalid format"); + } + return parsers.xyz.toBasisConfig(textOrObject, unitz); + } + return { constraints: [], ...textOrObject }; +} -type OptionallyConstrainedBasisConfig = BasisConfig & - Partial>; +export type PartialBy = Omit & Partial>; -type Schema = MaterialSchemaWithConsistencyChecksAsString; +type MaterialConfig = PartialBy; export const defaultMaterialConfig: MaterialSchema = { name: "Silicon FCC", @@ -89,7 +112,22 @@ export const defaultMaterialConfig: MaterialSchema = { metadata: {}, }; -class Material extends InMemoryEntity implements Schema { +interface BaseMaterial + extends MaterialSchemaMixin, + BankableEntity, + NamedEntity, + Defaultable, + Required> {} + +class BaseMaterial extends InMemoryEntity {} + +materialSchemaMixin(BaseMaterial.prototype); +bankableEntityMixin(BaseMaterial.prototype); +namedEntityMixin(BaseMaterial.prototype); +defaultableEntityMixin(BaseMaterial); +hasMetadataMixin(BaseMaterial.prototype); + +class Material extends BaseMaterial implements MaterialSchema { declare static createDefault: () => Material; static get defaultConfig() { @@ -109,40 +147,25 @@ class Material extends InMemoryEntity implements Schema { }; } - get name() { - return this.prop("name") ?? this.formula; // if name is not set, use formula, but keep empty string - } - - set name(name: string) { - this.setProp("name", name); - } + private constraints: AtomicConstraintsSchema = []; - get src() { - return this.prop("src"); - } + constructor(config: MaterialConfig, constraints: AtomicConstraintsSchema = []) { + super({ + ...config, + formula: config.formula ?? "", + name: config.name ?? config.formula ?? "", + metadata: config.metadata ?? {}, + }); - set src(src: FileSourceSchema | undefined) { - this.setProp("src", src); + this.formula = config.formula || this.getBasis().formula; + this.name = this.name || this.formula; + this.constraints = constraints; } updateFormula() { - this.setProp("formula", this.Basis.formula); - this.setProp("unitCellFormula", this.Basis.unitCellFormula); - } - - /** - * Gets Bolean value for whether or not a material is non-periodic vs periodic. - * False = periodic, True = non-periodic - */ - get isNonPeriodic(): boolean { - return this.prop("isNonPeriodic", false); - } - - /** - * @summary Sets the value of isNonPeriodic based on Boolean value passed as an argument. - */ - set isNonPeriodic(bool: boolean) { - this.setProp("isNonPeriodic", bool); + const basis = this.getBasis(); + this.formula = basis.formula; + this.unitCellFormula = basis.unitCellFormula; } /** @@ -156,18 +179,7 @@ class Material extends InMemoryEntity implements Schema { * @summary Returns the derived properties array for a material. */ getDerivedProperties(): DerivedPropertiesSchema { - return this.prop("derivedProperties", []); - } - - /** - * Gets material's formula - */ - get formula(): string { - return this.prop("formula") || this.Basis.formula; - } - - get unitCellFormula(): string { - return this.prop("unitCellFormula") || this.Basis.unitCellFormula; + return this.derivedProperties ?? []; } unsetFileProps() { @@ -176,85 +188,72 @@ class Material extends InMemoryEntity implements Schema { this.unsetProp("external"); } - /** - * @param textOrObject Basis text or JSON object. - * @param format Format (xyz, etc.) - * @param unitz crystal/cartesian - */ - setBasis(textOrObject: string | BasisConfig, format?: string, unitz?: string) { - let basis: BasisConfig | undefined; - if (typeof textOrObject === "string" && format === "xyz") { - basis = parsers.xyz.toBasisConfig(textOrObject, unitz); - } else { - basis = textOrObject as BasisConfig; - } - this.setProp("basis", basis); - this.unsetFileProps(); - this.updateFormula(); - } + setBasis(basis: BasisConfig): void; - setBasisConstraints(constraints: Constraint[]) { - const basisWithConstraints = { - ...this.basis, - constraints: constraints.map((c) => c.toJSON()), - }; - this.setBasis(basisWithConstraints); - } + setBasis(basis: string, format: "xyz", unitz?: BasisSchema["units"]): void; - setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { - const constraintsInstances = constraints.map((c) => { - return Constraint.fromValueAndId(c.value, c.id); - }); - this.setBasisConstraints(constraintsInstances); - } + setBasis(textOrObject: string | BasisConfig, format?: "xyz", unitz?: BasisSchema["units"]) { + const { constraints, ...basis } = parseBasis(textOrObject, format, unitz); - get basis() { - return this.requiredProp("basis"); + this.basis = basis; + this.constraints = constraints; + this.unsetFileProps(); + this.updateFormula(); } - // returns the instance of {ConstrainedBasis} class - get Basis() { + getBasis(constraints?: AtomicConstraintsSchema) { const basisData = this.basis; return new ConstrainedBasis({ ...basisData, - cell: this.Lattice.vectors, - constraints: basisData.constraints || [], + cell: this.getLattice().vectors, + constraints: constraints ?? this.constraints, }); } - /** - * High-level access to unique elements from material instead of basis. - */ - get uniqueElements() { - return this.Basis.uniqueElements; - } - - get lattice(): LatticeSchema { - return this.prop("lattice") as LatticeSchema; - } + setLattice(lattice: LatticeSchema) { + const basis = this.getBasis(); + const originalIsInCrystalUnits = basis.isInCrystalUnits; - set lattice(config: LatticeSchema) { - const originalIsInCrystalUnits = this.Basis.isInCrystalUnits; - const basis = this.Basis; basis.toCartesian(); + basis.cell = new Lattice(lattice).vectors; - const newLattice = new Lattice(config); - basis.cell = newLattice.vectors; - if (originalIsInCrystalUnits) basis.toCrystal(); + if (originalIsInCrystalUnits) { + basis.toCrystal(); + } - // Preserve all properties from the original basis to ensure constraints are included - const newBasisConfig = basis.toJSON(); - this.setProp("basis", newBasisConfig); - this.setProp("lattice", config); + this.basis = basis.toJSON(); + this.lattice = lattice; this.unsetFileProps(); } - get Lattice(): Lattice { + getLattice() { return new Lattice(this.lattice); } + // private setBasisConstraints(constraints: Constraint[]) { + // const basisWithConstraints = { + // ...this.basis, + // constraints: constraints.map((c) => c.toJSON()), + // }; + // this.setBasis(basisWithConstraints); + // } + + // setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { + // const constraintsInstances = constraints.map((c) => { + // return Constraint.fromValueAndId(c.value, c.id); + // }); + // this.setBasisConstraints(constraintsInstances); + // } + + /** + * High-level access to unique elements from material instead of basis. + */ + get uniqueElements() { + return this.getBasis().uniqueElements; + } + /** * Returns the inchi string from the derivedProperties for a non-periodic material, or throws an error if the * inchi cannot be found. @@ -282,53 +281,30 @@ class Material extends InMemoryEntity implements Schema { let message; if (!this.isNonPeriodic || bypassNonPeriodicCheck) { message = - this.Basis.hashString + "#" + this.Lattice.getHashString(isScaled) + "#" + salt; + this.getBasis().hashString + + "#" + + this.getLattice().getHashString(isScaled) + + "#" + + salt; } else { message = this.getInchiStringForHash(); } return CryptoJS.MD5(message).toString(); } - set hash(hash: string) { - this.setProp("hash", hash); - } - - get hash(): string { - return this.prop("hash") as string; - } - - /** - * Calculates hash from basis and lattice as above + scales lattice properties to make lattice.a = 1 - */ - get scaledHash(): string { - return this.calculateHash("", true); - } - - get external() { - return this.prop("external"); - } - - set external(external: MaterialSchema["external"]) { - this.setProp("external", external); - } - /** * Converts basis to crystal/fractional coordinates. */ - toCrystal() { - const basis = this.Basis; - basis.toCrystal(); - this.setProp("basis", basis.toJSON()); + toCrystal(constraints: AtomicConstraintsSchema = []) { + this.basis = this.getBasis(constraints).toCrystal().toJSON(); } /** * Converts current material's basis coordinates to cartesian. * No changes if coordinates already cartesian. */ - toCartesian() { - const basis = this.Basis; - basis.toCartesian(); - this.setProp("basis", basis.toJSON()); + toCartesian(constraints: AtomicConstraintsSchema = []) { + this.basis = this.getBasis(constraints).toCartesian().toJSON(); } /** @@ -372,15 +348,16 @@ class Material extends InMemoryEntity implements Schema { getACopyWithConventionalCell(): this { const material = this.clone(); + const lattice = this.getLattice(); + // if conventional and primitive cells are the same => return a copy. - if (isConventionalCellSameAsPrimitiveForLatticeType(this.Lattice.type)) { + if (isConventionalCellSameAsPrimitiveForLatticeType(lattice.type)) { return material; } const conventionalSupercellMatrix = - PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS[this.Lattice.type]; - const conventionalLatticeType = - PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES[this.Lattice.type]; + PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS[lattice.type]; + const conventionalLatticeType = PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES[lattice.type]; const config = supercellTools.generateConfig(this, conventionalSupercellMatrix); config.lattice.type = conventionalLatticeType; @@ -409,9 +386,9 @@ class Material extends InMemoryEntity implements Schema { getBasisConsistencyChecks(): ConsistencyCheck[] { const checks: ConsistencyCheck[] = []; const limit = 1000; - const basis = this.Basis; + const basis = this.getBasis(); - if (this.Basis.elements.length < limit) { + if (basis.elements.length < limit) { const overlappingAtomsGroups = basis.getOverlappingAtoms(); overlappingAtomsGroups.forEach(({ id1, id2, element1, element2 }) => { checks.push( @@ -438,21 +415,65 @@ class Material extends InMemoryEntity implements Schema { return checks; } - toJSON(): MaterialSchema & AnyObject { - // validation intoJSON() method will fail if name is not set in _json - this.name = this.name || this.formula; + toJSON(): MaterialSchema { + const lattice = this.getLattice(); + const basis = this.getBasis(); return { - ...(super.toJSON() as MaterialSchema & AnyObject), - lattice: this.Lattice.toJSON(), - basis: this.Basis.toJSON(), + ...super.toJSON(), + lattice: lattice.toJSON(), + basis: basis.toJSON(), isNonPeriodic: this.isNonPeriodic, - }; + } as MaterialSchema; } } -defaultableEntityMixin(Material); -hasConsistencyChecksMixin(Material.prototype); -hasMetadataMixin(Material.prototype); +// function materialOverridesMixin( +// item: InMemoryEntity, +// ): asserts item is InMemoryEntity & MaterialOverrides { +// // @ts-expect-error — mixin properties installed on Material.prototype +// const properties: Material & MaterialOverrides = { +// get formula() { +// return this.prop("formula") || this.Basis.formula; +// }, +// get unitCellFormula() { +// return this.prop("unitCellFormula") || this.Basis.unitCellFormula; +// }, +// get basis() { +// return this.requiredProp("basis"); +// }, +// get lattice() { +// return this.requiredProp("lattice"); +// }, +// set lattice(config: LatticeSchema) { +// const originalIsInCrystalUnits = this.Basis.isInCrystalUnits; +// const basis = this.Basis; +// basis.toCartesian(); + +// const newLattice = new Lattice(config); +// basis.cell = newLattice.vectors; +// if (originalIsInCrystalUnits) basis.toCrystal(); + +// const newBasisConfig = basis.toJSON(); +// this.setProp("basis", newBasisConfig); +// this.setProp("lattice", config); + +// this.unsetFileProps(); +// }, +// get scaledHash() { +// return this.calculateHash("", true); +// }, +// get isNonPeriodic() { +// return this.prop("isNonPeriodic", false) ?? false; +// }, +// set isNonPeriodic(bool: boolean) { +// this.setProp("isNonPeriodic", bool); +// }, +// }; + +// Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +// } + +// materialOverridesMixin(Material.prototype); export { Material }; diff --git a/src/js/tools/material.ts b/src/js/tools/material.ts index 76c4f2615..42fe7ff10 100644 --- a/src/js/tools/material.ts +++ b/src/js/tools/material.ts @@ -17,9 +17,9 @@ function scaleOneLatticeVector(material: Material, key: "a" | "b" | "c" = "a", f if (lattice.vectors === undefined) { throw new Error("Lattice vectors are undefined"); } - lattice.vectors[key] = lattice.vectors![key].map((v) => v * factor) as Vector3DSchema; + lattice.vectors[key] = lattice.vectors[key].map((v) => v * factor) as Vector3DSchema; - material.lattice = Lattice.fromVectors(lattice.vectors).toJSON(); + material.setLattice(Lattice.fromVectors(lattice.vectors).toJSON()); } /** @@ -28,10 +28,12 @@ function scaleOneLatticeVector(material: Material, key: "a" | "b" | "c" = "a", f * @param material {Material} */ function scaleLatticeToMakeNonPeriodic(material: Material) { - material.lattice = Lattice.fromConfigPartial({ - a: material.Basis.getMinimumLatticeSize(), - type: "CUB", - } as LatticeSchema).toJSON(); + material.setLattice( + Lattice.fromConfigPartial({ + a: material.getBasis().getMinimumLatticeSize(), + type: "CUB", + } as LatticeSchema).toJSON(), + ); } /** @@ -40,13 +42,14 @@ function scaleLatticeToMakeNonPeriodic(material: Material) { * @param material {Material} * */ function translateAtomsToCenter(material: Material) { - const originalUnits = material.Basis.units; + const basis = material.getBasis(); + const originalUnits = basis.units; material.toCartesian(); - const updatedBasis = material.Basis; + const updatedBasis = basis.toCartesian(); const centerOfCoordinates = updatedBasis.centerOfCoordinatesPoint; const centerOfLattice = math.multiply( 0.5, - material.Lattice.vectorArrays.reduce((a, b) => math.add(a, b) as Vector3DSchema), + material.getLattice().vectorArrays.reduce((a, b) => math.add(a, b) as Vector3DSchema), ); const translationVector = math.subtract(centerOfLattice, centerOfCoordinates); updatedBasis.translateByVector(translationVector as Vector3DSchema); diff --git a/src/js/tools/supercell.ts b/src/js/tools/supercell.ts index 0ebc03143..26276e7b2 100644 --- a/src/js/tools/supercell.ts +++ b/src/js/tools/supercell.ts @@ -52,18 +52,16 @@ function generateNewBasisWithinSupercell( /** * @summary Generates supercell config for the specified material. - * @param material - * @param supercellMatrix {Number[][]} */ function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema) { const det = math.det(supercellMatrix); if (det === 0) { throw new Error("Scaling matrix is degenerate."); } - const cell = material.Lattice.vectors; + const cell = material.getLattice().vectors; const supercell = cell.cloneAndScaleByMatrix(supercellMatrix); const newBasis = generateNewBasisWithinSupercell( - material.Basis, + material.getBasis(), cell, supercell, supercellMatrix, diff --git a/src/js/tools/surface.ts b/src/js/tools/surface.ts index eb49d9a5d..9e4c1fe77 100644 --- a/src/js/tools/surface.ts +++ b/src/js/tools/surface.ts @@ -175,7 +175,7 @@ function generateConfig( if (numberOfLayers < 1) throw new Error("Made.tools.surface.generateConfig: number of layers < 1."); - const cell = material.Lattice.vectors; + const cell = material.getLattice().vectors; const millerScalingMatrix = getMillerScalingMatrix(cell, millerIndices); const millerSupercell = cell.cloneAndScaleByMatrix(millerScalingMatrix); const millerPlanePseudoNormal = cell.convertPointToCartesian(millerIndices); @@ -189,7 +189,7 @@ function generateConfig( ); const supercellMatrix = MULT(dimensionsScalingMatrix, millerScalingMatrix); const supercell = millerSupercell.cloneAndScaleByMatrix(dimensionsScalingMatrix); - const tempBasis = material.Basis.clone(); + const tempBasis = material.getBasis().clone(); const newBasis = SupercellTools.generateNewBasisWithinSupercell( tempBasis, cell, diff --git a/tests/js/basis/basis.ts b/tests/js/basis/basis.ts index 6c784b9f1..c9dd77f70 100644 --- a/tests/js/basis/basis.ts +++ b/tests/js/basis/basis.ts @@ -29,20 +29,20 @@ describe("Basis", () => { }); it("should return true when basis is compared to its clone", () => { - const basis1 = new Material(Na4Cl4).Basis; + const basis1 = new Material(Na4Cl4).getBasis(); const basis2 = basis1.clone(); expect(basis1.isEqualTo(basis2)).to.be.equal(true); expect(basis1.hasEquivalentCellTo(basis2)).to.be.equal(true); }); it("should return jsonified basis", () => { - const basis = new Material(Na4Cl4).Basis; + const basis = new Material(Na4Cl4).getBasis(); expect(basis.toJSON()).to.be.deep.almost.equal(Na4Cl4.basis); }); it("should return true if cells are equal", () => { - const basis1 = new Material(Na4Cl4).Basis; - const basis2 = new Material(Na4Cl4Cartesian).Basis; + const basis1 = new Material(Na4Cl4).getBasis(); + const basis2 = new Material(Na4Cl4Cartesian).getBasis(); expect(basis1.hasEquivalentCellTo(basis2)).to.be.equal(true); }); @@ -120,8 +120,7 @@ describe("Basis", () => { }); it("should convert crystal to cartesian", () => { - const basis = new Material(Na4Cl4).Basis; - basis.toCartesian(); + const basis = new Material(Na4Cl4).getBasis().toCartesian(); expect(basis.isInCartesianUnits).to.be.equal(true); expect(basis.coordinates).to.be.deep.almost.equal(Na4Cl4Cartesian.basis.coordinates); }); @@ -195,7 +194,7 @@ describe("Basis", () => { */ it("should return standard representation", () => { - const basis = new Material(Na4Cl4Cartesian).Basis; + const basis = new Material(Na4Cl4Cartesian).getBasis(); expect(basis.standardRepresentation).to.be.deep.almost.equal(Na4Cl4.basis); }); diff --git a/tests/js/parsers/poscar.ts b/tests/js/parsers/poscar.ts index 962c4bfc7..ae99b08ba 100644 --- a/tests/js/parsers/poscar.ts +++ b/tests/js/parsers/poscar.ts @@ -4,6 +4,15 @@ import { AtomicConstraints } from "../../../src/js/constraints/constraints"; import { Material } from "../../../src/js/material"; import parsers from "../../../src/js/parsers/parsers"; import { atomsCount } from "../../../src/js/parsers/poscar"; +import { + atomicConstraints, + H2OPoscar, + Na4Cl4, + Na4Cl4Poscar, + Silicon, + Zr1H23Zr1H1, + Zr1H23Zr1H1Poscar, +} from "../fixtures"; const O2_POSCAR_WITH_COMMENTS = `O2 molecule in a box 1.0 ! universal scaling parameters @@ -16,15 +25,6 @@ cart ! positions in cartesian coordinates 0 0 0 O 0 0 1.21 O `; -import { - atomicConstraints, - H2OPoscar, - Na4Cl4, - Na4Cl4Poscar, - Silicon, - Zr1H23Zr1H1, - Zr1H23Zr1H1Poscar, -} from "../fixtures"; describe("Parsers.POSCAR", () => { it("should return a valid poscar", () => { @@ -81,7 +81,7 @@ direct const material = new Material(Silicon); const clonedMaterial = material.clone(); - clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.Basis.units); + clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.getBasis().units); const poscar = clonedMaterial.getAsPOSCAR(true); expect(poscar).to.be.equal(poscarConstraints); diff --git a/tests/js/tools/supercell.ts b/tests/js/tools/supercell.ts index 57f54c6f4..c537b566b 100644 --- a/tests/js/tools/supercell.ts +++ b/tests/js/tools/supercell.ts @@ -44,7 +44,7 @@ direct 0.625000000 0.250000000 0.250000000 Ge`; const material = new Material(Silicon); const clonedMaterial = material.clone(); - clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.Basis.units); + clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.getBasis().units); const supercellConfig = Made.tools.supercell.generateConfig(clonedMaterial, [ [2, 0, 0], [0, 1, 0], From 6ab110a28b4b081824258066eb08f3db75a99c72 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 23 Jun 2026 00:46:25 +0300 Subject: [PATCH 02/13] chore: cleanups --- dist/js/material.js | 24 -------------- src/js/material.ts | 76 --------------------------------------------- 2 files changed, 100 deletions(-) diff --git a/dist/js/material.js b/dist/js/material.js index 49f04362b..3411b3d3b 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -16,17 +16,6 @@ const MaterialSchemaMixin_1 = require("./generated/MaterialSchemaMixin"); const lattice_1 = require("./lattice/lattice"); const parsers_1 = __importDefault(require("./parsers/parsers")); const supercell_1 = __importDefault(require("./tools/supercell")); -// TODO: remove in-line type creation -// type OptionallyConstrainedBasisConfig = BasisConfig & -// Partial>; -// interface MaterialOverrides { -// formula: string; -// unitCellFormula: string; -// basis: OptionallyConstrainedBasisConfig; -// lattice: LatticeSchema; -// scaledHash: string; -// isNonPeriodic: boolean; -// } function parseBasis(textOrObject, format, unitz) { if (typeof textOrObject === "string") { if (format !== "xyz") { @@ -162,19 +151,6 @@ class Material extends BaseMaterial { getLattice() { return new lattice_1.Lattice(this.lattice); } - // private setBasisConstraints(constraints: Constraint[]) { - // const basisWithConstraints = { - // ...this.basis, - // constraints: constraints.map((c) => c.toJSON()), - // }; - // this.setBasis(basisWithConstraints); - // } - // setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { - // const constraintsInstances = constraints.map((c) => { - // return Constraint.fromValueAndId(c.value, c.id); - // }); - // this.setBasisConstraints(constraintsInstances); - // } /** * High-level access to unique elements from material instead of basis. */ diff --git a/src/js/material.ts b/src/js/material.ts index 65644c1ef..fc4c3c3ef 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -39,19 +39,6 @@ import { Lattice } from "./lattice/lattice"; import parsers from "./parsers/parsers"; import supercellTools from "./tools/supercell"; -// TODO: remove in-line type creation -// type OptionallyConstrainedBasisConfig = BasisConfig & -// Partial>; - -// interface MaterialOverrides { -// formula: string; -// unitCellFormula: string; -// basis: OptionallyConstrainedBasisConfig; -// lattice: LatticeSchema; -// scaledHash: string; -// isNonPeriodic: boolean; -// } - function parseBasis( textOrObject: string | BasisConfig, format?: "xyz", @@ -232,21 +219,6 @@ class Material extends BaseMaterial implements MaterialSchema { return new Lattice(this.lattice); } - // private setBasisConstraints(constraints: Constraint[]) { - // const basisWithConstraints = { - // ...this.basis, - // constraints: constraints.map((c) => c.toJSON()), - // }; - // this.setBasis(basisWithConstraints); - // } - - // setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { - // const constraintsInstances = constraints.map((c) => { - // return Constraint.fromValueAndId(c.value, c.id); - // }); - // this.setBasisConstraints(constraintsInstances); - // } - /** * High-level access to unique elements from material instead of basis. */ @@ -428,52 +400,4 @@ class Material extends BaseMaterial implements MaterialSchema { } } -// function materialOverridesMixin( -// item: InMemoryEntity, -// ): asserts item is InMemoryEntity & MaterialOverrides { -// // @ts-expect-error — mixin properties installed on Material.prototype -// const properties: Material & MaterialOverrides = { -// get formula() { -// return this.prop("formula") || this.Basis.formula; -// }, -// get unitCellFormula() { -// return this.prop("unitCellFormula") || this.Basis.unitCellFormula; -// }, -// get basis() { -// return this.requiredProp("basis"); -// }, -// get lattice() { -// return this.requiredProp("lattice"); -// }, -// set lattice(config: LatticeSchema) { -// const originalIsInCrystalUnits = this.Basis.isInCrystalUnits; -// const basis = this.Basis; -// basis.toCartesian(); - -// const newLattice = new Lattice(config); -// basis.cell = newLattice.vectors; -// if (originalIsInCrystalUnits) basis.toCrystal(); - -// const newBasisConfig = basis.toJSON(); -// this.setProp("basis", newBasisConfig); -// this.setProp("lattice", config); - -// this.unsetFileProps(); -// }, -// get scaledHash() { -// return this.calculateHash("", true); -// }, -// get isNonPeriodic() { -// return this.prop("isNonPeriodic", false) ?? false; -// }, -// set isNonPeriodic(bool: boolean) { -// this.setProp("isNonPeriodic", bool); -// }, -// }; - -// Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -// } - -// materialOverridesMixin(Material.prototype); - export { Material }; From bd4309ae3ea20cb5026658b6c0a8ab7b965ab076 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 23 Jun 2026 01:39:28 +0300 Subject: [PATCH 03/13] chore: cleanups --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 449200521..735cc2cb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", - "@mat3ra/esse": "2026.5.27-0", + "@mat3ra/esse": "2026.6.16-0", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", "@types/crypto-js": "^4.2.2", @@ -3114,9 +3114,9 @@ } }, "node_modules/@mat3ra/esse": { - "version": "2026.5.27-0", - "resolved": "https://registry.npmjs.org/@mat3ra/esse/-/esse-2026.5.27-0.tgz", - "integrity": "sha512-0/z6ORG+hNK64g/5S6JOZbgSUlTJDK4weMkkK4OIqYO4W26GQWRhvtRg4ydK38kV+IUHnwNYlEl3Z0b6XOwqTg==", + "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": { diff --git a/package.json b/package.json index 830762895..b9c4e12ee 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", - "@mat3ra/esse": "2026.5.27-0", + "@mat3ra/esse": "2026.6.16-0", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", "@types/crypto-js": "^4.2.2", From 3a52dde8681b5fc39ef9e8ee548339e377e761f8 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 23 Jun 2026 17:29:13 +0300 Subject: [PATCH 04/13] chore: generic InMemoryEntity --- dist/js/material.d.ts | 3 +- dist/js/material.js | 2 - package-lock.json | 398 +++++++++++++------------------------- package.json | 2 +- src/js/material.ts | 6 - tests/js/material.test.ts | 4 +- 6 files changed, 137 insertions(+), 278 deletions(-) diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index 8f1e15a6e..cf3e110b9 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -1,5 +1,4 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { BankableEntity } from "@mat3ra/code/dist/js/entity/mixins/BankableEntityMixin"; import { type Defaultable } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; import { type HasMetadata } from "@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"; import { type NamedEntity } from "@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"; @@ -11,7 +10,7 @@ import { Lattice } from "./lattice/lattice"; export type PartialBy = Omit & Partial>; type MaterialConfig = PartialBy; export declare const defaultMaterialConfig: MaterialSchema; -interface BaseMaterial extends MaterialSchemaMixin, BankableEntity, NamedEntity, Defaultable, Required> { +interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, Required> { } declare class BaseMaterial extends InMemoryEntity { } diff --git a/dist/js/material.js b/dist/js/material.js index 3411b3d3b..e82581a91 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.Material = exports.defaultMaterialConfig = void 0; const entity_1 = require("@mat3ra/code/dist/js/entity"); -const BankableEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/BankableEntityMixin"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); const HasMetadataMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"); const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"); @@ -69,7 +68,6 @@ exports.defaultMaterialConfig = { class BaseMaterial extends entity_1.InMemoryEntity { } (0, MaterialSchemaMixin_1.materialSchemaMixin)(BaseMaterial.prototype); -(0, BankableEntityMixin_1.bankableEntityMixin)(BaseMaterial.prototype); (0, NamedEntityMixin_1.namedEntityMixin)(BaseMaterial.prototype); (0, DefaultableMixin_1.defaultableEntityMixin)(BaseMaterial); (0, HasMetadataMixin_1.hasMetadataMixin)(BaseMaterial.prototype); diff --git a/package-lock.json b/package-lock.json index 735cc2cb3..978b6e8f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "@babel/register": "^7.22.15", "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", - "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", "@mat3ra/esse": "2026.6.16-0", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", @@ -72,6 +72,7 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -588,6 +589,7 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -2389,6 +2391,7 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -2408,6 +2411,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2423,6 +2427,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -2431,6 +2436,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -2445,6 +2451,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, "engines": { "node": ">= 4" } @@ -2453,6 +2460,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2464,12 +2472,14 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@eslint/eslintrc/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "node_modules/@exabyte-io/eslint-config": { "version": "2025.5.13-0", @@ -2835,6 +2845,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", "deprecated": "Use @eslint/config-array instead", + "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -2848,7 +2859,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "deprecated": "Use @eslint/object-schema instead" + "deprecated": "Use @eslint/object-schema instead", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -3021,8 +3033,8 @@ }, "node_modules/@mat3ra/code": { "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", - "integrity": "sha512-9EYHv81whrIGBiduVUrewliSgbES9dGILi9Ype77oWmPnJYNRkEIalO9bu493jsz09I0FveHCWzhFYpvkc3v5w==", + "resolved": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", + "integrity": "sha512-d50ie+SFn2jZIpIdGzdcx8olP35+zV+PMablDj1yTQcHho/A+9vOXibp405PGjcYCMr53TvzOm4IlrGWveQEMg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4064,20 +4076,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.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -4460,6 +4458,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -4489,6 +4488,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", @@ -4532,6 +4532,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "engines": { "node": ">=6" } @@ -4567,6 +4568,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -4575,6 +4577,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -4797,6 +4800,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, "engines": { "node": ">=8" } @@ -5040,6 +5044,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -5129,6 +5134,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5350,6 +5356,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -5357,7 +5364,8 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/colorette": { "version": "2.0.20", @@ -5474,6 +5482,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5559,7 +5568,8 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "node_modules/default-require-extensions": { "version": "3.0.1", @@ -5633,17 +5643,6 @@ "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", @@ -5660,6 +5659,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -5682,12 +5682,14 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5844,6 +5846,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -5853,6 +5856,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -5905,37 +5909,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.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.4", "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", @@ -6043,29 +6016,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.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -6220,67 +6170,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "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/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.7.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", @@ -6392,20 +6281,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", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -6478,6 +6353,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -6492,6 +6368,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, "engines": { "node": ">=4" } @@ -6508,6 +6385,7 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, "dependencies": { "@babel/highlight": "^7.10.4" } @@ -6516,6 +6394,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6531,6 +6410,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -6545,6 +6425,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -6553,6 +6434,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6568,6 +6450,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -6578,12 +6461,14 @@ "node_modules/eslint/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -6595,6 +6480,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -6609,6 +6495,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -6617,6 +6504,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, "engines": { "node": ">= 4" } @@ -6625,6 +6513,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -6636,12 +6525,14 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/eslint/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -6653,6 +6544,7 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -6666,12 +6558,14 @@ "node_modules/eslint/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6682,12 +6576,14 @@ "node_modules/eslint/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, "dependencies": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -6701,6 +6597,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -6712,6 +6609,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, "engines": { "node": ">=4" } @@ -6720,6 +6618,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -6732,6 +6631,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -6744,6 +6644,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -6809,7 +6710,8 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-diff": { "version": "1.3.0", @@ -6836,17 +6738,20 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, "funding": [ { "type": "github", @@ -6871,6 +6776,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -6927,6 +6833,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -6939,7 +6846,8 @@ "node_modules/flatted": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.0.tgz", - "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==" + "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==", + "dev": true }, "node_modules/for-each": { "version": "0.3.3", @@ -7050,7 +6958,8 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true }, "node_modules/functions-have-names": { "version": "1.2.3", @@ -7163,6 +7072,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -7269,6 +7179,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { "node": ">=4" } @@ -7404,6 +7315,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7419,6 +7331,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { "node": ">=0.8.19" } @@ -7582,6 +7495,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -7602,6 +7516,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -7625,6 +7540,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -7906,7 +7822,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isobject": { "version": "3.0.1", @@ -8159,7 +8076,8 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-schema": { "version": "0.4.0", @@ -8253,12 +8171,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -8271,73 +8191,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/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", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -8357,6 +8210,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -8388,6 +8242,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -8579,12 +8434,14 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", @@ -9101,7 +8958,8 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "node_modules/natural-compare-lite": { "version": "1.4.0", @@ -9611,6 +9469,7 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -9690,6 +9549,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -9717,6 +9577,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -9804,6 +9665,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -9851,6 +9713,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -9870,6 +9733,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "engines": { "node": ">=6" } @@ -9986,6 +9850,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, "engines": { "node": ">=8" }, @@ -10062,6 +9927,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10106,6 +9972,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "engines": { "node": ">=4" } @@ -10153,6 +10020,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -10326,6 +10194,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -10337,6 +10206,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -10373,6 +10243,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -10389,6 +10260,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -10403,6 +10275,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -10413,7 +10286,8 @@ "node_modules/slice-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/source-map": { "version": "0.6.1", @@ -10513,6 +10387,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10591,6 +10466,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10620,6 +10496,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -10631,6 +10508,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -10649,27 +10527,11 @@ "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.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -10698,7 +10560,8 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/through": { "version": "2.3.8", @@ -10879,6 +10742,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -10899,6 +10763,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -11114,6 +10979,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -11135,7 +11001,8 @@ "node_modules/v8-compile-cache": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", - "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==" + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", @@ -11189,6 +11056,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, diff --git a/package.json b/package.json index b9c4e12ee..62d290d60 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@babel/register": "^7.22.15", "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", - "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/62fa688445923bcb412b362e8a41b365bdbbad29.tar.gz", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", "@mat3ra/esse": "2026.6.16-0", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", diff --git a/src/js/material.ts b/src/js/material.ts index fc4c3c3ef..84773c7b1 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -1,8 +1,4 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { - BankableEntity, - bankableEntityMixin, -} from "@mat3ra/code/dist/js/entity/mixins/BankableEntityMixin"; import { type Defaultable, defaultableEntityMixin, @@ -101,7 +97,6 @@ export const defaultMaterialConfig: MaterialSchema = { interface BaseMaterial extends MaterialSchemaMixin, - BankableEntity, NamedEntity, Defaultable, Required> {} @@ -109,7 +104,6 @@ interface BaseMaterial class BaseMaterial extends InMemoryEntity {} materialSchemaMixin(BaseMaterial.prototype); -bankableEntityMixin(BaseMaterial.prototype); namedEntityMixin(BaseMaterial.prototype); defaultableEntityMixin(BaseMaterial); hasMetadataMixin(BaseMaterial.prototype); diff --git a/tests/js/material.test.ts b/tests/js/material.test.ts index f593784e1..e7e75e2cb 100644 --- a/tests/js/material.test.ts +++ b/tests/js/material.test.ts @@ -16,8 +16,8 @@ describe("Material", () => { it("should return cloned material", () => { const material = new Material(Silicon); const clonedMaterial = material.clone(); - clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.Basis.units); - expect(clonedMaterial.Basis.elements).to.have.lengthOf(2); + clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.getBasis().units); + expect(clonedMaterial.getBasis().elements).to.have.lengthOf(2); }); describe("calculateHash", () => { From 8805edc503378bd3b1ed2518085ebf8f4b57eb92 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Wed, 24 Jun 2026 17:44:35 +0300 Subject: [PATCH 05/13] feat: restore hashed mixin on Material with updated esse Compose system/hashed via esse c6c4d84b1, wire hashedEntityMixin on Material, and keep persisted hash in sync after basis/lattice mutations. Co-authored-by: Cursor --- dist/js/made.d.ts | 2 +- dist/js/material.d.ts | 10 ++++++---- dist/js/material.js | 13 ++++++++++++- dist/js/tools/surface.d.ts | 6 +++--- package-lock.json | 8 ++++---- package.json | 2 +- src/js/material.ts | 22 +++++++++++++++++++--- src/js/tools/surface.ts | 11 +++-------- tests/js/tools/surface.ts | 19 +++++++++++++------ 9 files changed, 62 insertions(+), 31 deletions(-) diff --git a/dist/js/made.d.ts b/dist/js/made.d.ts index 9d77155d2..cd8061b7b 100644 --- a/dist/js/made.d.ts +++ b/dist/js/made.d.ts @@ -33,7 +33,7 @@ export declare const Made: { cartesian: string; }; Material: typeof Material; - defaultMaterialConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema; + defaultMaterialConfig: import("./material").MaterialConfig; Lattice: typeof Lattice; Cell: typeof Cell; UnitCell: typeof UnitCell; diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index cf3e110b9..f387bca81 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -1,5 +1,6 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; import { type Defaultable } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; +import { type HashedEntity } from "@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"; import { type HasMetadata } from "@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"; import { type NamedEntity } from "@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"; import type { AtomicConstraintsSchema, BasisSchema, ConsistencyCheck, DerivedPropertiesSchema, FileSourceSchema, LatticeSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; @@ -8,19 +9,20 @@ import { ConstrainedBasis } from "./basis/constrained_basis"; import { type MaterialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; export type PartialBy = Omit & Partial>; -type MaterialConfig = PartialBy; -export declare const defaultMaterialConfig: MaterialSchema; -interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, Required> { +export type MaterialConfig = PartialBy; +export declare const defaultMaterialConfig: MaterialConfig; +interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, HashedEntity, Required> { } declare class BaseMaterial extends InMemoryEntity { } declare class Material extends BaseMaterial implements MaterialSchema { static createDefault: () => Material; - static get defaultConfig(): MaterialSchema; + static get defaultConfig(): MaterialConfig; static constructMaterialFileSource(fileName: string, fileContent: string, fileExtension: string): FileSourceSchema; private constraints; constructor(config: MaterialConfig, constraints?: AtomicConstraintsSchema); updateFormula(): void; + updateHash(): void; /** * @summary Returns the specific derived property (as specified by name) for a material. */ diff --git a/dist/js/material.js b/dist/js/material.js index e82581a91..e3e8ba2b2 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.Material = exports.defaultMaterialConfig = void 0; const entity_1 = require("@mat3ra/code/dist/js/entity"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); +const HashedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"); const HasMetadataMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"); const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"); const crypto_js_1 = __importDefault(require("crypto-js")); @@ -71,6 +72,7 @@ class BaseMaterial extends entity_1.InMemoryEntity { (0, NamedEntityMixin_1.namedEntityMixin)(BaseMaterial.prototype); (0, DefaultableMixin_1.defaultableEntityMixin)(BaseMaterial); (0, HasMetadataMixin_1.hasMetadataMixin)(BaseMaterial.prototype); +(0, HashedEntityMixin_1.hashedEntityMixin)(BaseMaterial.prototype); class Material extends BaseMaterial { static get defaultConfig() { return exports.defaultMaterialConfig; @@ -84,23 +86,28 @@ class Material extends BaseMaterial { }; } constructor(config, constraints = []) { - var _a, _b, _c, _d; + var _a, _b, _c, _d, _e, _f; super({ ...config, formula: (_a = config.formula) !== null && _a !== void 0 ? _a : "", name: (_c = (_b = config.name) !== null && _b !== void 0 ? _b : config.formula) !== null && _c !== void 0 ? _c : "", metadata: (_d = config.metadata) !== null && _d !== void 0 ? _d : {}, + hash: (_e = config.hash) !== null && _e !== void 0 ? _e : "", }); this.constraints = []; this.formula = config.formula || this.getBasis().formula; this.name = this.name || this.formula; this.constraints = constraints; + this.hash = (_f = config.hash) !== null && _f !== void 0 ? _f : this.calculateHash("", false, this.isNonPeriodic); } updateFormula() { const basis = this.getBasis(); this.formula = basis.formula; this.unitCellFormula = basis.unitCellFormula; } + updateHash() { + this.hash = this.calculateHash("", false, this.isNonPeriodic); + } /** * @summary Returns the specific derived property (as specified by name) for a material. */ @@ -125,6 +132,7 @@ class Material extends BaseMaterial { this.constraints = constraints; this.unsetFileProps(); this.updateFormula(); + this.updateHash(); } getBasis(constraints) { const basisData = this.basis; @@ -145,6 +153,7 @@ class Material extends BaseMaterial { this.basis = basis.toJSON(); this.lattice = lattice; this.unsetFileProps(); + this.updateHash(); } getLattice() { return new lattice_1.Lattice(this.lattice); @@ -197,6 +206,7 @@ class Material extends BaseMaterial { */ toCrystal(constraints = []) { this.basis = this.getBasis(constraints).toCrystal().toJSON(); + this.updateHash(); } /** * Converts current material's basis coordinates to cartesian. @@ -204,6 +214,7 @@ class Material extends BaseMaterial { */ toCartesian(constraints = []) { this.basis = this.getBasis(constraints).toCartesian().toJSON(); + this.updateHash(); } /** * Returns material's basis in XYZ format. diff --git a/dist/js/tools/surface.d.ts b/dist/js/tools/surface.d.ts index 56e4ad1ad..553721333 100644 --- a/dist/js/tools/surface.d.ts +++ b/dist/js/tools/surface.d.ts @@ -1,6 +1,6 @@ -import { Coordinate3DSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; -import { Material } from "../material"; -export type SlabConfigSchema = MaterialSchema & { +import { Coordinate3DSchema } from "@mat3ra/esse/dist/js/types"; +import { type MaterialConfig, Material } from "../material"; +export type SlabConfigSchema = MaterialConfig & { outOfPlaneAxisIndex: number; }; declare function generateConfig(material: Material, millerIndices: Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number): SlabConfigSchema; diff --git a/package-lock.json b/package-lock.json index 978b6e8f9..ad45cac82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", - "@mat3ra/esse": "2026.6.16-0", + "@mat3ra/esse": "https://github.com/mat3ra/esse/tarball/c6c4d84b1eedda012c968fd570b08b0faecde6c2", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", "@types/crypto-js": "^4.2.2", @@ -3126,9 +3126,9 @@ } }, "node_modules/@mat3ra/esse": { - "version": "2026.6.16-0", - "resolved": "https://registry.npmjs.org/@mat3ra/esse/-/esse-2026.6.16-0.tgz", - "integrity": "sha512-SZYwIzWX0G2RaX9uC1bH1531qCi2I2MMNdfKINhG7kweDuZ5Z4jnRBvQopstBfK8QjTSRuxeT4R6iiiT3e+ACg==", + "version": "0.0.0", + "resolved": "https://github.com/mat3ra/esse/tarball/c6c4d84b1eedda012c968fd570b08b0faecde6c2", + "integrity": "sha512-2Zfm/ywV58tU8kWpK8U1KQDcfA1xSHYfcyb2JJBvSlZH/I58S3vUYr1w18L5Nqp1x6zB0z8CM9oB+5S5JSBYNw==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 62d290d60..552a697dc 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@babel/runtime-corejs3": "^7.16.8", "@exabyte-io/eslint-config": "2025.5.13-0", "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", - "@mat3ra/esse": "2026.6.16-0", + "@mat3ra/esse": "https://github.com/mat3ra/esse/tarball/c6c4d84b1eedda012c968fd570b08b0faecde6c2", "@mat3ra/tsconfig": "2024.6.3-0", "@mat3ra/utils": "^2026.6.11-0", "@types/crypto-js": "^4.2.2", diff --git a/src/js/material.ts b/src/js/material.ts index 84773c7b1..272b21c01 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -3,6 +3,10 @@ import { type Defaultable, defaultableEntityMixin, } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; +import { + type HashedEntity, + hashedEntityMixin, +} from "@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"; import { type HasMetadata, hasMetadataMixin, @@ -51,9 +55,9 @@ function parseBasis( export type PartialBy = Omit & Partial>; -type MaterialConfig = PartialBy; +export type MaterialConfig = PartialBy; -export const defaultMaterialConfig: MaterialSchema = { +export const defaultMaterialConfig: MaterialConfig = { name: "Silicon FCC", basis: { elements: [ @@ -99,6 +103,7 @@ interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, + HashedEntity, Required> {} class BaseMaterial extends InMemoryEntity {} @@ -107,11 +112,12 @@ materialSchemaMixin(BaseMaterial.prototype); namedEntityMixin(BaseMaterial.prototype); defaultableEntityMixin(BaseMaterial); hasMetadataMixin(BaseMaterial.prototype); +hashedEntityMixin(BaseMaterial.prototype); class Material extends BaseMaterial implements MaterialSchema { declare static createDefault: () => Material; - static get defaultConfig() { + static get defaultConfig(): MaterialConfig { return defaultMaterialConfig; } @@ -136,11 +142,13 @@ class Material extends BaseMaterial implements MaterialSchema { formula: config.formula ?? "", name: config.name ?? config.formula ?? "", metadata: config.metadata ?? {}, + hash: config.hash ?? "", }); this.formula = config.formula || this.getBasis().formula; this.name = this.name || this.formula; this.constraints = constraints; + this.hash = config.hash ?? this.calculateHash("", false, this.isNonPeriodic); } updateFormula() { @@ -149,6 +157,10 @@ class Material extends BaseMaterial implements MaterialSchema { this.unitCellFormula = basis.unitCellFormula; } + updateHash() { + this.hash = this.calculateHash("", false, this.isNonPeriodic); + } + /** * @summary Returns the specific derived property (as specified by name) for a material. */ @@ -180,6 +192,7 @@ class Material extends BaseMaterial implements MaterialSchema { this.constraints = constraints; this.unsetFileProps(); this.updateFormula(); + this.updateHash(); } getBasis(constraints?: AtomicConstraintsSchema) { @@ -207,6 +220,7 @@ class Material extends BaseMaterial implements MaterialSchema { this.lattice = lattice; this.unsetFileProps(); + this.updateHash(); } getLattice() { @@ -263,6 +277,7 @@ class Material extends BaseMaterial implements MaterialSchema { */ toCrystal(constraints: AtomicConstraintsSchema = []) { this.basis = this.getBasis(constraints).toCrystal().toJSON(); + this.updateHash(); } /** @@ -271,6 +286,7 @@ class Material extends BaseMaterial implements MaterialSchema { */ toCartesian(constraints: AtomicConstraintsSchema = []) { this.basis = this.getBasis(constraints).toCartesian().toJSON(); + this.updateHash(); } /** diff --git a/src/js/tools/surface.ts b/src/js/tools/surface.ts index 9e4c1fe77..97dd68a7c 100644 --- a/src/js/tools/surface.ts +++ b/src/js/tools/surface.ts @@ -1,14 +1,9 @@ import { math } from "@mat3ra/code/dist/js/math"; -import { - Coordinate3DSchema, - MaterialSchema, - Matrix3X3Schema, - Vector3DSchema, -} from "@mat3ra/esse/dist/js/types"; +import { Coordinate3DSchema, Matrix3X3Schema, Vector3DSchema } from "@mat3ra/esse/dist/js/types"; import { Cell } from "../cell/cell"; import { Lattice } from "../lattice/lattice"; -import { Material } from "../material"; +import { type MaterialConfig, Material } from "../material"; import SupercellTools from "./supercell"; const MULT = math.multiply; @@ -152,7 +147,7 @@ function getDimensionsScalingMatrix( return transformationMatrix as Matrix3X3Schema; } -export type SlabConfigSchema = MaterialSchema & { +export type SlabConfigSchema = MaterialConfig & { outOfPlaneAxisIndex: number; }; diff --git a/tests/js/tools/surface.ts b/tests/js/tools/surface.ts index 941475f9d..7041db1b5 100644 --- a/tests/js/tools/surface.ts +++ b/tests/js/tools/surface.ts @@ -8,6 +8,11 @@ import { Silicon, SiSlab100, SiSlab111, SiSlab111NoVacuum } from "../fixtures"; const { assertDeepAlmostEqual } = Utils.assertion; +const toJSONWithoutHash = (material: Material) => { + const { hash: _, ...json } = material.toJSON(); + return json; +}; + const generateSlabWithVacuum = (slabConfig: SlabConfigSchema, vacuumRatio: number) => { const slabMaterial = new Material(slabConfig); const { outOfPlaneAxisIndex } = slabConfig; @@ -90,9 +95,10 @@ describe("Tools:Surface", () => { const vacuumRatio = 0.5; const slabMaterial = generateSlabWithVacuum(slabConfig, vacuumRatio); const expectedSlabMaterial = new Material(SiSlab111); - const expectedMaterialJSON = expectedSlabMaterial.toJSON(); - const slabMaterialJSON = slabMaterial.toJSON(); - assertDeepAlmostEqual(expectedMaterialJSON, slabMaterialJSON); + assertDeepAlmostEqual( + toJSONWithoutHash(expectedSlabMaterial), + toJSONWithoutHash(slabMaterial), + ); }); it("should return slab (111) with vacuum for gamma = 60.001", () => { @@ -108,8 +114,9 @@ describe("Tools:Surface", () => { const vacuumRatio = 0.5; const slabMaterial = generateSlabWithVacuum(slabConfig, vacuumRatio); const expectedSlabMaterial = new Material(SiSlab111); - const expectedMaterialJSON = expectedSlabMaterial.toJSON(); - const slabMaterialJSON = slabMaterial.toJSON(); - assertDeepAlmostEqual(expectedMaterialJSON, slabMaterialJSON); + assertDeepAlmostEqual( + toJSONWithoutHash(expectedSlabMaterial), + toJSONWithoutHash(slabMaterial), + ); }); }); From 40764ebeebd3df0756be4784c7b903102b402f65 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 21 Jul 2026 15:56:25 +0300 Subject: [PATCH 06/13] feat: extract MaterialHashed with auto-refreshing hash Keep Material structure-only; persist and refresh hash on MaterialHashed via basis/lattice setters. --- dist/js/made.d.ts | 4 +- dist/js/made.js | 5 +- dist/js/material.d.ts | 6 +- dist/js/material.js | 13 +- dist/js/material_hashed.d.ts | 18 ++ dist/js/material_hashed.js | 40 ++++ package-lock.json | 398 ++++++++++++----------------------- package.json | 8 +- src/js/made.ts | 3 + src/js/material.ts | 18 +- src/js/material_hashed.ts | 62 ++++++ tests/js/fixtures.ts | 54 ++--- tests/js/material.test.ts | 58 ++++- tests/js/tools/surface.ts | 3 +- 14 files changed, 352 insertions(+), 338 deletions(-) create mode 100644 dist/js/material_hashed.d.ts create mode 100644 dist/js/material_hashed.js create mode 100644 src/js/material_hashed.ts diff --git a/dist/js/made.d.ts b/dist/js/made.d.ts index 9e7531b93..a5a81c9d0 100644 --- a/dist/js/made.d.ts +++ b/dist/js/made.d.ts @@ -7,6 +7,7 @@ import { DEFAULT_LATTICE_UNITS, LATTICE_TYPE_CONFIGS } from "./lattice/lattice_t import { ReciprocalLattice } from "./lattice/reciprocal/lattice_reciprocal"; import { UnitCell } from "./lattice/unit_cell"; import { defaultMaterialConfig, Material } from "./material"; +import { MaterialHashed } from "./material_hashed"; import parsers from "./parsers/parsers"; import tools from "./tools/index"; export declare const Made: { @@ -33,6 +34,7 @@ export declare const Made: { cartesian: string; }; Material: typeof Material; + MaterialHashed: typeof MaterialHashed; defaultMaterialConfig: import("./material").MaterialConfig; Lattice: typeof Lattice; Cell: typeof Cell; @@ -101,4 +103,4 @@ export declare const Made: { }; }; }; -export { coefficients, tolerance, units, ATOMIC_COORD_UNITS, Material, defaultMaterialConfig, Lattice, Cell, UnitCell, defaultNonPeriodicMinimumLatticeSize, diatomicLatticePaddingFactor, molecularLatticePaddingFactor, ReciprocalLattice, Basis, AtomicConstraints, parsers, tools, LATTICE_TYPE_CONFIGS, DEFAULT_LATTICE_UNITS, }; +export { coefficients, tolerance, units, ATOMIC_COORD_UNITS, Material, MaterialHashed, defaultMaterialConfig, Lattice, Cell, UnitCell, defaultNonPeriodicMinimumLatticeSize, diatomicLatticePaddingFactor, molecularLatticePaddingFactor, ReciprocalLattice, Basis, AtomicConstraints, parsers, tools, LATTICE_TYPE_CONFIGS, DEFAULT_LATTICE_UNITS, }; diff --git a/dist/js/made.js b/dist/js/made.js index 2c836f299..bd00ffffa 100644 --- a/dist/js/made.js +++ b/dist/js/made.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.DEFAULT_LATTICE_UNITS = exports.LATTICE_TYPE_CONFIGS = exports.tools = exports.parsers = exports.AtomicConstraints = exports.Basis = exports.ReciprocalLattice = exports.molecularLatticePaddingFactor = exports.diatomicLatticePaddingFactor = exports.defaultNonPeriodicMinimumLatticeSize = exports.UnitCell = exports.Cell = exports.Lattice = exports.defaultMaterialConfig = exports.Material = exports.ATOMIC_COORD_UNITS = exports.units = exports.tolerance = exports.coefficients = exports.Made = void 0; +exports.DEFAULT_LATTICE_UNITS = exports.LATTICE_TYPE_CONFIGS = exports.tools = exports.parsers = exports.AtomicConstraints = exports.Basis = exports.ReciprocalLattice = exports.molecularLatticePaddingFactor = exports.diatomicLatticePaddingFactor = exports.defaultNonPeriodicMinimumLatticeSize = exports.UnitCell = exports.Cell = exports.Lattice = exports.defaultMaterialConfig = exports.MaterialHashed = exports.Material = exports.ATOMIC_COORD_UNITS = exports.units = exports.tolerance = exports.coefficients = exports.Made = void 0; const basis_1 = require("./basis/basis"); Object.defineProperty(exports, "Basis", { enumerable: true, get: function () { return basis_1.Basis; } }); const cell_1 = require("./cell/cell"); @@ -30,6 +30,8 @@ Object.defineProperty(exports, "UnitCell", { enumerable: true, get: function () const material_1 = require("./material"); Object.defineProperty(exports, "defaultMaterialConfig", { enumerable: true, get: function () { return material_1.defaultMaterialConfig; } }); Object.defineProperty(exports, "Material", { enumerable: true, get: function () { return material_1.Material; } }); +const material_hashed_1 = require("./material_hashed"); +Object.defineProperty(exports, "MaterialHashed", { enumerable: true, get: function () { return material_hashed_1.MaterialHashed; } }); const parsers_1 = __importDefault(require("./parsers/parsers")); exports.parsers = parsers_1.default; const index_1 = __importDefault(require("./tools/index")); @@ -40,6 +42,7 @@ exports.Made = { units: constants_1.units, ATOMIC_COORD_UNITS: constants_1.ATOMIC_COORD_UNITS, Material: material_1.Material, + MaterialHashed: material_hashed_1.MaterialHashed, defaultMaterialConfig: material_1.defaultMaterialConfig, Lattice: lattice_1.Lattice, Cell: cell_1.Cell, diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index d39898160..52ee528cc 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -1,6 +1,5 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; import { type Defaultable } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; -import { type HashedEntity } from "@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"; import { type HasMetadata } from "@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"; import { type NamedEntity } from "@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"; import type { AtomicConstraintsSchema, BasisSchema, ConsistencyCheck, DerivedPropertiesSchema, FileSourceSchema, LatticeSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; @@ -9,9 +8,9 @@ import { ConstrainedBasis } from "./basis/constrained_basis"; import { type MaterialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; export type PartialBy = Omit & Partial>; -export type MaterialConfig = PartialBy; +export type MaterialConfig = PartialBy; export declare const defaultMaterialConfig: MaterialConfig; -interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, HashedEntity, Required> { +interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, Required> { } declare class BaseMaterial extends InMemoryEntity { } @@ -22,7 +21,6 @@ declare class Material extends BaseMaterial implements MaterialSchema { private constraints; constructor(config: MaterialConfig, constraints?: AtomicConstraintsSchema); updateFormula(): void; - updateHash(): void; /** * @summary Returns the specific derived property (as specified by name) for a material. */ diff --git a/dist/js/material.js b/dist/js/material.js index e3e8ba2b2..e82581a91 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.Material = exports.defaultMaterialConfig = void 0; const entity_1 = require("@mat3ra/code/dist/js/entity"); const DefaultableMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"); -const HashedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"); const HasMetadataMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/HasMetadataMixin"); const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEntityMixin"); const crypto_js_1 = __importDefault(require("crypto-js")); @@ -72,7 +71,6 @@ class BaseMaterial extends entity_1.InMemoryEntity { (0, NamedEntityMixin_1.namedEntityMixin)(BaseMaterial.prototype); (0, DefaultableMixin_1.defaultableEntityMixin)(BaseMaterial); (0, HasMetadataMixin_1.hasMetadataMixin)(BaseMaterial.prototype); -(0, HashedEntityMixin_1.hashedEntityMixin)(BaseMaterial.prototype); class Material extends BaseMaterial { static get defaultConfig() { return exports.defaultMaterialConfig; @@ -86,28 +84,23 @@ class Material extends BaseMaterial { }; } constructor(config, constraints = []) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d; super({ ...config, formula: (_a = config.formula) !== null && _a !== void 0 ? _a : "", name: (_c = (_b = config.name) !== null && _b !== void 0 ? _b : config.formula) !== null && _c !== void 0 ? _c : "", metadata: (_d = config.metadata) !== null && _d !== void 0 ? _d : {}, - hash: (_e = config.hash) !== null && _e !== void 0 ? _e : "", }); this.constraints = []; this.formula = config.formula || this.getBasis().formula; this.name = this.name || this.formula; this.constraints = constraints; - this.hash = (_f = config.hash) !== null && _f !== void 0 ? _f : this.calculateHash("", false, this.isNonPeriodic); } updateFormula() { const basis = this.getBasis(); this.formula = basis.formula; this.unitCellFormula = basis.unitCellFormula; } - updateHash() { - this.hash = this.calculateHash("", false, this.isNonPeriodic); - } /** * @summary Returns the specific derived property (as specified by name) for a material. */ @@ -132,7 +125,6 @@ class Material extends BaseMaterial { this.constraints = constraints; this.unsetFileProps(); this.updateFormula(); - this.updateHash(); } getBasis(constraints) { const basisData = this.basis; @@ -153,7 +145,6 @@ class Material extends BaseMaterial { this.basis = basis.toJSON(); this.lattice = lattice; this.unsetFileProps(); - this.updateHash(); } getLattice() { return new lattice_1.Lattice(this.lattice); @@ -206,7 +197,6 @@ class Material extends BaseMaterial { */ toCrystal(constraints = []) { this.basis = this.getBasis(constraints).toCrystal().toJSON(); - this.updateHash(); } /** * Converts current material's basis coordinates to cartesian. @@ -214,7 +204,6 @@ class Material extends BaseMaterial { */ toCartesian(constraints = []) { this.basis = this.getBasis(constraints).toCartesian().toJSON(); - this.updateHash(); } /** * Returns material's basis in XYZ format. diff --git a/dist/js/material_hashed.d.ts b/dist/js/material_hashed.d.ts new file mode 100644 index 000000000..293e01b75 --- /dev/null +++ b/dist/js/material_hashed.d.ts @@ -0,0 +1,18 @@ +import { type HashedSchemaMixin } from "@mat3ra/code/dist/js/generated/HashedSchemaMixin"; +import type { AtomicConstraintsSchema, MaterialHashedSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { type PartialBy, Material } from "./material"; +export type MaterialHashedConfig = PartialBy; +interface MaterialHashed extends HashedSchemaMixin { +} +declare class MaterialHashed extends Material implements MaterialHashedSchema { + static createDefault: () => MaterialHashed; + static get defaultConfig(): MaterialHashedConfig; + constructor(config: MaterialHashedConfig, constraints?: AtomicConstraintsSchema); + get basis(): MaterialSchema["basis"]; + set basis(value: MaterialSchema["basis"]); + get lattice(): MaterialSchema["lattice"]; + set lattice(value: MaterialSchema["lattice"]); + updateHash(): void; + toJSON(): MaterialHashedSchema; +} +export { MaterialHashed }; diff --git a/dist/js/material_hashed.js b/dist/js/material_hashed.js new file mode 100644 index 000000000..78ea0940f --- /dev/null +++ b/dist/js/material_hashed.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MaterialHashed = void 0; +const HashedSchemaMixin_1 = require("@mat3ra/code/dist/js/generated/HashedSchemaMixin"); +const material_1 = require("./material"); +class MaterialHashed extends material_1.Material { + static get defaultConfig() { + return material_1.defaultMaterialConfig; + } + constructor(config, constraints = []) { + var _a; + super(config, constraints); + this.hash = (_a = config.hash) !== null && _a !== void 0 ? _a : this.calculateHash("", false, this.isNonPeriodic); + } + get basis() { + return super.basis; + } + set basis(value) { + super.basis = value; + this.updateHash(); + } + get lattice() { + return super.lattice; + } + set lattice(value) { + super.lattice = value; + this.updateHash(); + } + updateHash() { + this.hash = this.calculateHash("", false, this.isNonPeriodic); + } + toJSON() { + return { + ...super.toJSON(), + hash: this.hash, + }; + } +} +exports.MaterialHashed = MaterialHashed; +(0, HashedSchemaMixin_1.hashedSchemaMixin)(MaterialHashed.prototype); diff --git a/package-lock.json b/package-lock.json index 4d227ebc6..e52be6f77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "@babel/runtime-corejs3": "^7.29.7", "@exabyte-io/eslint-config": "^2026.7.3-0", "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", - "@mat3ra/esse": "https://github.com/mat3ra/esse/tarball/55306425f1d697aa150ee5ed8cf5cbca3cfa5b5e", + "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", "@mat3ra/standata": "2026.6.30-0", "@mat3ra/tsconfig": "^2024.6.3-0", "@mat3ra/utils": "^2026.7.8-0", @@ -73,6 +73,7 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -547,6 +548,7 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -2388,6 +2390,7 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -2407,6 +2410,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2422,6 +2426,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -2430,6 +2435,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -2444,6 +2450,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, "engines": { "node": ">= 4" } @@ -2452,6 +2459,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2463,12 +2471,14 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@eslint/eslintrc/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "node_modules/@exabyte-io/eslint-config": { "version": "2026.7.3-0", @@ -2835,6 +2845,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", "deprecated": "Use @eslint/config-array instead", + "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -2848,7 +2859,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "deprecated": "Use @eslint/object-schema instead" + "deprecated": "Use @eslint/object-schema instead", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -3114,8 +3126,8 @@ }, "node_modules/@mat3ra/esse": { "version": "0.0.0", - "resolved": "https://github.com/mat3ra/esse/tarball/55306425f1d697aa150ee5ed8cf5cbca3cfa5b5e", - "integrity": "sha512-mNhZHlyPR1oIh1sLAFKICO8DHGhb08fGUVreMf5R1E7aGXAlcCx6sf8HnCt7uwqX+p9dg/qJQIr1eByJQL7Pwg==", + "resolved": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", + "integrity": "sha512-4+EIEjuwWLZr5eme1jzw21ofZITz1y73whwRRUJVqp+kIzjOCnIkoDskwK8R5gRIzKhx9oZJXBJvJYNQdOwOBA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3756,20 +3768,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/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4180,6 +4178,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -4213,6 +4212,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", @@ -4256,6 +4256,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "engines": { "node": ">=6" } @@ -4291,6 +4292,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -4299,6 +4301,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -4563,6 +4566,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, "engines": { "node": ">=8" } @@ -4849,6 +4853,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -4939,6 +4944,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5213,6 +5219,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -5220,7 +5227,8 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/colorette": { "version": "2.0.20", @@ -5345,6 +5353,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5485,7 +5494,8 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "node_modules/default-require-extensions": { "version": "3.0.1", @@ -5563,17 +5573,6 @@ "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", @@ -5590,6 +5589,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -5627,12 +5627,14 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5863,6 +5865,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -5872,6 +5875,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -5924,37 +5928,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.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-config-airbnb": { "version": "19.0.4", "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", @@ -6088,29 +6061,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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.14.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", @@ -6270,67 +6220,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "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/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.10.2", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", @@ -6437,20 +6326,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "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", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -6523,6 +6398,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -6537,6 +6413,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, "engines": { "node": ">=4" } @@ -6553,6 +6430,7 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, "dependencies": { "@babel/highlight": "^7.10.4" } @@ -6561,6 +6439,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6576,6 +6455,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -6590,6 +6470,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -6598,6 +6479,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6613,6 +6495,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -6623,12 +6506,14 @@ "node_modules/eslint/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -6640,6 +6525,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -6654,6 +6540,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -6662,6 +6549,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, "engines": { "node": ">= 4" } @@ -6670,6 +6558,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -6681,12 +6570,14 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/eslint/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -6698,6 +6589,7 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -6711,12 +6603,14 @@ "node_modules/eslint/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6727,12 +6621,14 @@ "node_modules/eslint/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, "dependencies": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -6746,6 +6642,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -6757,6 +6654,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, "engines": { "node": ">=4" } @@ -6765,6 +6663,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -6777,6 +6676,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -6789,6 +6689,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -6854,7 +6755,8 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-diff": { "version": "1.3.0", @@ -6882,17 +6784,20 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, "funding": [ { "type": "github", @@ -6917,6 +6822,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -6973,6 +6879,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -6985,7 +6892,8 @@ "node_modules/flatted": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.0.tgz", - "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==" + "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==", + "dev": true }, "node_modules/for-each": { "version": "0.3.5", @@ -7109,7 +7017,8 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true }, "node_modules/functions-have-names": { "version": "1.2.3", @@ -7259,6 +7168,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -7363,6 +7273,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { "node": ">=4" } @@ -7505,6 +7416,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7520,6 +7432,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { "node": ">=0.8.19" } @@ -7735,6 +7648,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -7759,6 +7673,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -7787,6 +7702,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8105,7 +8021,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isobject": { "version": "3.0.1", @@ -8374,7 +8291,8 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-schema": { "version": "0.4.0", @@ -8468,12 +8386,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -8486,73 +8406,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/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.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -8572,6 +8425,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -8608,6 +8462,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -8799,12 +8654,14 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", @@ -9311,7 +9168,8 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "node_modules/natural-compare-lite": { "version": "1.4.0", @@ -9853,6 +9711,7 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -9950,6 +9809,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -9977,6 +9837,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -10074,6 +9935,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -10122,6 +9984,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -10141,6 +10004,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "engines": { "node": ">=6" } @@ -10266,6 +10130,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, "engines": { "node": ">=8" }, @@ -10342,6 +10207,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10386,6 +10252,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "engines": { "node": ">=4" } @@ -10433,6 +10300,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -10652,6 +10520,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -10663,6 +10532,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -10761,6 +10631,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -10777,6 +10648,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -10791,6 +10663,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -10801,7 +10674,8 @@ "node_modules/slice-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/source-map": { "version": "0.6.1", @@ -10915,6 +10789,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -11042,6 +10917,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11072,6 +10948,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -11083,6 +10960,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -11101,27 +10979,11 @@ "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.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -11150,7 +11012,8 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/through": { "version": "2.3.8", @@ -11343,6 +11206,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -11364,6 +11228,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -11599,6 +11464,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -11620,7 +11486,8 @@ "node_modules/v8-compile-cache": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", - "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==" + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", @@ -11675,6 +11542,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, diff --git a/package.json b/package.json index a6b173066..a2754c2ea 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,10 @@ "@babel/runtime-corejs3": "^7.29.7", "@exabyte-io/eslint-config": "^2026.7.3-0", "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", - "@mat3ra/esse": "https://github.com/mat3ra/esse/tarball/55306425f1d697aa150ee5ed8cf5cbca3cfa5b5e", + "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", + "@mat3ra/standata": "2026.6.30-0", "@mat3ra/tsconfig": "^2024.6.3-0", "@mat3ra/utils": "^2026.7.8-0", - "@mat3ra/standata": "2026.6.30-0", "@types/crypto-js": "^4.2.2", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", @@ -60,8 +60,8 @@ "husky": "^7.0.4", "lint-staged": "^12.5.0", "mocha": "10.8.2", - "prettier": "^2.8.8", - "nyc": "^15.1.0" + "nyc": "^15.1.0", + "prettier": "^2.8.8" }, "dependencies": { "@babel/core": "^7.29.7", diff --git a/src/js/made.ts b/src/js/made.ts index e16a79e49..998af2d2b 100644 --- a/src/js/made.ts +++ b/src/js/made.ts @@ -12,6 +12,7 @@ import { DEFAULT_LATTICE_UNITS, LATTICE_TYPE_CONFIGS } from "./lattice/lattice_t import { ReciprocalLattice } from "./lattice/reciprocal/lattice_reciprocal"; import { UnitCell } from "./lattice/unit_cell"; import { defaultMaterialConfig, Material } from "./material"; +import { MaterialHashed } from "./material_hashed"; import parsers from "./parsers/parsers"; import tools from "./tools/index"; @@ -22,6 +23,7 @@ export const Made = { ATOMIC_COORD_UNITS, Material, + MaterialHashed, defaultMaterialConfig, Lattice, Cell, @@ -45,6 +47,7 @@ export { units, ATOMIC_COORD_UNITS, Material, + MaterialHashed, defaultMaterialConfig, Lattice, Cell, diff --git a/src/js/material.ts b/src/js/material.ts index 272b21c01..dbfe263a1 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -3,10 +3,6 @@ import { type Defaultable, defaultableEntityMixin, } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin"; -import { - type HashedEntity, - hashedEntityMixin, -} from "@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin"; import { type HasMetadata, hasMetadataMixin, @@ -55,7 +51,7 @@ function parseBasis( export type PartialBy = Omit & Partial>; -export type MaterialConfig = PartialBy; +export type MaterialConfig = PartialBy; export const defaultMaterialConfig: MaterialConfig = { name: "Silicon FCC", @@ -103,7 +99,6 @@ interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, - HashedEntity, Required> {} class BaseMaterial extends InMemoryEntity {} @@ -112,7 +107,6 @@ materialSchemaMixin(BaseMaterial.prototype); namedEntityMixin(BaseMaterial.prototype); defaultableEntityMixin(BaseMaterial); hasMetadataMixin(BaseMaterial.prototype); -hashedEntityMixin(BaseMaterial.prototype); class Material extends BaseMaterial implements MaterialSchema { declare static createDefault: () => Material; @@ -142,13 +136,11 @@ class Material extends BaseMaterial implements MaterialSchema { formula: config.formula ?? "", name: config.name ?? config.formula ?? "", metadata: config.metadata ?? {}, - hash: config.hash ?? "", }); this.formula = config.formula || this.getBasis().formula; this.name = this.name || this.formula; this.constraints = constraints; - this.hash = config.hash ?? this.calculateHash("", false, this.isNonPeriodic); } updateFormula() { @@ -157,10 +149,6 @@ class Material extends BaseMaterial implements MaterialSchema { this.unitCellFormula = basis.unitCellFormula; } - updateHash() { - this.hash = this.calculateHash("", false, this.isNonPeriodic); - } - /** * @summary Returns the specific derived property (as specified by name) for a material. */ @@ -192,7 +180,6 @@ class Material extends BaseMaterial implements MaterialSchema { this.constraints = constraints; this.unsetFileProps(); this.updateFormula(); - this.updateHash(); } getBasis(constraints?: AtomicConstraintsSchema) { @@ -220,7 +207,6 @@ class Material extends BaseMaterial implements MaterialSchema { this.lattice = lattice; this.unsetFileProps(); - this.updateHash(); } getLattice() { @@ -277,7 +263,6 @@ class Material extends BaseMaterial implements MaterialSchema { */ toCrystal(constraints: AtomicConstraintsSchema = []) { this.basis = this.getBasis(constraints).toCrystal().toJSON(); - this.updateHash(); } /** @@ -286,7 +271,6 @@ class Material extends BaseMaterial implements MaterialSchema { */ toCartesian(constraints: AtomicConstraintsSchema = []) { this.basis = this.getBasis(constraints).toCartesian().toJSON(); - this.updateHash(); } /** diff --git a/src/js/material_hashed.ts b/src/js/material_hashed.ts new file mode 100644 index 000000000..b7397e523 --- /dev/null +++ b/src/js/material_hashed.ts @@ -0,0 +1,62 @@ +import { + type HashedSchemaMixin, + hashedSchemaMixin, +} from "@mat3ra/code/dist/js/generated/HashedSchemaMixin"; +import type { + AtomicConstraintsSchema, + MaterialHashedSchema, + MaterialSchema, +} from "@mat3ra/esse/dist/js/types"; + +import { type PartialBy, defaultMaterialConfig, Material } from "./material"; + +export type MaterialHashedConfig = PartialBy; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface MaterialHashed extends HashedSchemaMixin {} + +class MaterialHashed extends Material implements MaterialHashedSchema { + declare static createDefault: () => MaterialHashed; + + static get defaultConfig(): MaterialHashedConfig { + return defaultMaterialConfig; + } + + constructor(config: MaterialHashedConfig, constraints: AtomicConstraintsSchema = []) { + super(config, constraints); + this.hash = config.hash ?? this.calculateHash("", false, this.isNonPeriodic); + } + + get basis(): MaterialSchema["basis"] { + return super.basis; + } + + set basis(value: MaterialSchema["basis"]) { + super.basis = value; + this.updateHash(); + } + + get lattice(): MaterialSchema["lattice"] { + return super.lattice; + } + + set lattice(value: MaterialSchema["lattice"]) { + super.lattice = value; + this.updateHash(); + } + + updateHash() { + this.hash = this.calculateHash("", false, this.isNonPeriodic); + } + + toJSON(): MaterialHashedSchema { + return { + ...super.toJSON(), + hash: this.hash, + } as MaterialHashedSchema; + } +} + +hashedSchemaMixin(MaterialHashed.prototype); + +export { MaterialHashed }; diff --git a/tests/js/fixtures.ts b/tests/js/fixtures.ts index 697c34323..3cbeeea47 100644 --- a/tests/js/fixtures.ts +++ b/tests/js/fixtures.ts @@ -1,4 +1,8 @@ -import { AtomicConstraintsSchema, BasisSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { + AtomicConstraintsSchema, + BasisSchema, + MaterialHashedSchema, +} from "@mat3ra/esse/dist/js/types"; import { MaterialStandata } from "@mat3ra/standata"; import fs from "fs"; import path from "path"; @@ -9,7 +13,6 @@ import C2H4_JSON from "../fixtures/C2H4.json"; import C2H4Translated_JSON from "../fixtures/C2H4-translated.json"; import FeLiSiBasis_JSON from "../fixtures/FeLiSi-basis.json"; import FeO_JSON from "../fixtures/FeO.json"; - import Ge2Basis_JSON from "../fixtures/Ge2-basis.json"; import Graphene_JSON from "../fixtures/Graphene.json"; import H2HFinal_JSON from "../fixtures/H2+H-final.json"; @@ -28,35 +31,34 @@ import SiSlab111Gamma120_JSON from "../fixtures/si-slab-111-0.5-vacuum-gamma-120 import SiSlab111_JSON from "../fixtures/si-slab-111-0.5-vacuum-ratio.json"; import SiSlab111NoVacuum_JSON from "../fixtures/si-slab-111-0-vacuum.json"; import Silicon_JSON from "../fixtures/si-standata.json"; - import SiSupercell_JSON from "../fixtures/Si-supercell.json"; import Si2Basis_JSON from "../fixtures/Si2-basis.json"; import Si2BasisRepeated_JSON from "../fixtures/Si2-basis-repeated.json"; import Zr1H23Zr1H1_JSON from "../fixtures/Zr1H23Zr1H1.json"; -// Material -const Silicon = Silicon_JSON as unknown as MaterialSchema; -const SiSupercell = SiSupercell_JSON as unknown as MaterialSchema; -const SiSlab = SiSlab_JSON as unknown as MaterialSchema; -const SiSlab100 = SiSlab100_JSON as unknown as MaterialSchema; -const SiSlab111 = SiSlab111_JSON as unknown as MaterialSchema; -const SiSlab111Gamma120 = SiSlab111Gamma120_JSON as unknown as MaterialSchema; -const SiSlab111NoVacuum = SiSlab111NoVacuum_JSON as unknown as MaterialSchema; -const FeO = FeO_JSON as unknown as MaterialSchema; -const FeOStandata = MaterialStandata.getRuntimeDataConfigs().find( - (m: any) => m.name?.includes("FeO"), -) as MaterialSchema; -const Na4Cl4 = Na4Cl4_JSON as unknown as MaterialSchema; -const Na4Cl4Cartesian = Na4Cl4Cartesian_JSON as unknown as MaterialSchema; -const C2H4 = C2H4_JSON as unknown as MaterialSchema; -const C2H4Translated = C2H4Translated_JSON as unknown as MaterialSchema; -const Na = Na_JSON as unknown as MaterialSchema; -const H2HInitial = H2HInitial_JSON as unknown as MaterialSchema; -const H2HFinal = H2HFinal_JSON as unknown as MaterialSchema; -const H2HImage = H2HImage_JSON as unknown as MaterialSchema; -const Zr1H23Zr1H1 = Zr1H23Zr1H1_JSON as unknown as MaterialSchema; -const Graphene = Graphene_JSON as unknown as MaterialSchema; -const NiHex = NiHex_JSON as unknown as MaterialSchema; +// Material (fixtures include hash; typed as MaterialHashedSchema for hash assertions) +const Silicon = Silicon_JSON as unknown as MaterialHashedSchema; +const SiSupercell = SiSupercell_JSON as unknown as MaterialHashedSchema; +const SiSlab = SiSlab_JSON as unknown as MaterialHashedSchema; +const SiSlab100 = SiSlab100_JSON as unknown as MaterialHashedSchema; +const SiSlab111 = SiSlab111_JSON as unknown as MaterialHashedSchema; +const SiSlab111Gamma120 = SiSlab111Gamma120_JSON as unknown as MaterialHashedSchema; +const SiSlab111NoVacuum = SiSlab111NoVacuum_JSON as unknown as MaterialHashedSchema; +const FeO = FeO_JSON as unknown as MaterialHashedSchema; +const FeOStandata = MaterialStandata.getRuntimeDataConfigs().find((m: any) => + m.name?.includes("FeO"), +) as MaterialHashedSchema; +const Na4Cl4 = Na4Cl4_JSON as unknown as MaterialHashedSchema; +const Na4Cl4Cartesian = Na4Cl4Cartesian_JSON as unknown as MaterialHashedSchema; +const C2H4 = C2H4_JSON as unknown as MaterialHashedSchema; +const C2H4Translated = C2H4Translated_JSON as unknown as MaterialHashedSchema; +const Na = Na_JSON as unknown as MaterialHashedSchema; +const H2HInitial = H2HInitial_JSON as unknown as MaterialHashedSchema; +const H2HFinal = H2HFinal_JSON as unknown as MaterialHashedSchema; +const H2HImage = H2HImage_JSON as unknown as MaterialHashedSchema; +const Zr1H23Zr1H1 = Zr1H23Zr1H1_JSON as unknown as MaterialHashedSchema; +const Graphene = Graphene_JSON as unknown as MaterialHashedSchema; +const NiHex = NiHex_JSON as unknown as MaterialHashedSchema; // Basis const Si2Basis = Si2Basis_JSON as BasisSchema; diff --git a/tests/js/material.test.ts b/tests/js/material.test.ts index 1f3685afc..b6810d883 100644 --- a/tests/js/material.test.ts +++ b/tests/js/material.test.ts @@ -1,6 +1,8 @@ import { expect } from "chai"; import { Material } from "../../src/js/material"; +import { MaterialHashed } from "../../src/js/material_hashed"; +import expectedHashes from "../fixtures/hashes.json"; import { FeOStandata, Graphene, Na4Cl4, Silicon } from "./fixtures"; const newBasisXYZ = `Si 0.000000 0.000000 0.000000 @@ -19,24 +21,68 @@ describe("Material", () => { clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.getBasis().units); expect(clonedMaterial.getBasis().elements).to.have.lengthOf(2); }); +}); +describe("MaterialHashed", () => { describe("calculateHash", () => { [ { name: "Silicon", fixture: Silicon }, { name: "Graphene", fixture: Graphene }, ].forEach(({ name, fixture }) => { it(`should match expected hash for ${name}`, () => { - const material = new Material(fixture); - expect(material.calculateHash()).to.equal((fixture as any).hash); - expect(material.scaledHash).to.equal((fixture as any).scaledHash); + const material = new MaterialHashed(fixture); + expect(material.calculateHash()).to.equal(fixture.hash); + expect(material.scaledHash).to.equal(fixture.scaledHash); }); }); it("should match expected hash for FeO (standata)", () => { - const expectedHashes = require("../../fixtures/hashes.json"); - const material = new Material(FeOStandata); + const material = new MaterialHashed(FeOStandata); expect(material.calculateHash()).to.equal(expectedHashes.FeO.hash); - expect(material.scaledHash).to.equal(expectedHashes.FeO.scaledHash); + expect(material.calculateHash("", true)).to.equal(expectedHashes.FeO.scaledHash); + }); + + it("should persist hash on the instance and refresh after mutation", () => { + const material = new MaterialHashed(Silicon); + expect(material.hash).to.equal(Silicon.hash); + material.setBasis(newBasisXYZ, "xyz", material.getBasis().units); + expect(material.hash).to.equal(material.calculateHash()); + expect(material.hash).to.not.equal(Silicon.hash); + }); + + it("should refresh hash when basis or lattice setters are used directly", () => { + const material = new MaterialHashed(Silicon); + const previousHash = material.hash; + + material.basis = { + ...material.basis, + elements: [ + { id: 0, value: "Si" }, + { id: 1, value: "Ge" }, + ], + }; + expect(material.hash).to.equal(material.calculateHash()); + expect(material.hash).to.not.equal(previousHash); + + const hashAfterBasisChange = material.hash; + material.lattice = { + ...material.lattice, + a: material.lattice.a + 0.1, + }; + expect(material.hash).to.equal(material.calculateHash()); + expect(material.hash).to.not.equal(hashAfterBasisChange); + }); + + it("should refresh hash after setLattice", () => { + const material = new MaterialHashed(Silicon); + const previousHash = material.hash; + + material.setLattice({ + ...material.lattice, + a: material.lattice.a + 0.1, + }); + expect(material.hash).to.equal(material.calculateHash()); + expect(material.hash).to.not.equal(previousHash); }); }); }); diff --git a/tests/js/tools/surface.ts b/tests/js/tools/surface.ts index 7041db1b5..93b1bba21 100644 --- a/tests/js/tools/surface.ts +++ b/tests/js/tools/surface.ts @@ -9,8 +9,7 @@ import { Silicon, SiSlab100, SiSlab111, SiSlab111NoVacuum } from "../fixtures"; const { assertDeepAlmostEqual } = Utils.assertion; const toJSONWithoutHash = (material: Material) => { - const { hash: _, ...json } = material.toJSON(); - return json; + return material.toJSON(); }; const generateSlabWithVacuum = (slabConfig: SlabConfigSchema, vacuumRatio: number) => { From da062de833505c3aae9ca15d248410005676f9f2 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 21 Jul 2026 20:36:32 +0300 Subject: [PATCH 07/13] chore: make Material/MaterialHashed schema-generic Allow web-app Core* subclasses to widen schema via MaterialHashed without redeclaring _json. Pin @mat3ra/code for NoInfer on InMemoryEntity. Co-authored-by: Cursor --- dist/js/made.d.ts | 6 +++--- dist/js/material.d.ts | 13 +++++++------ dist/js/material.js | 1 + dist/js/material_hashed.d.ts | 9 +++++---- dist/js/material_hashed.js | 11 ++++++++--- dist/js/tools/index.d.ts | 4 ++-- dist/js/tools/supercell.d.ts | 4 ++-- dist/js/tools/surface.d.ts | 4 ++-- package-lock.json | 6 +++--- package.json | 2 +- src/js/material.ts | 19 +++++++++++-------- src/js/material_hashed.ts | 30 +++++++++++++++++++++++------- src/js/tools/supercell.ts | 12 +++++++++--- src/js/tools/surface.ts | 11 ++++++++--- tests/js/material.test.ts | 21 +++++++++++++++++++++ 15 files changed, 106 insertions(+), 47 deletions(-) diff --git a/dist/js/made.d.ts b/dist/js/made.d.ts index a5a81c9d0..e3acc2fdc 100644 --- a/dist/js/made.d.ts +++ b/dist/js/made.d.ts @@ -35,7 +35,7 @@ export declare const Made: { }; Material: typeof Material; MaterialHashed: typeof MaterialHashed; - defaultMaterialConfig: import("./material").MaterialConfig; + defaultMaterialConfig: import("./material").MaterialConfig; Lattice: typeof Lattice; Cell: typeof Cell; UnitCell: typeof UnitCell; @@ -73,10 +73,10 @@ export declare const Made: { }; tools: { surface: { - generateConfig: (material: Material, millerIndices: import("@mat3ra/esse/dist/js/types").Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number) => import("./tools/surface").SlabConfigSchema; + generateConfig: (material: Material, millerIndices: import("@mat3ra/esse/dist/js/types").Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number) => import("./tools/surface").SlabConfigSchema; }; supercell: { - generateConfig: (material: Material, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => { + generateConfig: (material: Material, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => { name: string; basis: import("@mat3ra/esse/dist/js/types").BasisSchema; lattice: import("@mat3ra/esse/dist/js/types").LatticeSchema; diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index 52ee528cc..95ea3ee5d 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -8,18 +8,19 @@ import { ConstrainedBasis } from "./basis/constrained_basis"; import { type MaterialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; export type PartialBy = Omit & Partial>; -export type MaterialConfig = PartialBy; +type Schema = MaterialSchema; +export type MaterialConfig = PartialBy; export declare const defaultMaterialConfig: MaterialConfig; -interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, Required> { +interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, Required> { } -declare class BaseMaterial extends InMemoryEntity { +declare class BaseMaterial extends InMemoryEntity { } -declare class Material extends BaseMaterial implements MaterialSchema { +declare class Material extends BaseMaterial implements Schema { static createDefault: () => Material; static get defaultConfig(): MaterialConfig; static constructMaterialFileSource(fileName: string, fileContent: string, fileExtension: string): FileSourceSchema; private constraints; - constructor(config: MaterialConfig, constraints?: AtomicConstraintsSchema); + constructor(config: NoInfer>, constraints?: AtomicConstraintsSchema); updateFormula(): void; /** * @summary Returns the specific derived property (as specified by name) for a material. @@ -131,6 +132,6 @@ declare class Material extends BaseMaterial implements MaterialSchema { * @returns Array of checks results */ getBasisConsistencyChecks(): ConsistencyCheck[]; - toJSON(): MaterialSchema; + toJSON(): S; } export { Material }; diff --git a/dist/js/material.js b/dist/js/material.js index e82581a91..6255ee850 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -83,6 +83,7 @@ class Material extends BaseMaterial { hash: crypto_js_1.default.MD5(fileContent).toString(), }; } + // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. constructor(config, constraints = []) { var _a, _b, _c, _d; super({ diff --git a/dist/js/material_hashed.d.ts b/dist/js/material_hashed.d.ts index 293e01b75..4b9a81781 100644 --- a/dist/js/material_hashed.d.ts +++ b/dist/js/material_hashed.d.ts @@ -1,18 +1,19 @@ import { type HashedSchemaMixin } from "@mat3ra/code/dist/js/generated/HashedSchemaMixin"; import type { AtomicConstraintsSchema, MaterialHashedSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { type PartialBy, Material } from "./material"; -export type MaterialHashedConfig = PartialBy; +type Schema = MaterialHashedSchema; +export type MaterialHashedConfig = PartialBy; interface MaterialHashed extends HashedSchemaMixin { } -declare class MaterialHashed extends Material implements MaterialHashedSchema { +declare class MaterialHashed extends Material implements Schema { static createDefault: () => MaterialHashed; static get defaultConfig(): MaterialHashedConfig; - constructor(config: MaterialHashedConfig, constraints?: AtomicConstraintsSchema); + constructor(config: NoInfer>, constraints?: AtomicConstraintsSchema); get basis(): MaterialSchema["basis"]; set basis(value: MaterialSchema["basis"]); get lattice(): MaterialSchema["lattice"]; set lattice(value: MaterialSchema["lattice"]); updateHash(): void; - toJSON(): MaterialHashedSchema; + toJSON(): S; } export { MaterialHashed }; diff --git a/dist/js/material_hashed.js b/dist/js/material_hashed.js index 78ea0940f..c3f805b4b 100644 --- a/dist/js/material_hashed.js +++ b/dist/js/material_hashed.js @@ -7,10 +7,15 @@ class MaterialHashed extends material_1.Material { static get defaultConfig() { return material_1.defaultMaterialConfig; } + // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. constructor(config, constraints = []) { - var _a; - super(config, constraints); - this.hash = (_a = config.hash) !== null && _a !== void 0 ? _a : this.calculateHash("", false, this.isNonPeriodic); + var _a, _b; + // MaterialConfig still requires hash; use a placeholder until calculateHash can run. + super({ + ...config, + hash: (_a = config.hash) !== null && _a !== void 0 ? _a : "", + }, constraints); + this.hash = (_b = config.hash) !== null && _b !== void 0 ? _b : this.calculateHash("", false, this.isNonPeriodic); } get basis() { return super.basis; diff --git a/dist/js/tools/index.d.ts b/dist/js/tools/index.d.ts index 0b4db4823..e0d30ae99 100644 --- a/dist/js/tools/index.d.ts +++ b/dist/js/tools/index.d.ts @@ -1,9 +1,9 @@ declare const _default: { surface: { - generateConfig: (material: import("../material").Material, millerIndices: import("@mat3ra/esse/dist/js/types").Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number) => import("./surface").SlabConfigSchema; + generateConfig: (material: import("../material").Material, millerIndices: import("@mat3ra/esse/dist/js/types").Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number) => import("./surface").SlabConfigSchema; }; supercell: { - generateConfig: (material: import("../material").Material, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => { + generateConfig: (material: import("../material").Material, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => { name: string; basis: import("@mat3ra/esse/dist/js/types").BasisSchema; lattice: import("@mat3ra/esse/dist/js/types").LatticeSchema; diff --git a/dist/js/tools/supercell.d.ts b/dist/js/tools/supercell.d.ts index 60e3f021a..52b158c78 100644 --- a/dist/js/tools/supercell.d.ts +++ b/dist/js/tools/supercell.d.ts @@ -1,4 +1,4 @@ -import { Matrix3X3Schema } from "@mat3ra/esse/dist/js/types"; +import { type MaterialSchema, Matrix3X3Schema } from "@mat3ra/esse/dist/js/types"; import { Basis } from "../basis/basis"; import { ConstrainedBasis } from "../basis/constrained_basis"; import { Cell } from "../cell/cell"; @@ -10,7 +10,7 @@ declare function generateNewBasisWithinSupercell(basis: Basis | ConstrainedBasis /** * @summary Generates supercell config for the specified material. */ -declare function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema): { +declare function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema): { name: string; basis: import("@mat3ra/esse/dist/js/types").BasisSchema; lattice: import("@mat3ra/esse/dist/js/types").LatticeSchema; diff --git a/dist/js/tools/surface.d.ts b/dist/js/tools/surface.d.ts index 553721333..7f2184520 100644 --- a/dist/js/tools/surface.d.ts +++ b/dist/js/tools/surface.d.ts @@ -1,9 +1,9 @@ -import { Coordinate3DSchema } from "@mat3ra/esse/dist/js/types"; +import { type MaterialSchema, Coordinate3DSchema } from "@mat3ra/esse/dist/js/types"; import { type MaterialConfig, Material } from "../material"; export type SlabConfigSchema = MaterialConfig & { outOfPlaneAxisIndex: number; }; -declare function generateConfig(material: Material, millerIndices: Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number): SlabConfigSchema; +declare function generateConfig(material: Material, millerIndices: Coordinate3DSchema, numberOfLayers?: number, vx?: number, vy?: number): SlabConfigSchema; declare const _default: { generateConfig: typeof generateConfig; }; diff --git a/package-lock.json b/package-lock.json index e52be6f77..a4c3422c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "@babel/register": "^7.29.7", "@babel/runtime-corejs3": "^7.29.7", "@exabyte-io/eslint-config": "^2026.7.3-0", - "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/ef877b55067afef34e492b8c2b317a1bb2cb8298.tar.gz", "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", "@mat3ra/standata": "2026.6.30-0", "@mat3ra/tsconfig": "^2024.6.3-0", @@ -3032,8 +3032,8 @@ }, "node_modules/@mat3ra/code": { "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", - "integrity": "sha512-d50ie+SFn2jZIpIdGzdcx8olP35+zV+PMablDj1yTQcHho/A+9vOXibp405PGjcYCMr53TvzOm4IlrGWveQEMg==", + "resolved": "https://github.com/Exabyte-io/code/archive/ef877b55067afef34e492b8c2b317a1bb2cb8298.tar.gz", + "integrity": "sha512-Qdu973CjIwHZOGoVqyLv1Jo9+BUusfpYGWWUeohjryZlDYx4r6J3qL1DDG+RQxl+CcaYKiTktK5vs/roZaEaVw==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index a2754c2ea..d6618f3fc 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@babel/register": "^7.29.7", "@babel/runtime-corejs3": "^7.29.7", "@exabyte-io/eslint-config": "^2026.7.3-0", - "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/e5f03b02102f51a5792e0b8c4fedac3860aaf7ed.tar.gz", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/ef877b55067afef34e492b8c2b317a1bb2cb8298.tar.gz", "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", "@mat3ra/standata": "2026.6.30-0", "@mat3ra/tsconfig": "^2024.6.3-0", diff --git a/src/js/material.ts b/src/js/material.ts index dbfe263a1..12983b8f9 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -51,7 +51,9 @@ function parseBasis( export type PartialBy = Omit & Partial>; -export type MaterialConfig = PartialBy; +type Schema = MaterialSchema; + +export type MaterialConfig = PartialBy; export const defaultMaterialConfig: MaterialConfig = { name: "Silicon FCC", @@ -99,16 +101,16 @@ interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, - Required> {} + Required> {} -class BaseMaterial extends InMemoryEntity {} +class BaseMaterial extends InMemoryEntity {} materialSchemaMixin(BaseMaterial.prototype); namedEntityMixin(BaseMaterial.prototype); defaultableEntityMixin(BaseMaterial); hasMetadataMixin(BaseMaterial.prototype); -class Material extends BaseMaterial implements MaterialSchema { +class Material extends BaseMaterial implements Schema { declare static createDefault: () => Material; static get defaultConfig(): MaterialConfig { @@ -130,13 +132,14 @@ class Material extends BaseMaterial implements MaterialSchema { private constraints: AtomicConstraintsSchema = []; - constructor(config: MaterialConfig, constraints: AtomicConstraintsSchema = []) { + // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. + constructor(config: NoInfer>, constraints: AtomicConstraintsSchema = []) { super({ ...config, formula: config.formula ?? "", name: config.name ?? config.formula ?? "", metadata: config.metadata ?? {}, - }); + } as S); this.formula = config.formula || this.getBasis().formula; this.name = this.name || this.formula; @@ -381,7 +384,7 @@ class Material extends BaseMaterial implements MaterialSchema { return checks; } - toJSON(): MaterialSchema { + toJSON(): S { const lattice = this.getLattice(); const basis = this.getBasis(); @@ -390,7 +393,7 @@ class Material extends BaseMaterial implements MaterialSchema { lattice: lattice.toJSON(), basis: basis.toJSON(), isNonPeriodic: this.isNonPeriodic, - } as MaterialSchema; + } as S; } } diff --git a/src/js/material_hashed.ts b/src/js/material_hashed.ts index b7397e523..46bca5ed8 100644 --- a/src/js/material_hashed.ts +++ b/src/js/material_hashed.ts @@ -8,22 +8,38 @@ import type { MaterialSchema, } from "@mat3ra/esse/dist/js/types"; -import { type PartialBy, defaultMaterialConfig, Material } from "./material"; +import { type MaterialConfig, type PartialBy, defaultMaterialConfig, Material } from "./material"; -export type MaterialHashedConfig = PartialBy; +type Schema = MaterialHashedSchema; + +export type MaterialHashedConfig = PartialBy< + S, + "name" | "metadata" | "hash" +>; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface MaterialHashed extends HashedSchemaMixin {} -class MaterialHashed extends Material implements MaterialHashedSchema { +class MaterialHashed extends Material implements Schema { declare static createDefault: () => MaterialHashed; static get defaultConfig(): MaterialHashedConfig { return defaultMaterialConfig; } - constructor(config: MaterialHashedConfig, constraints: AtomicConstraintsSchema = []) { - super(config, constraints); + // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. + constructor( + config: NoInfer>, + constraints: AtomicConstraintsSchema = [], + ) { + // MaterialConfig still requires hash; use a placeholder until calculateHash can run. + super( + { + ...config, + hash: config.hash ?? "", + } as MaterialConfig, + constraints, + ); this.hash = config.hash ?? this.calculateHash("", false, this.isNonPeriodic); } @@ -49,11 +65,11 @@ class MaterialHashed extends Material implements MaterialHashedSchema { this.hash = this.calculateHash("", false, this.isNonPeriodic); } - toJSON(): MaterialHashedSchema { + toJSON(): S { return { ...super.toJSON(), hash: this.hash, - } as MaterialHashedSchema; + } as S; } } diff --git a/src/js/tools/supercell.ts b/src/js/tools/supercell.ts index 4c7ba5a7f..402644ea5 100644 --- a/src/js/tools/supercell.ts +++ b/src/js/tools/supercell.ts @@ -1,4 +1,8 @@ -import { Coordinate3DSchema, Matrix3X3Schema } from "@mat3ra/esse/dist/js/types"; +import { + type MaterialSchema, + Coordinate3DSchema, + Matrix3X3Schema, +} from "@mat3ra/esse/dist/js/types"; import { Utils } from "@mat3ra/utils"; import { Basis } from "../basis/basis"; @@ -8,7 +12,6 @@ import { Lattice } from "../lattice/lattice"; import type { Material } from "../material"; import cellTools from "./cell"; - const ADD = Utils.math.add; /** @@ -54,7 +57,10 @@ function generateNewBasisWithinSupercell( /** * @summary Generates supercell config for the specified material. */ -function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema) { +function generateConfig( + material: Material, + supercellMatrix: Matrix3X3Schema, +) { const det = Utils.math.det(supercellMatrix); if (det === 0) { throw new Error("Scaling matrix is degenerate."); diff --git a/src/js/tools/surface.ts b/src/js/tools/surface.ts index c36307381..d8dd5a805 100644 --- a/src/js/tools/surface.ts +++ b/src/js/tools/surface.ts @@ -1,4 +1,9 @@ -import { Coordinate3DSchema, Matrix3X3Schema, Vector3DSchema } from "@mat3ra/esse/dist/js/types"; +import { + type MaterialSchema, + Coordinate3DSchema, + Matrix3X3Schema, + Vector3DSchema, +} from "@mat3ra/esse/dist/js/types"; import { Utils } from "@mat3ra/utils"; import { Cell } from "../cell/cell"; @@ -166,8 +171,8 @@ export type SlabConfigSchema = MaterialConfig & { * @param vy {Number} Size of lateral supercell along the direction of the second (y) cell vector (Positive Integer). * @return {Object} */ -function generateConfig( - material: Material, +function generateConfig( + material: Material, millerIndices: Coordinate3DSchema, numberOfLayers = 1, vx = 1, diff --git a/tests/js/material.test.ts b/tests/js/material.test.ts index b6810d883..8d912c6e3 100644 --- a/tests/js/material.test.ts +++ b/tests/js/material.test.ts @@ -1,3 +1,4 @@ +import type { MaterialHashedSchema } from "@mat3ra/esse/dist/js/types"; import { expect } from "chai"; import { Material } from "../../src/js/material"; @@ -85,4 +86,24 @@ describe("MaterialHashed", () => { expect(material.hash).to.not.equal(previousHash); }); }); + + describe("generic schema wrapper", () => { + type WiderMaterialHashedSchema = MaterialHashedSchema & { webappOnly?: string }; + + class WiderMaterialHashed extends MaterialHashed {} + + it("allows subclasses to widen _json typing and storage", () => { + const material = new WiderMaterialHashed(Silicon); + + material._json.webappOnly = "webapp-value"; + expect(material._json.webappOnly).to.equal("webapp-value"); + + // toJSON rebuilds from schema-shaped fields; _json retains widened keys. + expect(material.toJSON().name).to.equal(Silicon.name); + expect(material._json.webappOnly).to.equal("webapp-value"); + + material._json.webappOnly = "updated"; + expect(material._json.webappOnly).to.equal("updated"); + }); + }); }); From 034921e94a7855442c4bf35204c81e8bd7352f04 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 21 Jul 2026 20:41:23 +0300 Subject: [PATCH 08/13] chore: simplify MaterialHashed toJSON and default config typing Rely on InMemoryEntity.toJSON for hash; type defaultMaterialConfig as Schema. Co-authored-by: Cursor --- dist/js/made.d.ts | 2 +- dist/js/material.d.ts | 2 +- dist/js/material_hashed.d.ts | 1 - dist/js/material_hashed.js | 6 ------ src/js/material.ts | 2 +- src/js/material_hashed.ts | 7 ------- 6 files changed, 3 insertions(+), 17 deletions(-) diff --git a/dist/js/made.d.ts b/dist/js/made.d.ts index e3acc2fdc..fa21de4e7 100644 --- a/dist/js/made.d.ts +++ b/dist/js/made.d.ts @@ -35,7 +35,7 @@ export declare const Made: { }; Material: typeof Material; MaterialHashed: typeof MaterialHashed; - defaultMaterialConfig: import("./material").MaterialConfig; + defaultMaterialConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema; Lattice: typeof Lattice; Cell: typeof Cell; UnitCell: typeof UnitCell; diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index 95ea3ee5d..ce8dcdda4 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -10,7 +10,7 @@ import { Lattice } from "./lattice/lattice"; export type PartialBy = Omit & Partial>; type Schema = MaterialSchema; export type MaterialConfig = PartialBy; -export declare const defaultMaterialConfig: MaterialConfig; +export declare const defaultMaterialConfig: Schema; interface BaseMaterial extends MaterialSchemaMixin, NamedEntity, Defaultable, Required> { } declare class BaseMaterial extends InMemoryEntity { diff --git a/dist/js/material_hashed.d.ts b/dist/js/material_hashed.d.ts index 4b9a81781..632d7ecdd 100644 --- a/dist/js/material_hashed.d.ts +++ b/dist/js/material_hashed.d.ts @@ -14,6 +14,5 @@ declare class MaterialHashed extends Material impl get lattice(): MaterialSchema["lattice"]; set lattice(value: MaterialSchema["lattice"]); updateHash(): void; - toJSON(): S; } export { MaterialHashed }; diff --git a/dist/js/material_hashed.js b/dist/js/material_hashed.js index c3f805b4b..227950e28 100644 --- a/dist/js/material_hashed.js +++ b/dist/js/material_hashed.js @@ -34,12 +34,6 @@ class MaterialHashed extends material_1.Material { updateHash() { this.hash = this.calculateHash("", false, this.isNonPeriodic); } - toJSON() { - return { - ...super.toJSON(), - hash: this.hash, - }; - } } exports.MaterialHashed = MaterialHashed; (0, HashedSchemaMixin_1.hashedSchemaMixin)(MaterialHashed.prototype); diff --git a/src/js/material.ts b/src/js/material.ts index 12983b8f9..03c578e6e 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -55,7 +55,7 @@ type Schema = MaterialSchema; export type MaterialConfig = PartialBy; -export const defaultMaterialConfig: MaterialConfig = { +export const defaultMaterialConfig: Schema = { name: "Silicon FCC", basis: { elements: [ diff --git a/src/js/material_hashed.ts b/src/js/material_hashed.ts index 46bca5ed8..30a7e3e44 100644 --- a/src/js/material_hashed.ts +++ b/src/js/material_hashed.ts @@ -64,13 +64,6 @@ class MaterialHashed extends Material implements S updateHash() { this.hash = this.calculateHash("", false, this.isNonPeriodic); } - - toJSON(): S { - return { - ...super.toJSON(), - hash: this.hash, - } as S; - } } hashedSchemaMixin(MaterialHashed.prototype); From 110252f7a33140ad76a34f5fb142187e6260d7fc Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 27 Jul 2026 20:27:00 +0300 Subject: [PATCH 09/13] chore: merge main --- dist/js/generated/MaterialSchemaMixin.d.ts | 1 - package-lock.json | 404 ++++++++++++++------- package.json | 4 +- src/js/generated/MaterialSchemaMixin.ts | 2 - 4 files changed, 270 insertions(+), 141 deletions(-) diff --git a/dist/js/generated/MaterialSchemaMixin.d.ts b/dist/js/generated/MaterialSchemaMixin.d.ts index aff45f703..d4ee36b28 100644 --- a/dist/js/generated/MaterialSchemaMixin.d.ts +++ b/dist/js/generated/MaterialSchemaMixin.d.ts @@ -1,5 +1,4 @@ import type { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; import type { MaterialPropertiesSchema } from "@mat3ra/esse/dist/js/types"; export type MaterialSchemaMixin = MaterialPropertiesSchema; -export type MaterialInMemoryEntity = InMemoryEntity & MaterialSchemaMixin; export declare function materialSchemaMixin(item: InMemoryEntity): asserts item is T & MaterialSchemaMixin; diff --git a/package-lock.json b/package-lock.json index a4c3422c2..5ae0e371e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,8 +31,8 @@ "@babel/register": "^7.29.7", "@babel/runtime-corejs3": "^7.29.7", "@exabyte-io/eslint-config": "^2026.7.3-0", - "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/ef877b55067afef34e492b8c2b317a1bb2cb8298.tar.gz", - "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/923890274d775e36904674ceed755c9c542cf201.tar.gz", + "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/de8538cf2bd31bdcc240c209f78ab42811add289.tar.gz", "@mat3ra/standata": "2026.6.30-0", "@mat3ra/tsconfig": "^2024.6.3-0", "@mat3ra/utils": "^2026.7.8-0", @@ -73,7 +73,6 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -548,7 +547,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -2390,7 +2388,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -2410,7 +2407,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2426,7 +2422,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -2435,7 +2430,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -2450,7 +2444,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -2459,7 +2452,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2471,14 +2463,12 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/@eslint/eslintrc/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/@exabyte-io/eslint-config": { "version": "2026.7.3-0", @@ -2845,7 +2835,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", "deprecated": "Use @eslint/config-array instead", - "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -2859,8 +2848,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "deprecated": "Use @eslint/object-schema instead" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -3032,8 +3020,8 @@ }, "node_modules/@mat3ra/code": { "version": "0.0.0", - "resolved": "https://github.com/Exabyte-io/code/archive/ef877b55067afef34e492b8c2b317a1bb2cb8298.tar.gz", - "integrity": "sha512-Qdu973CjIwHZOGoVqyLv1Jo9+BUusfpYGWWUeohjryZlDYx4r6J3qL1DDG+RQxl+CcaYKiTktK5vs/roZaEaVw==", + "resolved": "https://github.com/Exabyte-io/code/archive/923890274d775e36904674ceed755c9c542cf201.tar.gz", + "integrity": "sha512-C7RXWDT8PaPXmfnbxFBxU8eckGPB0qvW9GxvMiuSQICQTVNd2GvkuJw1o4Owgefv+i34n+QuCZPim5WqZns4hA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3126,8 +3114,8 @@ }, "node_modules/@mat3ra/esse": { "version": "0.0.0", - "resolved": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", - "integrity": "sha512-4+EIEjuwWLZr5eme1jzw21ofZITz1y73whwRRUJVqp+kIzjOCnIkoDskwK8R5gRIzKhx9oZJXBJvJYNQdOwOBA==", + "resolved": "https://github.com/mat3ra/esse/archive/de8538cf2bd31bdcc240c209f78ab42811add289.tar.gz", + "integrity": "sha512-jz2ujB+em8b5PDklsnYE8eoEUSNl63i3JpBDtjzVF8q8OKJcZlnAMH7NOV4aMqUeCtlwbPR6xkMJIrnC4ZWIzw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3768,6 +3756,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/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4178,7 +4180,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -4212,7 +4213,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", @@ -4256,7 +4256,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, "engines": { "node": ">=6" } @@ -4292,7 +4291,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -4301,7 +4299,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -4566,7 +4563,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "engines": { "node": ">=8" } @@ -4853,7 +4849,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -4944,7 +4939,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5219,7 +5213,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -5227,8 +5220,7 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { "version": "2.0.20", @@ -5353,7 +5345,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5494,8 +5485,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/default-require-extensions": { "version": "3.0.1", @@ -5573,6 +5563,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", @@ -5589,7 +5590,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -5627,14 +5627,12 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5865,7 +5863,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -5875,7 +5872,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -5928,6 +5924,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.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-config-airbnb": { "version": "19.0.4", "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", @@ -6061,6 +6088,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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.14.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", @@ -6220,6 +6270,67 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "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/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.10.2", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", @@ -6326,6 +6437,20 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, + "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", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -6398,7 +6523,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -6413,7 +6537,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, "engines": { "node": ">=4" } @@ -6430,7 +6553,6 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, "dependencies": { "@babel/highlight": "^7.10.4" } @@ -6439,7 +6561,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6455,7 +6576,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -6470,7 +6590,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -6479,7 +6598,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6495,7 +6613,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -6506,14 +6623,12 @@ "node_modules/eslint/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -6525,7 +6640,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -6540,7 +6654,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -6549,7 +6662,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -6558,7 +6670,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -6570,14 +6681,12 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/eslint/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -6589,7 +6698,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -6603,14 +6711,12 @@ "node_modules/eslint/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6621,14 +6727,12 @@ "node_modules/eslint/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, "dependencies": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -6642,7 +6746,6 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -6654,7 +6757,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, "engines": { "node": ">=4" } @@ -6663,7 +6765,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -6676,7 +6777,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -6689,7 +6789,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -6755,8 +6854,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -6784,20 +6882,17 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, "funding": [ { "type": "github", @@ -6822,7 +6917,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -6879,7 +6973,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -6892,8 +6985,7 @@ "node_modules/flatted": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.0.tgz", - "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==", - "dev": true + "integrity": "sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg==" }, "node_modules/for-each": { "version": "0.3.5", @@ -7017,8 +7109,7 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" }, "node_modules/functions-have-names": { "version": "1.2.3", @@ -7168,7 +7259,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -7273,7 +7363,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -7416,7 +7505,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7432,7 +7520,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, "engines": { "node": ">=0.8.19" } @@ -7648,7 +7735,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -7673,7 +7759,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -7702,7 +7787,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8021,8 +8105,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isobject": { "version": "3.0.1", @@ -8291,8 +8374,7 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "node_modules/json-schema": { "version": "0.4.0", @@ -8386,14 +8468,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json5": { "version": "2.2.3", @@ -8406,6 +8486,73 @@ "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/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.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -8425,7 +8572,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -8462,7 +8608,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -8654,14 +8799,12 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -9168,8 +9311,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/natural-compare-lite": { "version": "1.4.0", @@ -9711,7 +9853,6 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -9809,7 +9950,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -9837,7 +9977,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -9935,7 +10074,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -9984,7 +10122,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -10004,7 +10141,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -10130,7 +10266,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, "engines": { "node": ">=8" }, @@ -10207,7 +10342,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10252,7 +10386,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -10300,7 +10433,6 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -10520,7 +10652,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -10532,7 +10663,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -10631,7 +10761,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -10648,7 +10777,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -10663,7 +10791,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -10674,8 +10801,7 @@ "node_modules/slice-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/source-map": { "version": "0.6.1", @@ -10789,7 +10915,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10917,7 +11042,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10948,7 +11072,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -10960,7 +11083,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -10979,11 +11101,27 @@ "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.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", - "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -11012,8 +11150,7 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, "node_modules/through": { "version": "2.3.8", @@ -11206,7 +11343,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -11228,7 +11364,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -11464,7 +11599,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -11486,8 +11620,7 @@ "node_modules/v8-compile-cache": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", - "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", - "dev": true + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==" }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", @@ -11542,7 +11675,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, diff --git a/package.json b/package.json index d6618f3fc..bb6f03458 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "@babel/register": "^7.29.7", "@babel/runtime-corejs3": "^7.29.7", "@exabyte-io/eslint-config": "^2026.7.3-0", - "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/ef877b55067afef34e492b8c2b317a1bb2cb8298.tar.gz", - "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/197e69ec146d9903f39c093ae21f5fd7e1e4229e.tar.gz", + "@mat3ra/code": "https://github.com/Exabyte-io/code/archive/923890274d775e36904674ceed755c9c542cf201.tar.gz", + "@mat3ra/esse": "https://github.com/mat3ra/esse/archive/de8538cf2bd31bdcc240c209f78ab42811add289.tar.gz", "@mat3ra/standata": "2026.6.30-0", "@mat3ra/tsconfig": "^2024.6.3-0", "@mat3ra/utils": "^2026.7.8-0", diff --git a/src/js/generated/MaterialSchemaMixin.ts b/src/js/generated/MaterialSchemaMixin.ts index cd0f43a11..6c1bdc131 100644 --- a/src/js/generated/MaterialSchemaMixin.ts +++ b/src/js/generated/MaterialSchemaMixin.ts @@ -3,8 +3,6 @@ import type { MaterialPropertiesSchema } from "@mat3ra/esse/dist/js/types"; export type MaterialSchemaMixin = MaterialPropertiesSchema; -export type MaterialInMemoryEntity = InMemoryEntity & MaterialSchemaMixin; - export function materialSchemaMixin( item: InMemoryEntity, ): asserts item is T & MaterialSchemaMixin { From 9f31b4bbde6d0e7e7cd2224f65c8c11e246835c7 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 28 Jul 2026 01:07:30 +0300 Subject: [PATCH 10/13] chore: add setBasisConstraints/setBasisConstraintsFromArrayOfObjects --- dist/js/material.d.ts | 3 +++ dist/js/material.js | 14 ++++++++++++++ src/js/material.ts | 16 ++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index ce8dcdda4..986d53e99 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -5,6 +5,7 @@ import { type NamedEntity } from "@mat3ra/code/dist/js/entity/mixins/NamedEntity import type { AtomicConstraintsSchema, BasisSchema, ConsistencyCheck, DerivedPropertiesSchema, FileSourceSchema, LatticeSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; import type { BasisConfig } from "./basis/basis"; import { ConstrainedBasis } from "./basis/constrained_basis"; +import { Constraint } from "./constraints/constraints"; import { type MaterialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; export type PartialBy = Omit & Partial>; @@ -63,6 +64,8 @@ declare class Material extends BaseMaterial implem unsetFileProps(): void; setBasis(basis: BasisConfig): void; setBasis(basis: string, format: "xyz", unitz?: BasisSchema["units"]): void; + setBasisConstraints(constraints: Constraint[]): void; + setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema): void; getBasis(constraints?: AtomicConstraintsSchema): ConstrainedBasis; setLattice(lattice: LatticeSchema): void; getLattice(): Lattice; diff --git a/dist/js/material.js b/dist/js/material.js index 6255ee850..ebd7d7e1c 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -11,6 +11,7 @@ const NamedEntityMixin_1 = require("@mat3ra/code/dist/js/entity/mixins/NamedEnti const crypto_js_1 = __importDefault(require("crypto-js")); const constrained_basis_1 = require("./basis/constrained_basis"); const conventional_cell_1 = require("./cell/conventional_cell"); +const constraints_1 = require("./constraints/constraints"); const MaterialSchemaMixin_1 = require("./generated/MaterialSchemaMixin"); const lattice_1 = require("./lattice/lattice"); const parsers_1 = __importDefault(require("./parsers/parsers")); @@ -127,6 +128,19 @@ class Material extends BaseMaterial { this.unsetFileProps(); this.updateFormula(); } + setBasisConstraints(constraints) { + const basisWithConstraints = { + ...this.basis, + constraints: constraints.map((c) => c.toJSON()), + }; + this.setBasis(basisWithConstraints); + } + setBasisConstraintsFromArrayOfObjects(constraints) { + const constraintsInstances = constraints.map((c) => { + return constraints_1.Constraint.fromValueAndId(c.value, c.id); + }); + this.setBasisConstraints(constraintsInstances); + } getBasis(constraints) { const basisData = this.basis; return new constrained_basis_1.ConstrainedBasis({ diff --git a/src/js/material.ts b/src/js/material.ts index 03c578e6e..b3c8597c1 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -30,6 +30,7 @@ import { PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES, PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS, } from "./cell/conventional_cell"; +import { Constraint } from "./constraints/constraints"; import { type MaterialSchemaMixin, materialSchemaMixin } from "./generated/MaterialSchemaMixin"; import { Lattice } from "./lattice/lattice"; import parsers from "./parsers/parsers"; @@ -185,6 +186,21 @@ class Material extends BaseMaterial implements Sch this.updateFormula(); } + setBasisConstraints(constraints: Constraint[]) { + const basisWithConstraints = { + ...this.basis, + constraints: constraints.map((c) => c.toJSON()), + }; + this.setBasis(basisWithConstraints); + } + + setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { + const constraintsInstances = constraints.map((c) => { + return Constraint.fromValueAndId(c.value, c.id); + }); + this.setBasisConstraints(constraintsInstances); + } + getBasis(constraints?: AtomicConstraintsSchema) { const basisData = this.basis; From b0310d77d890f13837096358ae1c1dc9b389a53c Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 28 Jul 2026 16:14:08 +0300 Subject: [PATCH 11/13] fix: default missing ConstrainedBasis constraints to [] Materials often omit basis.constraints (stored as a proto property); restoring optional constraints and ?? [] avoids fromObjects(undefined). Co-authored-by: Cursor --- dist/js/basis/constrained_basis.d.ts | 2 +- dist/js/basis/constrained_basis.js | 3 ++- dist/js/material.js | 2 +- src/js/basis/constrained_basis.ts | 4 ++-- src/js/material.ts | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/dist/js/basis/constrained_basis.d.ts b/dist/js/basis/constrained_basis.d.ts index b075d7a68..f75c064a3 100644 --- a/dist/js/basis/constrained_basis.d.ts +++ b/dist/js/basis/constrained_basis.d.ts @@ -5,7 +5,7 @@ import { AtomicCoordinateValue } from "./coordinates"; import { AtomicElementValue } from "./elements"; import { AtomicLabelValue } from "./labels"; export interface ConstrainedBasisConfig extends BasisConfig { - constraints: AtomicConstraintsSchema; + constraints?: AtomicConstraintsSchema; } export interface ElementsCoordinatesAndConstraintsConfig extends ElementsAndCoordinatesConfig { constraints: AtomicConstraintValue[]; diff --git a/dist/js/basis/constrained_basis.js b/dist/js/basis/constrained_basis.js index 88e6a0b08..988601841 100644 --- a/dist/js/basis/constrained_basis.js +++ b/dist/js/basis/constrained_basis.js @@ -11,8 +11,9 @@ const helpers_1 = require("./helpers"); */ class ConstrainedBasis extends basis_1.Basis { constructor(config) { + var _a; super(config); - this._constraints = constraints_1.AtomicConstraints.fromObjects(config.constraints); // `constraints` is an Array with ids + this._constraints = constraints_1.AtomicConstraints.fromObjects((_a = config.constraints) !== null && _a !== void 0 ? _a : []); // `constraints` is an Array with ids } static fromElementsCoordinatesAndConstraints(config) { const basisConfig = this._convertValuesToConfig(config); diff --git a/dist/js/material.js b/dist/js/material.js index ebd7d7e1c..d0867404e 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -124,7 +124,7 @@ class Material extends BaseMaterial { setBasis(textOrObject, format, unitz) { const { constraints, ...basis } = parseBasis(textOrObject, format, unitz); this.basis = basis; - this.constraints = constraints; + this.constraints = constraints !== null && constraints !== void 0 ? constraints : []; this.unsetFileProps(); this.updateFormula(); } diff --git a/src/js/basis/constrained_basis.ts b/src/js/basis/constrained_basis.ts index e401ac087..de384dae8 100644 --- a/src/js/basis/constrained_basis.ts +++ b/src/js/basis/constrained_basis.ts @@ -8,7 +8,7 @@ import { ElementWithLabel } from "./helpers"; import { AtomicLabelValue } from "./labels"; export interface ConstrainedBasisConfig extends BasisConfig { - constraints: AtomicConstraintsSchema; + constraints?: AtomicConstraintsSchema; } export interface ElementsCoordinatesAndConstraintsConfig extends ElementsAndCoordinatesConfig { @@ -24,7 +24,7 @@ export class ConstrainedBasis extends Basis { constructor(config: ConstrainedBasisConfig) { super(config); - this._constraints = AtomicConstraints.fromObjects(config.constraints); // `constraints` is an Array with ids + this._constraints = AtomicConstraints.fromObjects(config.constraints ?? []); // `constraints` is an Array with ids } static fromElementsCoordinatesAndConstraints( diff --git a/src/js/material.ts b/src/js/material.ts index b3c8597c1..299a89485 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -181,7 +181,7 @@ class Material extends BaseMaterial implements Sch const { constraints, ...basis } = parseBasis(textOrObject, format, unitz); this.basis = basis; - this.constraints = constraints; + this.constraints = constraints ?? []; this.unsetFileProps(); this.updateFormula(); } From a9fc306b99b125c83497ff32f2e9c41df37b9ed7 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Wed, 29 Jul 2026 16:20:42 +0300 Subject: [PATCH 12/13] Keep atomic constraints off ESSE basis and make Basis schema-generic. Pass constraints via Material ctor/parsers separately, split non-empty fixture constraints into sidecar files, and type ConstrainedBasis as Basis. Co-authored-by: Cursor --- dist/js/basis/basis.d.ts | 18 ++-- dist/js/basis/basis.js | 19 ++-- dist/js/basis/constrained_basis.d.ts | 4 +- dist/js/basis/constrained_basis.js | 4 +- dist/js/made.d.ts | 16 ++-- dist/js/material.d.ts | 7 +- dist/js/material.js | 46 ++++++---- dist/js/parsers/espresso.d.ts | 6 +- dist/js/parsers/espresso.js | 6 +- dist/js/parsers/native_format_parsers.d.ts | 17 ++-- dist/js/parsers/native_format_parsers.js | 12 +-- dist/js/parsers/parsers.d.ts | 12 +-- dist/js/parsers/poscar.d.ts | 15 ++-- dist/js/parsers/poscar.js | 14 +-- dist/js/parsers/xyz.d.ts | 9 +- dist/js/parsers/xyz.js | 9 +- dist/js/parsers/xyz_combinatorial_basis.js | 4 +- dist/js/tools/basis.d.ts | 2 +- dist/js/tools/index.d.ts | 4 +- dist/js/tools/supercell.d.ts | 2 +- src/js/basis/basis.ts | 55 ++++++------ src/js/basis/constrained_basis.ts | 8 +- src/js/material.ts | 62 ++++++++----- src/js/parsers/espresso.ts | 11 ++- src/js/parsers/native_format_parsers.ts | 18 ++-- src/js/parsers/poscar.ts | 28 ++++-- src/js/parsers/xyz.ts | 15 ++-- src/js/parsers/xyz_combinatorial_basis.ts | 7 +- tests/fixtures/FeO.constraints.json | 3 + tests/fixtures/FeO.json | 4 +- tests/fixtures/Graphene.constraints.json | 3 + tests/fixtures/Graphene.json | 4 +- tests/fixtures/Na4Cl4.json | 4 +- tests/fixtures/Ni-hex.json | 4 +- tests/fixtures/Si-slab.json | 4 +- tests/fixtures/si-slab-100.json | 4 +- tests/fixtures/si-slab-111-0-vacuum.json | 4 +- .../si-slab-111-0.5-vacuum-gamma-120.json | 4 +- .../si-slab-111-0.5-vacuum-ratio.json | 4 +- tests/fixtures/si-standata.json | 4 +- tests/js/basis/basis.ts | 7 +- tests/js/fixtures.ts | 9 +- tests/js/material.test.ts | 90 +++++++++++++++++++ tests/js/parsers/espresso.ts | 7 +- tests/js/parsers/native_formats.ts | 16 ++-- tests/js/parsers/xyz.ts | 11 ++- 46 files changed, 407 insertions(+), 209 deletions(-) create mode 100644 tests/fixtures/FeO.constraints.json create mode 100644 tests/fixtures/Graphene.constraints.json diff --git a/dist/js/basis/basis.d.ts b/dist/js/basis/basis.d.ts index b088e71b7..a670dd4fd 100644 --- a/dist/js/basis/basis.d.ts +++ b/dist/js/basis/basis.d.ts @@ -1,5 +1,5 @@ import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -import { BasisSchema, Coordinate3DSchema, Vector3DSchema, BaseInMemoryEntitySchema } from "@mat3ra/esse/dist/js/types"; +import { BaseInMemoryEntitySchema, BasisSchema, Coordinate3DSchema, Vector3DSchema } from "@mat3ra/esse/dist/js/types"; import { Cell } from "../cell/cell"; import { AtomicCoordinateValue, Coordinates } from "./coordinates"; import { AtomicElementValue, Elements } from "./elements"; @@ -30,8 +30,8 @@ export interface ElementsAndCoordinatesConfig { units?: BasisSchema["units"]; cell?: Cell; } -type BasisEntitySchema = BasisConfig & BaseInMemoryEntitySchema; -export declare class Basis extends InMemoryEntity implements BasisSchema { +type BasisEntitySchema = S & BaseInMemoryEntitySchema; +export declare class Basis extends InMemoryEntity> implements BasisSchema { static defaultConfig: BasisSchema; units: BasisSchema["units"]; cell: Cell; @@ -40,14 +40,14 @@ export declare class Basis extends InMemoryEntity implements _labels: Labels; static _convertValuesToConfig({ elements, coordinates, units, cell, labels, }: ElementsAndCoordinatesConfig): BasisConfig; static fromElementsAndCoordinates({ elements, coordinates, units, cell, labels, }: ElementsAndCoordinatesConfig): Basis; - constructor(config?: BasisConfig); + constructor(config?: NoInfer); get elements(): BasisSchema["elements"]; set elements(elements: BasisSchema["elements"]); get coordinates(): BasisSchema["coordinates"]; set coordinates(coordinates: BasisSchema["coordinates"]); get labels(): BasisSchema["labels"]; set labels(labels: BasisSchema["labels"]); - toJSON(exclude?: (keyof BasisConfig)[]): BasisSchema; + toJSON(exclude?: (keyof BasisEntitySchema)[]): BasisEntitySchema; clone(): this; removeAllAtoms(): void; get cellRounded(): import("@mat3ra/esse/dist/js/types").Matrix3X3Schema; @@ -141,12 +141,16 @@ export declare class Basis extends InMemoryEntity implements * @summary Returns true if bases are equal, otherwise - false. * @param anotherBasisClsInstance {Basis} Another Basis. */ - isEqualTo(anotherBasisClsInstance: Basis): boolean; + isEqualTo(anotherBasisClsInstance: { + hashString: string; + }): boolean; /** * @summary Returns true if basis cells are equal, otherwise - false. * @param anotherBasisClsInstance {Basis} Another Basis. */ - hasEquivalentCellTo(anotherBasisClsInstance: Basis): boolean; + hasEquivalentCellTo(anotherBasisClsInstance: { + cell: Cell; + }): boolean; /** * @summary Returns the minimum cubic lattice size for a non-periodic structure. * Single-atom structures use the element atomic radius floored at defaultMinimumLatticeSize. diff --git a/dist/js/basis/basis.js b/dist/js/basis/basis.js index 4c032a79e..1b3e8949e 100644 --- a/dist/js/basis/basis.js +++ b/dist/js/basis/basis.js @@ -35,6 +35,8 @@ const DEFAULT_BASIS_CONFIG = { ], units: "crystal", }; +// Keep `{` on same line as `implements` to satisfy brace-style (conflicts with Prettier multi-line heritage). +// prettier-ignore class Basis extends entity_1.InMemoryEntity { static _convertValuesToConfig({ elements = [], coordinates = [], units = constants_1.ATOMIC_COORD_UNITS.crystal, cell = new cell_1.Cell(), labels = [], }) { const elementsArrayWithIdsJSON = elements_1.Elements.fromValues(elements).toJSON(); @@ -57,6 +59,7 @@ class Basis extends entity_1.InMemoryEntity { labels, })); } + // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. constructor(config = Basis.defaultConfig) { super(config); const { elements, coordinates, units, labels } = config; @@ -309,7 +312,7 @@ class Basis extends entity_1.InMemoryEntity { /* Returns array of atomic labels E.g., ["1", "2", "", ""] */ get atomicLabelsArray() { var _a; - const labelsArray = Array.from({ length: this.elements.length }, (_) => ""); + const labelsArray = Array.from({ length: this.elements.length }, () => ""); // https://dev.to/maafaishal/benchmarking-for-while-forof-and-arrayforeach-using-performancenow-1jjg if ((_a = this.labels) === null || _a === void 0 ? void 0 : _a.length) { for (let i = 0; i < this.labels.length; i++) { @@ -446,13 +449,13 @@ class Basis extends entity_1.InMemoryEntity { for (let i = 0; i < this._elements.values.length; i++) { for (let j = i + 1; j < this._elements.values.length; j++) { const distance = utils_1.Utils.math.vDist(this._coordinates.getElementValueByIndex(i), this._coordinates.getElementValueByIndex(j)); - if (!distance) - continue; - if (extremum === "max" && distance > resultDistance) { - resultDistance = distance; - } - if (extremum === "min" && distance < resultDistance) { - resultDistance = distance; + if (distance) { + if (extremum === "max" && distance > resultDistance) { + resultDistance = distance; + } + if (extremum === "min" && distance < resultDistance) { + resultDistance = distance; + } } } } diff --git a/dist/js/basis/constrained_basis.d.ts b/dist/js/basis/constrained_basis.d.ts index f75c064a3..43c25ee28 100644 --- a/dist/js/basis/constrained_basis.d.ts +++ b/dist/js/basis/constrained_basis.d.ts @@ -14,14 +14,14 @@ export interface ElementsCoordinatesAndConstraintsConfig extends ElementsAndCoor * @summary Extension of the Basis class able to deal with atomic constraints. * @extends Basis */ -export declare class ConstrainedBasis extends Basis { +export declare class ConstrainedBasis extends Basis { private _constraints; constructor(config: ConstrainedBasisConfig); static fromElementsCoordinatesAndConstraints(config: ElementsCoordinatesAndConstraintsConfig): ConstrainedBasis; get constraints(): AtomicConstraintsSchema; set constraints(constraints: AtomicConstraintsSchema); get AtomicConstraints(): AtomicConstraints; - toJSON(): ConstrainedBasisConfig; + toJSON(exclude?: (keyof ConstrainedBasisConfig)[]): ConstrainedBasisConfig; getConstraintByIndex(idx: number): AtomicConstraintValue; getConstraintById(id: number): AtomicConstraintValue; /** diff --git a/dist/js/basis/constrained_basis.js b/dist/js/basis/constrained_basis.js index 988601841..f29ca0af8 100644 --- a/dist/js/basis/constrained_basis.js +++ b/dist/js/basis/constrained_basis.js @@ -32,9 +32,9 @@ class ConstrainedBasis extends basis_1.Basis { get AtomicConstraints() { return constraints_1.AtomicConstraints.fromObjects(this.constraints); } - toJSON() { + toJSON(exclude = ["cell"]) { return { - ...super.toJSON(), + ...super.toJSON(exclude), constraints: this.constraints, }; } diff --git a/dist/js/made.d.ts b/dist/js/made.d.ts index fa21de4e7..219420325 100644 --- a/dist/js/made.d.ts +++ b/dist/js/made.d.ts @@ -48,15 +48,15 @@ export declare const Made: { parsers: { xyz: { validate: typeof import("./parsers/xyz").validate; - fromMaterial: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, fractional?: boolean) => string; + fromMaterial: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, fractional?: boolean, constraints?: import("@mat3ra/esse/dist/js/types").AtomicConstraintsSchema) => string; toBasisConfig: (txt: string, units?: string, cell?: Cell) => import("./basis/constrained_basis").ConstrainedBasisConfig; fromBasis: (basisClsInstance: import("./basis/constrained_basis").ConstrainedBasis, coordinatePrintFormat: string) => string; CombinatorialBasis: typeof import("./parsers/xyz_combinatorial_basis").CombinatorialBasis; }; poscar: { isPoscar: (text: string) => boolean; - toPoscar: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, omitConstraints?: boolean) => string; - fromPoscar: (fileContent: string) => object; + toPoscar: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, constraints?: import("@mat3ra/esse/dist/js/types").AtomicConstraintsSchema, omitConstraints?: boolean) => string; + fromPoscar: (fileContent: string) => import("./parsers/poscar").MaterialSchemaWithConstraints; atomicConstraintsCharFromBool: (bool: boolean) => string; atomsCount: typeof import("./parsers/poscar").atomsCount; }; @@ -64,11 +64,11 @@ export declare const Made: { parseMeta: (txt: string) => import("./parsers/cif").Meta; }; espresso: { - toEspressoFormat: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema) => string; + toEspressoFormat: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, constraints?: import("@mat3ra/esse/dist/js/types").AtomicConstraintsSchema) => string; }; nativeFormatParsers: { - detectFormat: (text: string) => string; - convertFromNativeFormat: (text: string) => any; + detectFormat: (text: string) => "json" | "poscar" | "unknown"; + convertFromNativeFormat: (text: string) => import("./parsers/poscar").MaterialSchemaWithConstraints; }; }; tools: { @@ -78,7 +78,7 @@ export declare const Made: { supercell: { generateConfig: (material: Material, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => { name: string; - basis: import("@mat3ra/esse/dist/js/types").BasisSchema; + basis: import("./basis/basis").BasisConfig & import("@mat3ra/esse/dist/js/types").BaseInMemoryEntitySchema; lattice: import("@mat3ra/esse/dist/js/types").LatticeSchema; }; generateNewBasisWithinSupercell: (basis: Basis | import("./basis/constrained_basis").ConstrainedBasis, cell: Cell, supercell: Cell, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => Basis; @@ -90,7 +90,7 @@ export declare const Made: { }; basis: { repeat: (basis: Basis, repetitions: number[]) => Basis; - interpolate: (initialBasis: Basis, finalBasis: Basis, numberOfSteps?: number) => Basis[]; + interpolate: (initialBasis: Basis, finalBasis: Basis, numberOfSteps?: number) => Basis[]; }; }; LATTICE_TYPE_CONFIGS: import("./lattice/lattice_types").LatticeTypeConfig[]; diff --git a/dist/js/material.d.ts b/dist/js/material.d.ts index 986d53e99..706f7eac1 100644 --- a/dist/js/material.d.ts +++ b/dist/js/material.d.ts @@ -20,7 +20,7 @@ declare class Material extends BaseMaterial implem static createDefault: () => Material; static get defaultConfig(): MaterialConfig; static constructMaterialFileSource(fileName: string, fileContent: string, fileExtension: string): FileSourceSchema; - private constraints; + constraints: AtomicConstraintsSchema; constructor(config: NoInfer>, constraints?: AtomicConstraintsSchema); updateFormula(): void; /** @@ -101,6 +101,7 @@ declare class Material extends BaseMaterial implem toCartesian(constraints?: AtomicConstraintsSchema): void; /** * Returns material's basis in XYZ format. + * Uses ESSE material JSON plus constraints separately (same contract as POSCAR/QE serializers). */ getBasisAsXyz(fractional?: boolean): string; /** @@ -121,6 +122,10 @@ declare class Material extends BaseMaterial implem * Returns material in POSCAR format. Pass `true` to ignore original poscar source and re-serialize. */ getAsPOSCAR(ignoreOriginal?: boolean, omitConstraints?: boolean): string; + /** + * Preserve private constraints via the second constructor argument (never on basis JSON). + */ + clone(extraContext?: object): this; /** * Returns a copy of the material with conventional cell constructed instead of primitive. */ diff --git a/dist/js/material.js b/dist/js/material.js index d0867404e..bdb289071 100644 --- a/dist/js/material.js +++ b/dist/js/material.js @@ -85,6 +85,7 @@ class Material extends BaseMaterial { }; } // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. + // Atomic constraints are accepted only via the second argument (not on config.basis). constructor(config, constraints = []) { var _a, _b, _c, _d; super({ @@ -129,11 +130,8 @@ class Material extends BaseMaterial { this.updateFormula(); } setBasisConstraints(constraints) { - const basisWithConstraints = { - ...this.basis, - constraints: constraints.map((c) => c.toJSON()), - }; - this.setBasis(basisWithConstraints); + this.constraints = constraints.map((c) => ({ id: c.id, value: c.value })); + this.unsetFileProps(); } setBasisConstraintsFromArrayOfObjects(constraints) { const constraintsInstances = constraints.map((c) => { @@ -157,7 +155,9 @@ class Material extends BaseMaterial { if (originalIsInCrystalUnits) { basis.toCrystal(); } - this.basis = basis.toJSON(); + const { constraints: nextConstraints, ...basisWithoutConstraints } = basis.toJSON(); + this.basis = basisWithoutConstraints; + this.constraints = nextConstraints !== null && nextConstraints !== void 0 ? nextConstraints : this.constraints; this.lattice = lattice; this.unsetFileProps(); } @@ -210,21 +210,22 @@ class Material extends BaseMaterial { /** * Converts basis to crystal/fractional coordinates. */ - toCrystal(constraints = []) { - this.basis = this.getBasis(constraints).toCrystal().toJSON(); + toCrystal(constraints) { + this.setBasis(this.getBasis(constraints).toCrystal().toJSON()); } /** * Converts current material's basis coordinates to cartesian. * No changes if coordinates already cartesian. */ - toCartesian(constraints = []) { - this.basis = this.getBasis(constraints).toCartesian().toJSON(); + toCartesian(constraints) { + this.setBasis(this.getBasis(constraints).toCartesian().toJSON()); } /** * Returns material's basis in XYZ format. + * Uses ESSE material JSON plus constraints separately (same contract as POSCAR/QE serializers). */ getBasisAsXyz(fractional = false) { - return parsers_1.default.xyz.fromMaterial(this.toJSON(), fractional); + return parsers_1.default.xyz.fromMaterial(this.toJSON(), fractional, this.constraints); } /** * Returns material in Quantum Espresso output format: @@ -240,7 +241,7 @@ class Material extends BaseMaterial { * ``` */ getAsQEFormat() { - return parsers_1.default.espresso.toEspressoFormat(this.toJSON()); + return parsers_1.default.espresso.toEspressoFormat(this.toJSON(), this.constraints); } /** * Returns material in POSCAR format. Pass `true` to ignore original poscar source and re-serialize. @@ -251,7 +252,16 @@ class Material extends BaseMaterial { if (((_a = this.src) === null || _a === void 0 ? void 0 : _a.extension) === "poscar" && !ignoreOriginal) { return this.src.text; } - return parsers_1.default.poscar.toPoscar(this.toJSON(), omitConstraints); + return parsers_1.default.poscar.toPoscar(this.toJSON(), this.constraints, omitConstraints); + } + /** + * Preserve private constraints via the second constructor argument (never on basis JSON). + */ + clone(extraContext) { + return new this.constructor({ + ...this.toJSON(), + ...extraContext, + }, this.constraints); } /** * Returns a copy of the material with conventional cell constructed instead of primitive. @@ -268,8 +278,7 @@ class Material extends BaseMaterial { const config = supercell_1.default.generateConfig(this, conventionalSupercellMatrix); config.lattice.type = conventionalLatticeType; config.name = `${this.name} - conventional cell`; - // @ts-expect-error - return new this.constructor(config); + return new this.constructor(config, this.constraints); } /** * @summary a series of checks for the material and returns an array of results in ConsistencyChecks format. @@ -307,12 +316,11 @@ class Material extends BaseMaterial { return checks; } toJSON() { - const lattice = this.getLattice(); - const basis = this.getBasis(); + const { constraints, ...basis } = this.getBasis().toJSON(); return { ...super.toJSON(), - lattice: lattice.toJSON(), - basis: basis.toJSON(), + lattice: this.getLattice().toJSON(), + basis, isNonPeriodic: this.isNonPeriodic, }; } diff --git a/dist/js/parsers/espresso.d.ts b/dist/js/parsers/espresso.d.ts index c3e448384..9dc90f72e 100644 --- a/dist/js/parsers/espresso.d.ts +++ b/dist/js/parsers/espresso.d.ts @@ -1,9 +1,9 @@ -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { AtomicConstraintsSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; /** * Construct textual representation of a materialOrConfig according to Quantum ESPRESSO pw.x input format. - * @param materialOrConfig - material class instance or its config object + * Constraints are not part of ESSE basis — pass them separately. */ -declare function toEspressoFormat(materialOrConfig: MaterialSchema): string; +declare function toEspressoFormat(materialOrConfig: MaterialSchema, constraints?: AtomicConstraintsSchema): string; declare const _default: { toEspressoFormat: typeof toEspressoFormat; }; diff --git a/dist/js/parsers/espresso.js b/dist/js/parsers/espresso.js index 8afec4a00..4676edf04 100644 --- a/dist/js/parsers/espresso.js +++ b/dist/js/parsers/espresso.js @@ -9,15 +9,15 @@ const lattice_1 = require("../lattice/lattice"); const xyz_1 = __importDefault(require("./xyz")); /** * Construct textual representation of a materialOrConfig according to Quantum ESPRESSO pw.x input format. - * @param materialOrConfig - material class instance or its config object + * Constraints are not part of ESSE basis — pass them separately. */ -function toEspressoFormat(materialOrConfig) { +function toEspressoFormat(materialOrConfig, constraints = []) { const l = new lattice_1.Lattice(materialOrConfig.lattice); const vectors = l.vectorArrays; const vectorsAsString = (0, lodash_1.map)(vectors, (v) => { return `${underscore_string_1.default.sprintf("%14.9f", v[0])}\t${underscore_string_1.default.sprintf("%14.9f", v[1])}\t${underscore_string_1.default.sprintf("%14.9f", v[2])}`; }).join("\n"); - return underscore_string_1.default.sprintf("CELL_PARAMETERS (angstroms)\n%s\n\nATOMIC_POSITIONS (crystal)\n%s", vectorsAsString, xyz_1.default.fromMaterial(materialOrConfig)); + return underscore_string_1.default.sprintf("CELL_PARAMETERS (angstroms)\n%s\n\nATOMIC_POSITIONS (crystal)\n%s", vectorsAsString, xyz_1.default.fromMaterial(materialOrConfig, false, constraints)); } exports.default = { toEspressoFormat, diff --git a/dist/js/parsers/native_format_parsers.d.ts b/dist/js/parsers/native_format_parsers.d.ts index d9515f45c..49da3e5c9 100644 --- a/dist/js/parsers/native_format_parsers.d.ts +++ b/dist/js/parsers/native_format_parsers.d.ts @@ -1,17 +1,18 @@ +import { type MaterialSchemaWithConstraints } from "./poscar"; /** * @summary Detects the format of the input string - * @throws {Error} - If the input string is unknown format - * @param {string} text - input string to detect format - * @returns {NATIVE_FORMAT} - Format of the input string + * @throws If the input string is unknown format + * @param text input string to detect format + * @returns Format of the input string */ -declare function detectFormat(text: string): string; +declare function detectFormat(text: string): "json" | "poscar" | "unknown"; /** * @summary Function to handle conversion from native formats - * @param {String} text - input string to detect format and convert - * @throws {Error} - If the input string is of unknown format - * @return {Object} - Material config + * @param text - input string to detect format and convert + * @throws If the input string is of unknown format + * @return Material config */ -declare function convertFromNativeFormat(text: string): any; +declare function convertFromNativeFormat(text: string): MaterialSchemaWithConstraints; declare const _default: { detectFormat: typeof detectFormat; convertFromNativeFormat: typeof convertFromNativeFormat; diff --git a/dist/js/parsers/native_format_parsers.js b/dist/js/parsers/native_format_parsers.js index 0f0322fc1..7907e0ddc 100644 --- a/dist/js/parsers/native_format_parsers.js +++ b/dist/js/parsers/native_format_parsers.js @@ -14,9 +14,9 @@ const NATIVE_FORMAT = { }; /** * @summary Detects the format of the input string - * @throws {Error} - If the input string is unknown format - * @param {string} text - input string to detect format - * @returns {NATIVE_FORMAT} - Format of the input string + * @throws If the input string is unknown format + * @param text input string to detect format + * @returns Format of the input string */ function detectFormat(text) { const jsonRegex = /^\s*\{/; @@ -28,9 +28,9 @@ function detectFormat(text) { } /** * @summary Function to handle conversion from native formats - * @param {String} text - input string to detect format and convert - * @throws {Error} - If the input string is of unknown format - * @return {Object} - Material config + * @param text - input string to detect format and convert + * @throws If the input string is of unknown format + * @return Material config */ function convertFromNativeFormat(text) { const format = detectFormat(text); diff --git a/dist/js/parsers/parsers.d.ts b/dist/js/parsers/parsers.d.ts index d4c300a5d..48a1e202f 100644 --- a/dist/js/parsers/parsers.d.ts +++ b/dist/js/parsers/parsers.d.ts @@ -1,15 +1,15 @@ declare const _default: { xyz: { validate: typeof import("./xyz").validate; - fromMaterial: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, fractional?: boolean) => string; + fromMaterial: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, fractional?: boolean, constraints?: import("@mat3ra/esse/dist/js/types").AtomicConstraintsSchema) => string; toBasisConfig: (txt: string, units?: string, cell?: import("../made").Cell) => import("../basis/constrained_basis").ConstrainedBasisConfig; fromBasis: (basisClsInstance: import("../basis/constrained_basis").ConstrainedBasis, coordinatePrintFormat: string) => string; CombinatorialBasis: typeof import("./xyz_combinatorial_basis").CombinatorialBasis; }; poscar: { isPoscar: (text: string) => boolean; - toPoscar: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, omitConstraints?: boolean) => string; - fromPoscar: (fileContent: string) => object; + toPoscar: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, constraints?: import("@mat3ra/esse/dist/js/types").AtomicConstraintsSchema, omitConstraints?: boolean) => string; + fromPoscar: (fileContent: string) => import("./poscar").MaterialSchemaWithConstraints; atomicConstraintsCharFromBool: (bool: boolean) => string; atomsCount: typeof import("./poscar").atomsCount; }; @@ -17,11 +17,11 @@ declare const _default: { parseMeta: (txt: string) => import("./cif").Meta; }; espresso: { - toEspressoFormat: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema) => string; + toEspressoFormat: (materialOrConfig: import("@mat3ra/esse/dist/js/types").MaterialSchema, constraints?: import("@mat3ra/esse/dist/js/types").AtomicConstraintsSchema) => string; }; nativeFormatParsers: { - detectFormat: (text: string) => string; - convertFromNativeFormat: (text: string) => any; + detectFormat: (text: string) => "json" | "poscar" | "unknown"; + convertFromNativeFormat: (text: string) => import("./poscar").MaterialSchemaWithConstraints; }; }; export default _default; diff --git a/dist/js/parsers/poscar.d.ts b/dist/js/parsers/poscar.d.ts index 9b8a4f09d..b33ac4ebd 100644 --- a/dist/js/parsers/poscar.d.ts +++ b/dist/js/parsers/poscar.d.ts @@ -1,21 +1,26 @@ -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { AtomicConstraintsSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; /** * Obtain a textual representation of a material in POSCAR format. - * @param materialOrConfig - material class instance or config object. - * @param omitConstraints - whether to discard constraints passed with material. + * @param materialOrConfig - material class instance or config object (ESSE basis; no constraints). + * @param constraints - atomic constraints, separate from material config. + * @param omitConstraints - whether to discard constraints when serializing. */ -declare function toPoscar(materialOrConfig: MaterialSchema, omitConstraints?: boolean): string; +declare function toPoscar(materialOrConfig: MaterialSchema, constraints?: AtomicConstraintsSchema, omitConstraints?: boolean): string; /** * @summary calculates the number of atoms in a poscar file based on the summation of the numbers in line 7 of the file. * Poscar file formatting: https://www.vasp.at/wiki/index.php/POSCAR */ export declare function atomsCount(poscarFileContent: string): number; +export type MaterialSchemaWithConstraints = Omit & { + metadata?: MaterialSchema["metadata"]; + constraints?: AtomicConstraintsSchema; +}; /** * Parses POSCAR file into a Material config object. * @param fileContent - POSCAR file content. * @return Material config. */ -declare function fromPoscar(fileContent: string): object; +declare function fromPoscar(fileContent: string): MaterialSchemaWithConstraints; /** * @summary Checks if a string has a POSCAR format (first 8 lines are read) * @param text - string to check diff --git a/dist/js/parsers/poscar.js b/dist/js/parsers/poscar.js index 54678d9e2..fd9b577e5 100644 --- a/dist/js/parsers/poscar.js +++ b/dist/js/parsers/poscar.js @@ -15,16 +15,17 @@ const _latticeVectorsToString = (vectors) => vectors.map((v) => v.map((c) => _pr const atomicConstraintsCharFromBool = (bool) => (bool ? "T" : "F"); /** * Obtain a textual representation of a material in POSCAR format. - * @param materialOrConfig - material class instance or config object. - * @param omitConstraints - whether to discard constraints passed with material. + * @param materialOrConfig - material class instance or config object (ESSE basis; no constraints). + * @param constraints - atomic constraints, separate from material config. + * @param omitConstraints - whether to discard constraints when serializing. */ -function toPoscar(materialOrConfig, omitConstraints = false) { +function toPoscar(materialOrConfig, constraints = [], omitConstraints = false) { const lattice = new lattice_1.Lattice(materialOrConfig.lattice); const vectorsAsString = _latticeVectorsToString(lattice.vectorArrays); - // @ts-ignore const basis = new constrained_basis_1.ConstrainedBasis({ ...materialOrConfig.basis, cell: cell_1.Cell.fromVectorsArray(lattice.vectorArrays), + constraints: omitConstraints ? [] : constraints, }); const BasisLines = []; let addSelectiveDynamics = false; @@ -131,11 +132,14 @@ function fromPoscar(fileContent) { cell: cell_1.Cell.fromVectorsArray(lattice.vectorArrays), constraints, }); + const basisJson = basis.toJSON(); + const { constraints: atomicConstraints, ...basisWithoutConstraints } = basisJson; const materialConfig = { lattice: lattice.toJSON(), - basis: basis.toJSON(), + basis: basisWithoutConstraints, name: comment, isNonPeriodic: false, + ...((atomicConstraints === null || atomicConstraints === void 0 ? void 0 : atomicConstraints.length) ? { constraints: atomicConstraints } : {}), }; return materialConfig; } diff --git a/dist/js/parsers/xyz.d.ts b/dist/js/parsers/xyz.d.ts index ea2af8c04..dd88df929 100644 --- a/dist/js/parsers/xyz.d.ts +++ b/dist/js/parsers/xyz.d.ts @@ -1,4 +1,4 @@ -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { AtomicConstraintsSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { ConstrainedBasis, ConstrainedBasisConfig } from "../basis/constrained_basis"; import { AtomicCoordinateValue } from "../basis/coordinates"; import { AtomicElementValue } from "../basis/elements"; @@ -32,11 +32,10 @@ declare function toBasisConfig(txt: string, units?: string, cell?: Cell): Constr declare function fromBasis(basisClsInstance: ConstrainedBasis, coordinatePrintFormat: string): string; /** * Create XYZ from Material class instance (or its JSON config). - * @param materialOrConfig Material. - * @param fractional Coordinate units as fractional. - * @return Class Instance + * Constraints are not part of ESSE basis — pass them separately. + * Prefer fromBasis when you already have a ConstrainedBasis instance. */ -declare function fromMaterial(materialOrConfig: MaterialSchema, fractional?: boolean): string; +declare function fromMaterial(materialOrConfig: MaterialSchema, fractional?: boolean, constraints?: AtomicConstraintsSchema): string; declare const _default: { validate: typeof validate; fromMaterial: typeof fromMaterial; diff --git a/dist/js/parsers/xyz.js b/dist/js/parsers/xyz.js index f8a7d8d64..55a55c377 100644 --- a/dist/js/parsers/xyz.js +++ b/dist/js/parsers/xyz.js @@ -132,16 +132,15 @@ function fromBasis(basisClsInstance, coordinatePrintFormat) { } /** * Create XYZ from Material class instance (or its JSON config). - * @param materialOrConfig Material. - * @param fractional Coordinate units as fractional. - * @return Class Instance + * Constraints are not part of ESSE basis — pass them separately. + * Prefer fromBasis when you already have a ConstrainedBasis instance. */ -function fromMaterial(materialOrConfig, fractional = false) { +function fromMaterial(materialOrConfig, fractional = false, constraints = []) { const lattice = new lattice_1.Lattice(materialOrConfig.lattice); - // @ts-ignore const basis = new constrained_basis_1.ConstrainedBasis({ ...materialOrConfig.basis, cell: cell_1.Cell.fromVectorsArray(lattice.vectorArrays), + constraints, }); if (fractional) { basis.toCrystal(); diff --git a/dist/js/parsers/xyz_combinatorial_basis.js b/dist/js/parsers/xyz_combinatorial_basis.js index a50ef0acf..149f09918 100644 --- a/dist/js/parsers/xyz_combinatorial_basis.js +++ b/dist/js/parsers/xyz_combinatorial_basis.js @@ -209,7 +209,9 @@ class CombinatorialBasis { dimensions.push(itemsSet); }); // @ts-ignore // We're multiplying objects with math, not numbers. No type casting will help. - const basisSet = utils_1.Utils.math.cartesianProduct.apply(null, dimensions); + const basisSet = utils_1.Utils.math.cartesianProduct.apply(null, + // @ts-ignore + dimensions); return basisSet.map((basis) => basis.filter((entry) => entry.element !== VACANCY_CHARACTER)); } /** diff --git a/dist/js/tools/basis.d.ts b/dist/js/tools/basis.d.ts index 9a9ef2628..c6d9cc72a 100644 --- a/dist/js/tools/basis.d.ts +++ b/dist/js/tools/basis.d.ts @@ -14,7 +14,7 @@ declare function repeat(basis: Basis, repetitions: number[]): Basis; * @param numberOfSteps{Number} Number of intermediate steps. * @return {Basis[]} List of all bases. */ -declare function interpolate(initialBasis: Basis, finalBasis: Basis, numberOfSteps?: number): Basis[]; +declare function interpolate(initialBasis: Basis, finalBasis: Basis, numberOfSteps?: number): Basis[]; declare const _default: { repeat: typeof repeat; interpolate: typeof interpolate; diff --git a/dist/js/tools/index.d.ts b/dist/js/tools/index.d.ts index e0d30ae99..6c6daf413 100644 --- a/dist/js/tools/index.d.ts +++ b/dist/js/tools/index.d.ts @@ -5,7 +5,7 @@ declare const _default: { supercell: { generateConfig: (material: import("../material").Material, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => { name: string; - basis: import("@mat3ra/esse/dist/js/types").BasisSchema; + basis: import("../basis/basis").BasisConfig & import("@mat3ra/esse/dist/js/types").BaseInMemoryEntitySchema; lattice: import("@mat3ra/esse/dist/js/types").LatticeSchema; }; generateNewBasisWithinSupercell: (basis: import("../made").Basis | import("../basis/constrained_basis").ConstrainedBasis, cell: import("../made").Cell, supercell: import("../made").Cell, supercellMatrix: import("@mat3ra/esse/dist/js/types").Matrix3X3Schema) => import("../made").Basis; @@ -17,7 +17,7 @@ declare const _default: { }; basis: { repeat: (basis: import("../made").Basis, repetitions: number[]) => import("../made").Basis; - interpolate: (initialBasis: import("../made").Basis, finalBasis: import("../made").Basis, numberOfSteps?: number) => import("../made").Basis[]; + interpolate: (initialBasis: import("../made").Basis, finalBasis: import("../made").Basis, numberOfSteps?: number) => import("../made").Basis[]; }; }; export default _default; diff --git a/dist/js/tools/supercell.d.ts b/dist/js/tools/supercell.d.ts index 52b158c78..83b099ecc 100644 --- a/dist/js/tools/supercell.d.ts +++ b/dist/js/tools/supercell.d.ts @@ -12,7 +12,7 @@ declare function generateNewBasisWithinSupercell(basis: Basis | ConstrainedBasis */ declare function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema): { name: string; - basis: import("@mat3ra/esse/dist/js/types").BasisSchema; + basis: import("../basis/basis").BasisConfig & import("@mat3ra/esse/dist/js/types").BaseInMemoryEntitySchema; lattice: import("@mat3ra/esse/dist/js/types").LatticeSchema; }; declare const _default: { diff --git a/src/js/basis/basis.ts b/src/js/basis/basis.ts index df2268bcf..2cd81dd72 100644 --- a/src/js/basis/basis.ts +++ b/src/js/basis/basis.ts @@ -1,20 +1,17 @@ // @ts-ignore import { getElectronegativity, getElementAtomicRadius } from "@exabyte-io/periodic-table.js"; import { InMemoryEntity } from "@mat3ra/code/dist/js/entity"; -// import { math } from "@mat3ra/code/dist/js/math"; -// import { -// BaseInMemoryEntitySchema, -// BasisSchema, -// Coordinate3DSchema, -// Vector3DSchema, -// } from "@mat3ra/esse/dist/js/types"; -import { BasisSchema, Coordinate3DSchema, Vector3DSchema, BaseInMemoryEntitySchema } from "@mat3ra/esse/dist/js/types"; +import { + BaseInMemoryEntitySchema, + BasisSchema, + Coordinate3DSchema, + Vector3DSchema, +} from "@mat3ra/esse/dist/js/types"; import { Utils } from "@mat3ra/utils"; import { chain, toPairs, uniq, values } from "lodash"; import { Cell } from "../cell/cell"; import { ATOMIC_COORD_UNITS, HASH_TOLERANCE } from "../constants"; - import { defaultNonPeriodicMinimumLatticeSize, diatomicLatticePaddingFactor, @@ -79,9 +76,11 @@ const DEFAULT_BASIS_CONFIG = { units: "crystal", }; -type BasisEntitySchema = BasisConfig & BaseInMemoryEntitySchema; +type BasisEntitySchema = S & BaseInMemoryEntitySchema; -export class Basis extends InMemoryEntity implements BasisSchema { +// Keep `{` on same line as `implements` to satisfy brace-style (conflicts with Prettier multi-line heritage). +// prettier-ignore +export class Basis extends InMemoryEntity> implements BasisSchema { static defaultConfig: BasisSchema = DEFAULT_BASIS_CONFIG as BasisSchema; units: BasisSchema["units"]; @@ -131,8 +130,9 @@ export class Basis extends InMemoryEntity implements BasisSch ); } - constructor(config: BasisConfig = Basis.defaultConfig) { - super(config); + // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. + constructor(config: NoInfer = Basis.defaultConfig as NoInfer) { + super(config as BasisEntitySchema); const { elements, coordinates, units, labels } = config; this.cell = new Cell(config.cell); this.units = units || (ATOMIC_COORD_UNITS.crystal as BasisSchema["units"]); @@ -165,14 +165,16 @@ export class Basis extends InMemoryEntity implements BasisSch this._labels = Labels.fromObjects(labels || []); } - toJSON(exclude: (keyof BasisConfig)[] = ["cell"]): BasisSchema { + toJSON( + exclude: (keyof BasisEntitySchema)[] = ["cell"] as (keyof BasisEntitySchema)[], + ): BasisEntitySchema { return { ...super.toJSON(exclude), elements: this.elements, coordinates: this.coordinates, units: this.units, ...(this.labels?.length ? { labels: this.labels } : {}), - }; + } as BasisEntitySchema; } override clone(): this { @@ -401,7 +403,9 @@ export class Basis extends InMemoryEntity implements BasisSch const element = entry[0]; const coordinate = entry[1]; const atomicLabel = entry[2]; - const toleratedCoordinate = coordinate.map((x) => Utils.math.roundCustom(x, HASH_TOLERANCE)); + const toleratedCoordinate = coordinate.map((x) => + Utils.math.roundCustom(x, HASH_TOLERANCE), + ); return `${element}${atomicLabel} ${toleratedCoordinate.join()}`; }); return `${standardRep.sort().join(";")};`; @@ -424,7 +428,7 @@ export class Basis extends InMemoryEntity implements BasisSch /* Returns array of atomic labels E.g., ["1", "2", "", ""] */ get atomicLabelsArray(): string[] { - const labelsArray = Array.from({ length: this.elements.length }, (_) => ""); + const labelsArray = Array.from({ length: this.elements.length }, () => ""); // https://dev.to/maafaishal/benchmarking-for-while-forof-and-arrayforeach-using-performancenow-1jjg if (this.labels?.length) { for (let i = 0; i < this.labels.length; i++) { @@ -469,7 +473,7 @@ export class Basis extends InMemoryEntity implements BasisSch * @summary Returns true if bases are equal, otherwise - false. * @param anotherBasisClsInstance {Basis} Another Basis. */ - isEqualTo(anotherBasisClsInstance: Basis): boolean { + isEqualTo(anotherBasisClsInstance: { hashString: string }): boolean { return this.hashString === anotherBasisClsInstance.hashString; } @@ -477,7 +481,7 @@ export class Basis extends InMemoryEntity implements BasisSch * @summary Returns true if basis cells are equal, otherwise - false. * @param anotherBasisClsInstance {Basis} Another Basis. */ - hasEquivalentCellTo(anotherBasisClsInstance: Basis): boolean { + hasEquivalentCellTo(anotherBasisClsInstance: { cell: Cell }): boolean { return !this.cell.vectorArrays .map((vector, idx) => { return Utils.math.vEqualWithTolerance( @@ -584,12 +588,13 @@ export class Basis extends InMemoryEntity implements BasisSch this._coordinates.getElementValueByIndex(i) as Coordinate3DSchema, this._coordinates.getElementValueByIndex(j) as Coordinate3DSchema, ); - if (!distance) continue; - if (extremum === "max" && distance > resultDistance) { - resultDistance = distance; - } - if (extremum === "min" && distance < resultDistance) { - resultDistance = distance; + if (distance) { + if (extremum === "max" && distance > resultDistance) { + resultDistance = distance; + } + if (extremum === "min" && distance < resultDistance) { + resultDistance = distance; + } } } } diff --git a/src/js/basis/constrained_basis.ts b/src/js/basis/constrained_basis.ts index de384dae8..79a7f2c9c 100644 --- a/src/js/basis/constrained_basis.ts +++ b/src/js/basis/constrained_basis.ts @@ -19,7 +19,7 @@ export interface ElementsCoordinatesAndConstraintsConfig extends ElementsAndCoor * @summary Extension of the Basis class able to deal with atomic constraints. * @extends Basis */ -export class ConstrainedBasis extends Basis { +export class ConstrainedBasis extends Basis { private _constraints: AtomicConstraints; constructor(config: ConstrainedBasisConfig) { @@ -50,9 +50,9 @@ export class ConstrainedBasis extends Basis { return AtomicConstraints.fromObjects(this.constraints); } - override toJSON(): ConstrainedBasisConfig { + override toJSON(exclude: (keyof ConstrainedBasisConfig)[] = ["cell"]): ConstrainedBasisConfig { return { - ...super.toJSON(), + ...super.toJSON(exclude as (keyof ConstrainedBasisConfig)[]), constraints: this.constraints, }; } @@ -74,7 +74,7 @@ export class ConstrainedBasis extends Basis { AtomicCoordinateValue, AtomicConstraintValue, ][] { - return this._elements.values.map((element: any, idx: number) => { + return this._elements.values.map((element: AtomicElementValue, idx: number) => { const coordinate = this.getCoordinateValueByIndex(idx); const constraint = this.getConstraintByIndex(idx); const label = this.atomicLabelsArray[idx]; diff --git a/src/js/material.ts b/src/js/material.ts index 299a89485..520207f26 100644 --- a/src/js/material.ts +++ b/src/js/material.ts @@ -131,9 +131,10 @@ class Material extends BaseMaterial implements Sch }; } - private constraints: AtomicConstraintsSchema = []; + constraints: AtomicConstraintsSchema = []; // NoInfer: keep default S (or an explicit type arg) instead of inferring S from the config literal. + // Atomic constraints are accepted only via the second argument (not on config.basis). constructor(config: NoInfer>, constraints: AtomicConstraintsSchema = []) { super({ ...config, @@ -187,11 +188,8 @@ class Material extends BaseMaterial implements Sch } setBasisConstraints(constraints: Constraint[]) { - const basisWithConstraints = { - ...this.basis, - constraints: constraints.map((c) => c.toJSON()), - }; - this.setBasis(basisWithConstraints); + this.constraints = constraints.map((c) => ({ id: c.id, value: c.value })); + this.unsetFileProps(); } setBasisConstraintsFromArrayOfObjects(constraints: AtomicConstraintsSchema) { @@ -222,7 +220,9 @@ class Material extends BaseMaterial implements Sch basis.toCrystal(); } - this.basis = basis.toJSON(); + const { constraints: nextConstraints, ...basisWithoutConstraints } = basis.toJSON(); + this.basis = basisWithoutConstraints; + this.constraints = nextConstraints ?? this.constraints; this.lattice = lattice; this.unsetFileProps(); @@ -280,23 +280,24 @@ class Material extends BaseMaterial implements Sch /** * Converts basis to crystal/fractional coordinates. */ - toCrystal(constraints: AtomicConstraintsSchema = []) { - this.basis = this.getBasis(constraints).toCrystal().toJSON(); + toCrystal(constraints?: AtomicConstraintsSchema) { + this.setBasis(this.getBasis(constraints).toCrystal().toJSON()); } /** * Converts current material's basis coordinates to cartesian. * No changes if coordinates already cartesian. */ - toCartesian(constraints: AtomicConstraintsSchema = []) { - this.basis = this.getBasis(constraints).toCartesian().toJSON(); + toCartesian(constraints?: AtomicConstraintsSchema) { + this.setBasis(this.getBasis(constraints).toCartesian().toJSON()); } /** * Returns material's basis in XYZ format. + * Uses ESSE material JSON plus constraints separately (same contract as POSCAR/QE serializers). */ getBasisAsXyz(fractional = false): string { - return parsers.xyz.fromMaterial(this.toJSON(), fractional); + return parsers.xyz.fromMaterial(this.toJSON(), fractional, this.constraints); } /** @@ -313,7 +314,7 @@ class Material extends BaseMaterial implements Sch * ``` */ getAsQEFormat(): string { - return parsers.espresso.toEspressoFormat(this.toJSON()); + return parsers.espresso.toEspressoFormat(this.toJSON(), this.constraints); } /** @@ -324,7 +325,25 @@ class Material extends BaseMaterial implements Sch if (this.src?.extension === "poscar" && !ignoreOriginal) { return this.src.text; } - return parsers.poscar.toPoscar(this.toJSON(), omitConstraints); + return parsers.poscar.toPoscar(this.toJSON(), this.constraints, omitConstraints); + } + + /** + * Preserve private constraints via the second constructor argument (never on basis JSON). + */ + clone(extraContext?: object): this { + type ThisType = typeof this; + type ThisConstructor = { + new (o: object, constraints?: AtomicConstraintsSchema): ThisType; + }; + + return new (this.constructor as ThisConstructor)( + { + ...this.toJSON(), + ...extraContext, + }, + this.constraints, + ); } /** @@ -348,8 +367,12 @@ class Material extends BaseMaterial implements Sch config.lattice.type = conventionalLatticeType; config.name = `${this.name} - conventional cell`; - // @ts-expect-error - return new this.constructor(config) as this; + type ThisType = typeof this; + type ThisConstructor = { + new (o: object, constraints?: AtomicConstraintsSchema): ThisType; + }; + + return new (this.constructor as ThisConstructor)(config, this.constraints); } /** @@ -401,13 +424,12 @@ class Material extends BaseMaterial implements Sch } toJSON(): S { - const lattice = this.getLattice(); - const basis = this.getBasis(); + const { constraints, ...basis } = this.getBasis().toJSON(); return { ...super.toJSON(), - lattice: lattice.toJSON(), - basis: basis.toJSON(), + lattice: this.getLattice().toJSON(), + basis, isNonPeriodic: this.isNonPeriodic, } as S; } diff --git a/src/js/parsers/espresso.ts b/src/js/parsers/espresso.ts index 7252ac9c1..708bb1ace 100644 --- a/src/js/parsers/espresso.ts +++ b/src/js/parsers/espresso.ts @@ -1,4 +1,4 @@ -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { AtomicConstraintsSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { map } from "lodash"; import s from "underscore.string"; @@ -7,9 +7,12 @@ import xyz from "./xyz"; /** * Construct textual representation of a materialOrConfig according to Quantum ESPRESSO pw.x input format. - * @param materialOrConfig - material class instance or its config object + * Constraints are not part of ESSE basis — pass them separately. */ -function toEspressoFormat(materialOrConfig: MaterialSchema): string { +function toEspressoFormat( + materialOrConfig: MaterialSchema, + constraints: AtomicConstraintsSchema = [], +): string { const l = new Lattice(materialOrConfig.lattice); const vectors = l.vectorArrays; const vectorsAsString = map(vectors, (v) => { @@ -21,7 +24,7 @@ function toEspressoFormat(materialOrConfig: MaterialSchema): string { return s.sprintf( "CELL_PARAMETERS (angstroms)\n%s\n\nATOMIC_POSITIONS (crystal)\n%s", vectorsAsString, - xyz.fromMaterial(materialOrConfig), + xyz.fromMaterial(materialOrConfig, false, constraints), ); } diff --git a/src/js/parsers/native_format_parsers.ts b/src/js/parsers/native_format_parsers.ts index 3b0bb4e9f..d498575ea 100644 --- a/src/js/parsers/native_format_parsers.ts +++ b/src/js/parsers/native_format_parsers.ts @@ -1,4 +1,4 @@ -import Poscar from "./poscar"; +import Poscar, { type MaterialSchemaWithConstraints } from "./poscar"; const NATIVE_FORMAT = { JSON: "json", @@ -7,13 +7,13 @@ const NATIVE_FORMAT = { PWX: "pwx", XYZ: "xyz", UNKNOWN: "unknown", -}; +} as const; /** * @summary Detects the format of the input string - * @throws {Error} - If the input string is unknown format - * @param {string} text - input string to detect format - * @returns {NATIVE_FORMAT} - Format of the input string + * @throws If the input string is unknown format + * @param text input string to detect format + * @returns Format of the input string */ function detectFormat(text: string) { const jsonRegex = /^\s*\{/; @@ -25,11 +25,11 @@ function detectFormat(text: string) { /** * @summary Function to handle conversion from native formats - * @param {String} text - input string to detect format and convert - * @throws {Error} - If the input string is of unknown format - * @return {Object} - Material config + * @param text - input string to detect format and convert + * @throws If the input string is of unknown format + * @return Material config */ -function convertFromNativeFormat(text: string) { +function convertFromNativeFormat(text: string): MaterialSchemaWithConstraints { const format = detectFormat(text); switch (format) { diff --git a/src/js/parsers/poscar.ts b/src/js/parsers/poscar.ts index 479b857f3..94e43226e 100644 --- a/src/js/parsers/poscar.ts +++ b/src/js/parsers/poscar.ts @@ -1,4 +1,5 @@ import { + AtomicConstraintsSchema, BasisSchema, Coordinate3DSchema, MaterialSchema, @@ -15,7 +16,6 @@ import { ATOMIC_COORD_UNITS } from "../constants"; import { AtomicConstraintValue } from "../constraints/constraints"; import { Lattice } from "../lattice/lattice"; - const _print = (x: number, printFormat = "%14.9f") => s.sprintf(printFormat, Utils.math.precise(x)); const _latticeVectorsToString = (vectors: Vector3DSchema[]) => vectors.map((v) => v.map((c) => _print(c)).join("\t")).join("\n"); @@ -23,16 +23,21 @@ const atomicConstraintsCharFromBool = (bool: boolean): string => (bool ? "T" : " /** * Obtain a textual representation of a material in POSCAR format. - * @param materialOrConfig - material class instance or config object. - * @param omitConstraints - whether to discard constraints passed with material. + * @param materialOrConfig - material class instance or config object (ESSE basis; no constraints). + * @param constraints - atomic constraints, separate from material config. + * @param omitConstraints - whether to discard constraints when serializing. */ -function toPoscar(materialOrConfig: MaterialSchema, omitConstraints = false): string { +function toPoscar( + materialOrConfig: MaterialSchema, + constraints: AtomicConstraintsSchema = [], + omitConstraints = false, +): string { const lattice = new Lattice(materialOrConfig.lattice); const vectorsAsString = _latticeVectorsToString(lattice.vectorArrays); - // @ts-ignore const basis = new ConstrainedBasis({ ...materialOrConfig.basis, cell: Cell.fromVectorsArray(lattice.vectorArrays), + constraints: omitConstraints ? [] : constraints, }); const BasisLines: string[] = []; let addSelectiveDynamics = false; @@ -73,12 +78,17 @@ export function atomsCount(poscarFileContent: string): number { return atomsLine.map((x) => parseInt(x, 10)).reduce((a, b) => a + b); } +export type MaterialSchemaWithConstraints = Omit & { + metadata?: MaterialSchema["metadata"]; + constraints?: AtomicConstraintsSchema; +}; + /** * Parses POSCAR file into a Material config object. * @param fileContent - POSCAR file content. * @return Material config. */ -function fromPoscar(fileContent: string): object { +function fromPoscar(fileContent: string): MaterialSchemaWithConstraints { const cleanContent = Utils.str.removeCommentsFromSourceCode(fileContent, "fortran"); const lines = cleanContent.split("\n"); @@ -151,11 +161,15 @@ function fromPoscar(fileContent: string): object { constraints, }); + const basisJson = basis.toJSON(); + const { constraints: atomicConstraints, ...basisWithoutConstraints } = basisJson; + const materialConfig = { lattice: lattice.toJSON(), - basis: basis.toJSON(), + basis: basisWithoutConstraints, name: comment, isNonPeriodic: false, + ...(atomicConstraints?.length ? { constraints: atomicConstraints } : {}), }; return materialConfig; diff --git a/src/js/parsers/xyz.ts b/src/js/parsers/xyz.ts index 430841fc8..b653db149 100644 --- a/src/js/parsers/xyz.ts +++ b/src/js/parsers/xyz.ts @@ -1,4 +1,4 @@ -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { AtomicConstraintsSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { isEmpty, isNaN, map } from "lodash"; import s from "underscore.string"; @@ -161,16 +161,19 @@ function fromBasis(basisClsInstance: ConstrainedBasis, coordinatePrintFormat: st /** * Create XYZ from Material class instance (or its JSON config). - * @param materialOrConfig Material. - * @param fractional Coordinate units as fractional. - * @return Class Instance + * Constraints are not part of ESSE basis — pass them separately. + * Prefer fromBasis when you already have a ConstrainedBasis instance. */ -function fromMaterial(materialOrConfig: MaterialSchema, fractional = false): string { +function fromMaterial( + materialOrConfig: MaterialSchema, + fractional = false, + constraints: AtomicConstraintsSchema = [], +): string { const lattice = new Lattice(materialOrConfig.lattice); - // @ts-ignore const basis = new ConstrainedBasis({ ...materialOrConfig.basis, cell: Cell.fromVectorsArray(lattice.vectorArrays), + constraints, }); if (fractional) { basis.toCrystal(); diff --git a/src/js/parsers/xyz_combinatorial_basis.ts b/src/js/parsers/xyz_combinatorial_basis.ts index 18bf27c71..bbac98664 100644 --- a/src/js/parsers/xyz_combinatorial_basis.ts +++ b/src/js/parsers/xyz_combinatorial_basis.ts @@ -8,7 +8,6 @@ import { AtomicCoordinateValue } from "../basis/coordinates"; import { AtomicElementValue } from "../basis/elements"; import { Cell } from "../cell/cell"; - /** * @summary Combinatorial XYZ basis class and related. Create and get all information about basis and elements in it. * Constructor accepts string in extended XYZ format. Extended XYZ format is as follows: @@ -225,7 +224,11 @@ export class CombinatorialBasis { dimensions.push(itemsSet); }); // @ts-ignore // We're multiplying objects with math, not numbers. No type casting will help. - const basisSet = Utils.math.cartesianProduct.apply(null, dimensions) as ElementWithCoordinate[][]; + const basisSet = Utils.math.cartesianProduct.apply( + null, + // @ts-ignore + dimensions, + ) as ElementWithCoordinate[][]; return basisSet.map((basis: ElementWithCoordinate[]) => basis.filter((entry) => entry.element !== VACANCY_CHARACTER), ); diff --git a/tests/fixtures/FeO.constraints.json b/tests/fixtures/FeO.constraints.json new file mode 100644 index 000000000..be14b117d --- /dev/null +++ b/tests/fixtures/FeO.constraints.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d319520a167c9b81c4b6beaaca22e8c4b44193fc656f511e55f7639d59a8e26a +size 451 diff --git a/tests/fixtures/FeO.json b/tests/fixtures/FeO.json index 99515869e..167b40eb7 100644 --- a/tests/fixtures/FeO.json +++ b/tests/fixtures/FeO.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ceaee5513c8093601a075bbb93bd8914e3dff76e24c2da0d67b35b785a27b8a2 -size 1254 +oid sha256:bfaf9788fd26553e8372fe045221de23530fb13576ae9c31af27caeaa88b1a2c +size 1315 diff --git a/tests/fixtures/Graphene.constraints.json b/tests/fixtures/Graphene.constraints.json new file mode 100644 index 000000000..edcbd9b22 --- /dev/null +++ b/tests/fixtures/Graphene.constraints.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:695f8accde93141378deed9495df5a4cc8b3db321ca43891729ee072aaa5fd0b +size 230 diff --git a/tests/fixtures/Graphene.json b/tests/fixtures/Graphene.json index b8c65821f..05d3c413a 100644 --- a/tests/fixtures/Graphene.json +++ b/tests/fixtures/Graphene.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43712ea8ada9350751be35d18f0ef92880a095be6536615f86b0c9ffd3b10dae -size 1835 +oid sha256:787d94fcb49087bdf359e6e76702041e88dc0682284dba5f25e94d8a2d217a39 +size 1465 diff --git a/tests/fixtures/Na4Cl4.json b/tests/fixtures/Na4Cl4.json index 11afb5dbd..9d6e07cff 100644 --- a/tests/fixtures/Na4Cl4.json +++ b/tests/fixtures/Na4Cl4.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6dbac6049c485dd790063d80419ca94160b2ee006463a3ae92e133023008746a -size 2017 +oid sha256:61acc2683a5046e24a8e4f592498083eaed24a0c1ed854972492597ed56b0eba +size 2800 diff --git a/tests/fixtures/Ni-hex.json b/tests/fixtures/Ni-hex.json index 9d30a16da..a3e937ebc 100644 --- a/tests/fixtures/Ni-hex.json +++ b/tests/fixtures/Ni-hex.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ac714e6f565c9bf4dd30c291a2e13d67da441b07cb5dcf6bb618537596702de -size 1870 +oid sha256:e2521a77cb1fad2b7ad68527b6432246742c0010e8cca1d4595730b5125dbfbe +size 1843 diff --git a/tests/fixtures/Si-slab.json b/tests/fixtures/Si-slab.json index 3aeaad6e7..205b6c2e4 100644 --- a/tests/fixtures/Si-slab.json +++ b/tests/fixtures/Si-slab.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb8fc82009d8a5c6d437bf17301e7a99760b51f756b4867360d48eaf5b7a7505 -size 1588 +oid sha256:9879224e228ba90f87690f894713cd4c768fdbcff4c009f81d988063b587eeaf +size 2029 diff --git a/tests/fixtures/si-slab-100.json b/tests/fixtures/si-slab-100.json index c94ff41a7..5ebb2efd4 100644 --- a/tests/fixtures/si-slab-100.json +++ b/tests/fixtures/si-slab-100.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f674c41197c026e6945a7eebefc12420cb924b67b6fb246934003c2ed87de06 -size 1609 +oid sha256:f2cbbe28f42b6a061e0a057b120cd3f34c47122b42ec6336651ca439702cd073 +size 2050 diff --git a/tests/fixtures/si-slab-111-0-vacuum.json b/tests/fixtures/si-slab-111-0-vacuum.json index 147ba2849..0a8b13364 100644 --- a/tests/fixtures/si-slab-111-0-vacuum.json +++ b/tests/fixtures/si-slab-111-0-vacuum.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d13761b40f49a864409fef85b011b0c1d5afe71fd8b6be63dc33811a344342af -size 1569 +oid sha256:bcb50b3e71e3513518503d3d98a24570f79079df7107bbff64c36d84613b9705 +size 2010 diff --git a/tests/fixtures/si-slab-111-0.5-vacuum-gamma-120.json b/tests/fixtures/si-slab-111-0.5-vacuum-gamma-120.json index ed3ebe149..e1e23e1bb 100644 --- a/tests/fixtures/si-slab-111-0.5-vacuum-gamma-120.json +++ b/tests/fixtures/si-slab-111-0.5-vacuum-gamma-120.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f5905448537352e0af199e5d1b66a2d51585b6fc91ad2078809fda097a428ab -size 1894 +oid sha256:d1b83b48b4400b5d125f72004705d520778e14f95e239239162a2f7fda0b7779 +size 2757 diff --git a/tests/fixtures/si-slab-111-0.5-vacuum-ratio.json b/tests/fixtures/si-slab-111-0.5-vacuum-ratio.json index 317c4f562..f883c629e 100644 --- a/tests/fixtures/si-slab-111-0.5-vacuum-ratio.json +++ b/tests/fixtures/si-slab-111-0.5-vacuum-ratio.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26c02b987bfc67d4f6702cbb3cb1e1b3df30a1e6d4301aead75d1eba791a478e -size 1609 +oid sha256:3320a17460b10fbff88ef4beb6684fe89af15f7f165b003467997451ceeea175 +size 2050 diff --git a/tests/fixtures/si-standata.json b/tests/fixtures/si-standata.json index dd195f26b..7f4417371 100644 --- a/tests/fixtures/si-standata.json +++ b/tests/fixtures/si-standata.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62175309558d4a75da4fd723ccb47dc558cdbb89fa224e61921c4ee2d5b48094 -size 1133 +oid sha256:ef37920119b9ae2ca66f73b24765bdfc8cb31786ffa07c54739359a4ad92be8e +size 1447 diff --git a/tests/js/basis/basis.ts b/tests/js/basis/basis.ts index c9dd77f70..2572bc2fc 100644 --- a/tests/js/basis/basis.ts +++ b/tests/js/basis/basis.ts @@ -37,7 +37,8 @@ describe("Basis", () => { it("should return jsonified basis", () => { const basis = new Material(Na4Cl4).getBasis(); - expect(basis.toJSON()).to.be.deep.almost.equal(Na4Cl4.basis); + const { constraints: _, ...basisJson } = basis.toJSON(); + expect(basisJson).to.be.deep.almost.equal(Na4Cl4.basis); }); it("should return true if cells are equal", () => { @@ -195,7 +196,9 @@ describe("Basis", () => { it("should return standard representation", () => { const basis = new Material(Na4Cl4Cartesian).getBasis(); - expect(basis.standardRepresentation).to.be.deep.almost.equal(Na4Cl4.basis); + const standardRepresentation = { ...basis.standardRepresentation }; + delete (standardRepresentation as { constraints?: unknown }).constraints; + expect(standardRepresentation).to.be.deep.almost.equal(Na4Cl4.basis); }); /** diff --git a/tests/js/fixtures.ts b/tests/js/fixtures.ts index 3cbeeea47..0b2a22ee3 100644 --- a/tests/js/fixtures.ts +++ b/tests/js/fixtures.ts @@ -12,8 +12,10 @@ import atomicConstraints_JSON from "../fixtures/atomic-constraints.json"; import C2H4_JSON from "../fixtures/C2H4.json"; import C2H4Translated_JSON from "../fixtures/C2H4-translated.json"; import FeLiSiBasis_JSON from "../fixtures/FeLiSi-basis.json"; +import FeOConstraints_JSON from "../fixtures/FeO.constraints.json"; import FeO_JSON from "../fixtures/FeO.json"; import Ge2Basis_JSON from "../fixtures/Ge2-basis.json"; +import GrapheneConstraints_JSON from "../fixtures/Graphene.constraints.json"; import Graphene_JSON from "../fixtures/Graphene.json"; import H2HFinal_JSON from "../fixtures/H2+H-final.json"; import H2HImage_JSON from "../fixtures/H2+H-image.json"; @@ -36,7 +38,8 @@ import Si2Basis_JSON from "../fixtures/Si2-basis.json"; import Si2BasisRepeated_JSON from "../fixtures/Si2-basis-repeated.json"; import Zr1H23Zr1H1_JSON from "../fixtures/Zr1H23Zr1H1.json"; -// Material (fixtures include hash; typed as MaterialHashedSchema for hash assertions) +// Material (fixtures include hash; typed as MaterialHashedSchema for hash assertions). +// Atomic constraints live in sibling `*.constraints.json` files when non-empty — never on basis. const Silicon = Silicon_JSON as unknown as MaterialHashedSchema; const SiSupercell = SiSupercell_JSON as unknown as MaterialHashedSchema; const SiSlab = SiSlab_JSON as unknown as MaterialHashedSchema; @@ -45,6 +48,7 @@ const SiSlab111 = SiSlab111_JSON as unknown as MaterialHashedSchema; const SiSlab111Gamma120 = SiSlab111Gamma120_JSON as unknown as MaterialHashedSchema; const SiSlab111NoVacuum = SiSlab111NoVacuum_JSON as unknown as MaterialHashedSchema; const FeO = FeO_JSON as unknown as MaterialHashedSchema; +const FeOConstraints = FeOConstraints_JSON as AtomicConstraintsSchema; const FeOStandata = MaterialStandata.getRuntimeDataConfigs().find((m: any) => m.name?.includes("FeO"), ) as MaterialHashedSchema; @@ -58,6 +62,7 @@ const H2HFinal = H2HFinal_JSON as unknown as MaterialHashedSchema; const H2HImage = H2HImage_JSON as unknown as MaterialHashedSchema; const Zr1H23Zr1H1 = Zr1H23Zr1H1_JSON as unknown as MaterialHashedSchema; const Graphene = Graphene_JSON as unknown as MaterialHashedSchema; +const GrapheneConstraints = GrapheneConstraints_JSON as AtomicConstraintsSchema; const NiHex = NiHex_JSON as unknown as MaterialHashedSchema; // Basis @@ -86,6 +91,7 @@ export { Si2BasisRepeated, // Other FeO, + FeOConstraints, FeOStandata, Na4Cl4, Na4Cl4Cartesian, @@ -104,6 +110,7 @@ export { H2HImage, Zr1H23Zr1H1, Graphene, + GrapheneConstraints, NiHex, }; diff --git a/tests/js/material.test.ts b/tests/js/material.test.ts index 8d912c6e3..3ba21a0d1 100644 --- a/tests/js/material.test.ts +++ b/tests/js/material.test.ts @@ -22,6 +22,96 @@ describe("Material", () => { clonedMaterial.setBasis(newBasisXYZ, "xyz", clonedMaterial.getBasis().units); expect(clonedMaterial.getBasis().elements).to.have.lengthOf(2); }); + + describe("atomic constraints", () => { + const constrainedBasisXYZ = `Li 0 0 0 1 1 0 +Li 0.25 0.25 0.25 +`; + + it("keeps constraints in getBasisAsXyz after setBasis strips them from basis JSON", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + + expect(material.basis).to.not.have.property("constraints"); + expect(material.getBasisAsXyz()).to.include("1 1 0"); + expect(material.getBasisAsXyz()).to.include("1 1 1"); + }); + + it("keeps constraints in getBasisAsXyz when toJSON omits them (client CoreMaterial path)", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + + // Simulate CoreMaterial client toJSON(): return raw _json without constraints. + material.toJSON = () => material._json; + + expect(material.toJSON().basis).to.not.have.property("constraints"); + expect(material.getBasisAsXyz()).to.include( + "Li 0.000000 0.000000 0.000000 1 1 0", + ); + expect(material.getBasisAsXyz()).to.include( + "Li 0.250000 0.250000 0.250000 1 1 1", + ); + }); + + it("toJSON never embeds constraints on basis", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + + expect(material.toJSON().basis).to.not.have.property("constraints"); + expect(material.constraints).to.have.lengthOf(2); + }); + + it("accepts constraints only as the second constructor argument", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + const { constraints } = material.getBasis(); + + // Embedded basis.constraints are not used; only the second arg hydrates this.constraints. + const fromSecondArg = new Material( + { ...Silicon, basis: { ...material.basis } }, + constraints, + ); + expect(fromSecondArg.constraints).to.deep.equal(constraints); + expect(fromSecondArg.getBasisAsXyz()).to.include("1 1 0"); + expect(fromSecondArg.getBasisAsXyz()).to.include("1 1 1"); + expect(fromSecondArg.toJSON().basis).to.not.have.property("constraints"); + }); + + it("rehydrates private constraints via setBasisConstraintsFromArrayOfObjects", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + const { constraints } = material.getBasis(); + + const reloaded = new Material({ + ...Silicon, + basis: { ...material.basis }, + }); + reloaded.setBasisConstraintsFromArrayOfObjects(constraints); + + expect(reloaded.getBasisAsXyz()).to.include("1 1 0"); + expect(reloaded.getBasisAsXyz()).to.include("1 1 1"); + }); + + it("preserves constraints across clone via second constructor argument", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + material.toJSON = () => material._json; + + const cloned = material.clone(); + expect(cloned.getBasisAsXyz()).to.include("1 1 0"); + expect(cloned.toJSON().basis).to.not.have.property("constraints"); + }); + + it("serializes constraints via getAsPOSCAR separate from basis JSON", () => { + const material = new Material(Silicon); + material.setBasis(constrainedBasisXYZ, "xyz", "crystal"); + + expect(material.toJSON().basis).to.not.have.property("constraints"); + const poscar = material.getAsPOSCAR(true); + expect(poscar).to.include("Selective dynamics"); + expect(poscar).to.match(/T\s+T\s+F/); + }); + }); }); describe("MaterialHashed", () => { diff --git a/tests/js/parsers/espresso.ts b/tests/js/parsers/espresso.ts index 7d9a2d1b6..88da0f23a 100644 --- a/tests/js/parsers/espresso.ts +++ b/tests/js/parsers/espresso.ts @@ -1,4 +1,3 @@ -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { expect } from "chai"; import { Material } from "../../../src/js/material"; @@ -8,8 +7,8 @@ import { Silicon, SiPWSCFInput } from "../fixtures"; describe("Parsers:Espresso", () => { it("should return textual representation of a material according to QE pw.x input format", () => { const material = new Material(Silicon); - expect(parsers.espresso.toEspressoFormat(material as MaterialSchema)).to.be.equal( - SiPWSCFInput, - ); + expect( + parsers.espresso.toEspressoFormat(material.toJSON(), material.constraints), + ).to.be.equal(SiPWSCFInput); }); }); diff --git a/tests/js/parsers/native_formats.ts b/tests/js/parsers/native_formats.ts index 1210b73ca..c2f105857 100644 --- a/tests/js/parsers/native_formats.ts +++ b/tests/js/parsers/native_formats.ts @@ -4,7 +4,7 @@ import { Utils } from "@mat3ra/utils"; import { expect } from "chai"; import nativeFormatParsers from "../../../src/js/parsers/native_format_parsers"; -import { Graphene, GraphenePoscar, NiHex, NiHexPoscar } from "../fixtures"; +import { Graphene, GrapheneConstraints, GraphenePoscar, NiHex, NiHexPoscar } from "../fixtures"; const { assertDeepAlmostEqual } = Utils.assertion; @@ -15,17 +15,21 @@ describe("Parsers.NativeFormat", () => { }); it("should return a material config for graphene from a poscar", () => { - const poscar = GraphenePoscar; - const config = nativeFormatParsers.convertFromNativeFormat(poscar); + const { constraints, ...config } = + nativeFormatParsers.convertFromNativeFormat(GraphenePoscar); + assertDeepAlmostEqual(config, Graphene, ["basis.labels", "lattice"]); assertDeepAlmostEqual(config.lattice, Graphene.lattice, ["type"]); + expect(constraints).to.deep.equal(GrapheneConstraints); }); it("should return a material config for Ni hex from a poscar", () => { - const poscar = NiHexPoscar; - const config = nativeFormatParsers.convertFromNativeFormat(poscar); + const { constraints, ...config } = nativeFormatParsers.convertFromNativeFormat(NiHexPoscar); + assertDeepAlmostEqual(config, NiHex, ["lattice", "basis.labels"]); - assertDeepAlmostEqual(config.lattice, NiHex.lattice, ["type"]); // to omit "lattice.type" property + assertDeepAlmostEqual(config.lattice, NiHex.lattice, ["type"]); + // Empty selective-dynamics list is omitted from POSCAR parse output. + expect(constraints ?? []).to.deep.equal([]); }); it("should throw an error for unknown format", () => { diff --git a/tests/js/parsers/xyz.ts b/tests/js/parsers/xyz.ts index a38c43231..08ddc0bbe 100644 --- a/tests/js/parsers/xyz.ts +++ b/tests/js/parsers/xyz.ts @@ -1,4 +1,5 @@ import { Utils } from "@mat3ra/utils"; +import { expect } from "chai"; import parsers from "../../../src/js/parsers/parsers"; import { FeO, Silicon } from "../fixtures"; @@ -21,12 +22,20 @@ describe("Parsers:XYZ", () => { "Fe2 0.50 0.50 0.50 1 1 1\n" + "O 0.25 0.25 0.25 1 1 1\n" + "O 0.75 0.75 0.75 1 1 1"; - assertDeepAlmostEqual(parsers.xyz.toBasisConfig(text), FeO.basis, ["cell", "units"]); + assertDeepAlmostEqual(parsers.xyz.toBasisConfig(text), FeO.basis, [ + "constraints", + "cell", + "units", + ]); }); it("should return [true, true, true] as constraints for the line without any constraints", () => { const text = "Si 0 0 0 0 1 1\n Si 0.25 0.25 0.25"; const basis = parsers.xyz.toBasisConfig(text); + expect(basis.constraints).to.be.an("array").with.lengthOf(2); + if (!basis.constraints) { + throw new Error("expected constraints on parsed XYZ basis"); + } assertDeepAlmostEqual(basis.constraints[0].value, [false, true, true]); assertDeepAlmostEqual(basis.constraints[1].value, [true, true, true]); }); From 0123fb749b4e7f90468278f3018a1b0e70ac8df3 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Wed, 29 Jul 2026 16:26:51 +0300 Subject: [PATCH 13/13] fix: lint --- src/js/basis/coordinates.ts | 1 - src/js/cell/cell.ts | 1 - .../lattice/reciprocal/lattice_reciprocal.ts | 25 ++++++++++++++----- src/js/tools/basis.ts | 1 - src/js/tools/cell.ts | 1 - 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/js/basis/coordinates.ts b/src/js/basis/coordinates.ts index 760095cf8..9127aee27 100644 --- a/src/js/basis/coordinates.ts +++ b/src/js/basis/coordinates.ts @@ -8,7 +8,6 @@ import { import { Utils } from "@mat3ra/utils"; import { sprintf } from "underscore.string"; - export type AtomicCoordinateValue = AtomicCoordinateSchema["value"]; type AxisType = "x" | "y" | "z"; diff --git a/src/js/cell/cell.ts b/src/js/cell/cell.ts index 83c514729..811f1b7d2 100644 --- a/src/js/cell/cell.ts +++ b/src/js/cell/cell.ts @@ -9,7 +9,6 @@ import { Utils } from "@mat3ra/utils"; import constants from "../constants"; - const MATRIX = Utils.math.matrix; const MULT = Utils.math.multiply; const INV = Utils.math.inv; diff --git a/src/js/lattice/reciprocal/lattice_reciprocal.ts b/src/js/lattice/reciprocal/lattice_reciprocal.ts index e12f64814..298145204 100644 --- a/src/js/lattice/reciprocal/lattice_reciprocal.ts +++ b/src/js/lattice/reciprocal/lattice_reciprocal.ts @@ -7,7 +7,6 @@ import { Lattice } from "../lattice"; import { paths } from "./paths"; import { symmetryPoints } from "./symmetry_points"; - export type KPointCoordinates = number[]; export type KPointPath = Array<{ point: string; @@ -47,9 +46,18 @@ export class ReciprocalLattice extends Lattice { Utils.math.cross(vectors_[1], vectors_[2]), ) as unknown as number) / a; return [ - Utils.math.multiply(Utils.math.cross(vectors_[1], vectors_[2]), 1 / divider) as Vector3DSchema, - Utils.math.multiply(Utils.math.cross(vectors_[2], vectors_[0]), 1 / divider) as Vector3DSchema, - Utils.math.multiply(Utils.math.cross(vectors_[0], vectors_[1]), 1 / divider) as Vector3DSchema, + Utils.math.multiply( + Utils.math.cross(vectors_[1], vectors_[2]), + 1 / divider, + ) as Vector3DSchema, + Utils.math.multiply( + Utils.math.cross(vectors_[2], vectors_[0]), + 1 / divider, + ) as Vector3DSchema, + Utils.math.multiply( + Utils.math.cross(vectors_[0], vectors_[1]), + 1 / divider, + ) as Vector3DSchema, ]; } @@ -57,7 +65,9 @@ export class ReciprocalLattice extends Lattice { * Norms of reciprocal vectors. */ get reciprocalVectorNorms(): Vector3DSchema { - return this.reciprocalVectors.map((vec) => Utils.math.norm(vec) as number) as Vector3DSchema; + return this.reciprocalVectors.map( + (vec) => Utils.math.norm(vec) as number, + ) as Vector3DSchema; } /** @@ -167,7 +177,10 @@ export class ReciprocalLattice extends Lattice { getDimensionsFromSpacing(spacing: number, units: string = ATOMIC_COORD_UNITS.cartesian) { const factor: number = this.conversionTable[units][ATOMIC_COORD_UNITS.cartesian] || 1; return this.reciprocalVectorNorms.map((norm: number) => { - return Utils.math.max(1, Utils.math.ceil(lodash.round(norm / (spacing * factor), 4))) as number; + return Utils.math.max( + 1, + Utils.math.ceil(lodash.round(norm / (spacing * factor), 4)), + ) as number; }) as Vector3DSchema; } diff --git a/src/js/tools/basis.ts b/src/js/tools/basis.ts index 9b8ce2ad3..ea1307629 100644 --- a/src/js/tools/basis.ts +++ b/src/js/tools/basis.ts @@ -5,7 +5,6 @@ import { chunk, flatten } from "lodash"; import { Basis } from "../basis/basis"; import { AtomicCoordinateValue, Coordinate } from "../basis/coordinates"; - const ADD = Utils.math.add; const MULT = Utils.math.multiply; diff --git a/src/js/tools/cell.ts b/src/js/tools/cell.ts index d21d7ba23..7a9225b9f 100644 --- a/src/js/tools/cell.ts +++ b/src/js/tools/cell.ts @@ -3,7 +3,6 @@ import { Utils } from "@mat3ra/utils"; import { Cell } from "../cell/cell"; - /** * Returns the list of points on the original lattice contained in the supercell in fractional coordinates. * Source: https://pymatgen.org/_modules/pymatgen/util/coord.html