Skip to content

Commit

Permalink
feat: types simplified
Browse files Browse the repository at this point in the history
  • Loading branch information
seankwarren committed Feb 7, 2024
1 parent 37d4d92 commit 2ecef50
Show file tree
Hide file tree
Showing 17 changed files with 501 additions and 451 deletions.
1 change: 0 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@
"@babel/plugin-proposal-class-properties"
]
}

11 changes: 6 additions & 5 deletions .nycrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"all": true,
"include": [
"src/**/*.js",
"src/**/*.jsx"
]
"extension": [".ts"],
"require": ["ts-node/register"],
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["dist"],
"sourceMap": true,
"instrument": true
}

10 changes: 7 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"prepublishOnly": "rm -rf lib; npm run transpile",
"transpile": "tsc",
"postinstall": "npm run transpile",
"test": "nyc --reporter=text mocha --recursive --bail --require @babel/register/lib --require tests/setup.js tests",
"test": "nyc --reporter=text mocha --recursive --bail --require ts-node/register --require tests/setup.ts 'tests/**/*.test.ts'",
"lint": "eslint src tests && prettier --write src tests",
"lint:fix": "eslint --fix --cache src tests && prettier --write src tests",
"prettier": "prettier --check src tests",
Expand All @@ -27,9 +27,6 @@
"@babel/cli": "7.16.0",
"@babel/core": "7.16.0",
"@exabyte-io/periodic-table.js": "2022.6.8-0",
"@types/chai": "^4.3.5",
"@types/mocha": "^10.0.1",
"@types/node": "^20.4.2",
"@types/underscore": "^1.11.6",
"@types/underscore.string": "^0.0.40",
"lodash": "^4.17.21",
Expand All @@ -50,6 +47,9 @@
"@exabyte-io/code.js": "https://github.com/Exabyte-io/code.js.git#20d456ad83bd59b5a075bc499513fd076f46c6ce",
"@exabyte-io/eslint-config": "^2022.11.17-0",
"@exabyte-io/made.js": "^2024.1.8-0",
"@types/chai": "^4.3.11",
"@types/mocha": "^10.0.6",
"@types/node": "^20.11.16",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"chai": "^4.3.4",
Expand All @@ -66,7 +66,8 @@
"lint-staged": "^12.1.2",
"mocha": "^9.1.3",
"nyc": "^15.1.0",
"prettier": "^2.7.1"
"prettier": "^2.7.1",
"ts-node": "^10.9.2"
},
"peerDependencies": {
"@exabyte-io/code.js": "*",
Expand Down
273 changes: 131 additions & 142 deletions src/application.ts
Original file line number Diff line number Diff line change
@@ -1,153 +1,142 @@
// @ts-ignore
// @ts-expect-error application-flavors.js is not typed
import { allApplications, getAppData, getAppTree } from "@exabyte-io/application-flavors.js";
import { NamedDefaultableHashedInMemoryEntity } from "@exabyte-io/code.js/dist/entity";
import { type Constructor } from "@exabyte-io/code.js/dist/context";

import lodash from "lodash";

import { Executable } from "./executable";
import { getApplicationConfig, getExecutableConfig } from "./tree";
import { ApplicationConfig, ApplicationData } from "./types";

type ApplicationBase = InstanceType<typeof NamedDefaultableHashedInMemoryEntity>;

// @ts-ignore
export function ApplicationMixin<
T extends Constructor<ApplicationBase> = Constructor<ApplicationBase>
>(superclass: T) {
return class AdeApplication extends superclass {
static Executable = Executable;

constructor(...args: any[]) {
const config = args[0] as ApplicationConfig;
if (!config || typeof config.name !== "string") throw new Error("Invalid application configuration object.");
const staticConfig = getApplicationConfig(config);
if (!staticConfig) throw new Error(`Application "${config.name} (${config.version}-${config.build})" is not supported.`);
super({ ...staticConfig, ...config });
}

// TODO: extract this from application-flavors "global" default config for espresso 5.4.0
static get defaultConfig() {
return {
name: "espresso",
shortName: "qe",
version: "6.3",
summary: "Quantum Espresso",
build: "Default",
};
}

static create(config: {
name: string,
version?: string,
build?: string
}) {
return this.createFromNameVersionBuild(config);
}

static createFromNameVersionBuild({
name,
version = undefined,
build = "Default"
}: {
name: string,
version?: string,
build?: string
}) {
return new AdeApplication({ name, version, build });
}

getExecutables() {
return this.executables;
}

getBuilds() {
const data = getAppData(this.prop("name")) as ApplicationData;
const { versions } = data;
const builds = ["Default"];
versions.map((v) => v.build && builds.push(v.build));
return lodash.uniq(builds);
}

getVersions() {
const data = getAppData(this.prop("name")) as ApplicationData;
const { versions } = data;
const these: string[] = versions.map((v) => v.version);
return lodash.uniq(these);
}

static getUniqueAvailableNames() {
return allApplications;
}

getExecutableByName(name?: string) {
return new AdeApplication.Executable(
getExecutableConfig({
appName: this.prop("name"),
execName: name,
}),
);
}

getExecutableByConfig(config: {name: string} | null | undefined = null) {
return config ? this.getExecutableByName(config.name) : this.defaultExecutable;
}

get defaultExecutable() {
return this.getExecutableByName();
}

// override upon inheritance
// eslint-disable-next-line class-methods-use-this
get allowedModelTypes() {
return [];
}

get summary() {
return this.prop("summary");
}

get version() {
return this.prop("version");
}

get build() {
return this.prop("build");
}

get shortName() {
return this.prop("shortName", this.prop("name"));
}

get executables() {
const tree = getAppTree(this.prop("name"));
return Object.keys(tree)
.filter((key) => {
const { supportedApplicationVersions } = tree[key];
return (
!supportedApplicationVersions ||
supportedApplicationVersions.includes(this.prop("version"))
);
})
.map((key) => {
return new AdeApplication.Executable({ ...tree[key], name: key });
});
}

get hasAdvancedComputeOptions() {
return this.prop("hasAdvancedComputeOptions");
}

get isLicensed() {
return this.prop("isLicensed");
}

get isUsingMaterial() {
const materialUsingApplications = ["vasp", "nwchem", "espresso", "exabyteml"];
return materialUsingApplications.includes(this.name);
}
export class Application extends NamedDefaultableHashedInMemoryEntity {
static Executable = Executable;

constructor(...args: any[]) {
const config = args[0] as ApplicationConfig;
if (!config || typeof config.name !== "string") throw new Error("Invalid application configuration object.");
const staticConfig = getApplicationConfig(config);
if (!staticConfig) throw new Error(`Application "${config.name} (${config.version}-${config.build})" is not supported.`);
super({ ...staticConfig, ...config });
}

// TODO: extract this from application-flavors "global" default config for espresso 5.4.0
static get defaultConfig() {
return {
name: "espresso",
shortName: "qe",
version: "6.3",
summary: "Quantum Espresso",
build: "Default",
};
}

static create(config: {
name: string,
version?: string,
build?: string
}) {
return this.createFromNameVersionBuild(config);
}

static createFromNameVersionBuild({
name,
version = undefined,
build = "Default"
}: {
name: string,
version?: string,
build?: string
}) {
return new Application({ name, version, build });
}

getExecutables() {
return this.executables;
}

getBuilds() {
const data = getAppData(this.prop("name")) as ApplicationData;
const { versions } = data;
const builds = ["Default"];
versions.map((v) => v.build && builds.push(v.build));
return lodash.uniq(builds);
}

getVersions() {
const data = getAppData(this.prop("name")) as ApplicationData;
const { versions } = data;
const these: string[] = versions.map((v) => v.version);
return lodash.uniq(these);
}

static getUniqueAvailableNames() {
return allApplications;
}

getExecutableByName(name?: string) {
return new Application.Executable(
getExecutableConfig({
appName: this.prop("name"),
execName: name,
}),
);
}

getExecutableByConfig(config: {name: string} | null | undefined = null) {
return config ? this.getExecutableByName(config.name) : this.defaultExecutable;
}
}

export const Application = ApplicationMixin(NamedDefaultableHashedInMemoryEntity);
export type Application = InstanceType<typeof Application>;
get defaultExecutable() {
return this.getExecutableByName();
}

// override upon inheritance
// eslint-disable-next-line class-methods-use-this
get allowedModelTypes() {
return [];
}

get summary() {
return this.prop("summary");
}

get version() {
return this.prop("version");
}

get build() {
return this.prop("build");
}

get shortName() {
return this.prop("shortName", this.prop("name"));
}

get executables() {
const tree = getAppTree(this.prop("name"));
return Object.keys(tree)
.filter((key) => {
const { supportedApplicationVersions } = tree[key];
return (
!supportedApplicationVersions ||
supportedApplicationVersions.includes(this.prop("version"))
);
})
.map((key) => {
return new Application.Executable({ ...tree[key], name: key });
});
}

get hasAdvancedComputeOptions() {
return this.prop("hasAdvancedComputeOptions");
}

get isLicensed() {
return this.prop("isLicensed");
}

get isUsingMaterial() {
const materialUsingApplications = ["vasp", "nwchem", "espresso", "exabyteml"];
return materialUsingApplications.includes(this.name);
}
}
Loading

0 comments on commit 2ecef50

Please sign in to comment.