Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"extends": [
"@exabyte-io/eslint-config"
],
"ignorePatterns": [
"dist/"
],
"settings": {
"import/resolver": {
"node": {
"extensions": [
".js",
".jsx",
".ts",
".tsx"
]
}
}
}
}
90 changes: 90 additions & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Continuous Testing and Publication

on: [push]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
run-py-linter:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: [3.10.13]
steps:
- uses: actions/checkout@v7
with: { lfs: true }
- uses: actions/checkout@v7
with: { repository: Exabyte-io/actions, token: "${{ secrets.BOT_GITHUB_TOKEN }}", path: actions }
- name: Run ruff linter
uses: ./actions/py/lint
with: { python-version: "${{ matrix.python-version }}" }

run-py-tests:
needs: run-py-linter
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: [3.10.x, 3.11.x, 3.12.x, 3.13.x]
steps:
- uses: actions/checkout@v7
with: { lfs: true }
- uses: actions/checkout@v7
with: { repository: Exabyte-io/actions, token: "${{ secrets.BOT_GITHUB_TOKEN }}", path: actions }
- name: Run python unit tests
uses: ./actions/py/pytest
with:
python-version: ${{ matrix.python-version }}
unit-test-directory: tests/py
bot-ssh-key: ${{ secrets.BOT_GITHUB_KEY }}

run-js-tests:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x, 22.x]
steps:
- uses: actions/checkout@v7
with: { lfs: true }
- uses: actions/checkout@v7
with: { repository: Exabyte-io/actions, token: "${{ secrets.BOT_GITHUB_TOKEN }}", path: actions }
- name: Run JS validate
uses: ./actions/js/validate
with: { node-version: '20.x', skip-eslint: 'true' }
- name: Run JS tests
uses: ./actions/js/test
with: { node-version: "${{ matrix.node-version }}" }

publish-js-package:
needs: [run-js-tests, run-py-tests, run-py-linter]
runs-on: ubuntu-latest
if: github.ref_name == 'main'
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v7
with: { repository: Exabyte-io/actions, token: "${{ secrets.BOT_GITHUB_TOKEN }}", path: actions }
- name: Publish JS release
uses: ./actions/js/publish
with:
node-version: 20.x
npm-token: ${{ secrets.NPM_TOKEN }}
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
verify-tests: 'false'

publish-py-package:
needs: [run-js-tests, run-py-tests, run-py-linter, publish-js-package]
runs-on: ubuntu-latest
if: github.ref_name == 'main'
steps:
- uses: actions/checkout@v7
with: { lfs: true }
- uses: actions/checkout@v7
with: { repository: Exabyte-io/actions, token: "${{ secrets.BOT_GITHUB_TOKEN }}", path: actions }
- name: Publish python release
uses: ./actions/py/publish
with:
python-version: 3.10.13
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
pypi-api-token: ${{ secrets.PYPI_API_TOKEN }}
publish-tag: 'false'
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
*.tgz
.nyc_output/
coverage/
__pycache__/
*.egg-info/
.pytest_cache/
6 changes: 6 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
npm run transpile
git add dist/
30 changes: 30 additions & 0 deletions .nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"all": true,
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts"
],
"exclude": [
"src/js/generated/**/*",
"tests/**/*",
"**/*.test.ts",
"**/*.spec.ts",
"**/*.d.ts"
],
"reporter": [
"text",
"html",
"lcov"
],
"check-coverage": true,
"branches": 80,
"lines": 85,
"functions": 80,
"statements": 85,
"sourceMap": true,
"instrument": true,
"require": [
"ts-node/register"
]
}
26 changes: 26 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
repos:
- repo: https://github.com/Exabyte-io/pre-commit-hooks
rev: 2023.6.28
hooks:
- id: ruff
exclude: ^tests/fixtures*
- id: black
exclude: ^tests/fixtures*
- id: isort
exclude: ^tests/fixtures*
- id: mypy
exclude: ^tests/fixtures*
- id: check-yaml
exclude: ^tests/fixtures*
- id: end-of-file-fixer
exclude: ^tests/fixtures*|^dist*
- id: trailing-whitespace
exclude: ^tests/fixtures*|^dist*
- repo: local
hooks:
- id: lint-staged
name: lint-staged
language: node
entry: npx lint-staged
verbose: true
pass_filenames: false
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"printWidth": 100,
"tabWidth": 4,
"trailingComma": "all",
"singleQuote": false
}
15 changes: 15 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# LICENSE

Copyright 2026 Exabyte Inc. (Mat3ra.com)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
104 changes: 104 additions & 0 deletions dist/js/Job.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { type NamedInMemoryEntity, InMemoryEntity } from "@mat3ra/code/dist/js/entity";
import { type Defaultable } from "@mat3ra/code/dist/js/entity/mixins/DefaultableMixin";
import { type HasDescription } from "@mat3ra/code/dist/js/entity/mixins/HasDescriptionMixin";
import { type HashedEntity } from "@mat3ra/code/dist/js/entity/mixins/HashedEntityMixin";
import { Taggable } from "@mat3ra/code/dist/js/entity/mixins/TaggableMixin";
import type { AnyObject } from "@mat3ra/esse/dist/js/esse/types";
import type { JobSchema as EsseJobSchema, ExtendedJobSchema } from "@mat3ra/esse/dist/js/types";
import { ComputedEntityMixin } from "@mat3ra/ide/dist/js/compute";
import type { Material } from "@mat3ra/made";
import type WodeWorkflowType from "@mat3ra/wode/dist/js/Workflow";
import { type JobSchemaMixin } from "./generated/JobSchemaMixin";
/**
* Combined Job schema type from ESSE base + extended schemas.
* Uses Partial because not all fields are present at construction time.
*/
export type JobSchema = Partial<EsseJobSchema> & Partial<ExtendedJobSchema> & AnyObject;
/**
* A minimal entity reference — contains at least an `_id` to identify the entity.
*/
export interface EntityReference {
_id: string;
[key: string]: unknown;
}
interface Job extends Defaultable, NamedInMemoryEntity, JobSchemaMixin, Taggable, HashedEntity, ComputedEntityMixin, HasDescription {
compute: EsseJobSchema["compute"];
}
/**
* Job — core non-visual model for a computational job.
*
* This class is host-application-agnostic. It is designed for use in
* standalone packages (jove, job-designer) as well as in the web-app,
* where a host-level subclass may extend it with persistence and routing.
*/
declare class Job extends InMemoryEntity {
_json: JobSchema & AnyObject;
_workflow?: WodeWorkflowType;
constructor(config: JobSchema);
/**
* Initializes derived state (workflow instance, material references) from raw JSON.
*/
initialize(): void;
setProps(json: AnyObject): this;
toJSON(): JobSchema & AnyObject;
/**
* Renders the workflow with the given material context.
* Only valid when the job has a workflow and at least one material.
*/
render(): void;
get statusCls(): string;
/**
* Returns true when the job has a terminal status (finished/error/terminated/timeout).
*/
get isInFinalStatus(): boolean;
get isSubmitted(): boolean;
get isActive(): boolean;
get isError(): boolean;
get isInInitialStatus(): boolean;
get isInRunningStatus(): boolean;
get statusTrack(): Array<{
status: string;
trackedAt: number;
}>;
/** Status track items in chronological order. */
get statusTrackSorted(): Array<{
status: string;
trackedAt: number;
}>;
get submittedTimestamp(): {
status: string;
trackedAt: number;
} | undefined;
get activeTimestamp(): {
status: string;
trackedAt: number;
} | undefined;
get finalTimestamp(): {
status: string;
trackedAt: number;
} | undefined;
get hasBeenActiveMoreThanOnce(): boolean;
/**
* Sets the primary material for this job.
*/
setMaterial(material: Material): void;
/**
* Sets multiple materials for a multi-material job.
*/
setMaterials(materials?: Material[]): void;
get material(): Material | undefined;
get materials(): Material[] | undefined;
setMaterialsSet(materialsSet: EntityReference | undefined): void;
get materialsSet(): EntityReference | undefined;
get workflowInstance(): WodeWorkflowType;
setWorkflow(workflowInstance: WodeWorkflowType): void;
get usedApplicationNames(): string[];
setParent(parentJob: Job): void;
unsetParent(): void;
/**
* Creates a new Job with sensible defaults for a given workflow and material.
*/
static createFromWorkflow(workflow: WodeWorkflowType, material: Material | Material[], extraConfig?: Partial<JobSchema>): Job;
}
export { Job };
export default Job;
Loading