edacation
Version:
Library and CLI for interacting with Yosys and nextpnr.
204 lines • 7.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Project = exports.ProjectOutputFile = exports.ProjectInputFile = void 0;
const util_js_1 = require("../util.js");
const configuration_js_1 = require("./configuration.js");
class ProjectInputFile {
constructor(_path, _type) {
this._path = _path;
this._type = _type;
}
get path() {
return this._path;
}
get type() {
return this._type;
}
set type(type) {
this._type = type;
}
static serialize(file) {
return {
path: file.path,
type: file.type
};
}
static deserialize(data, ..._args) {
// Older versions of this module (<= 0.3.9) stored input files as an array of paths instead,
// so we need to migrate if data is a string (single output file).
if (typeof data === 'string') {
data = { path: data, type: 'design' };
}
return new ProjectInputFile(data.path, data.type);
}
}
exports.ProjectInputFile = ProjectInputFile;
class ProjectOutputFile {
constructor(_project, _path, _targetId = null, _stale = false) {
this._project = _project;
this._path = _path;
this._targetId = _targetId;
this._stale = _stale;
}
get path() {
return this._path;
}
get targetId() {
return this._targetId;
}
set targetId(id) {
if (id !== null && this._project.getTarget(id) === null) {
throw new Error(`Invalid target id: ${id}`);
}
this._targetId = id;
}
get target() {
if (!this._targetId)
return null;
return this._project.getTarget(this._targetId);
}
get stale() {
return this._stale;
}
set stale(isStale) {
this._stale = isStale;
}
static serialize(file) {
return {
path: file.path,
targetId: file.targetId,
stale: file.stale
};
}
static deserialize(project, data, ..._args) {
// Older versions of this module (<= 0.3.12) stored output files as an array of paths instead,
// so we need to migrate if data is a string (single output file).
if (typeof data === 'string') {
data = { path: data, targetId: null, stale: false };
}
return new ProjectOutputFile(project, data.path, data.targetId, data.stale);
}
}
exports.ProjectOutputFile = ProjectOutputFile;
class Project {
constructor(name, inputFiles = [], outputFiles = [], configuration = configuration_js_1.DEFAULT_CONFIGURATION) {
this.name = name;
this.inputFiles = inputFiles.map((file) => ProjectInputFile.deserialize(file));
this.outputFiles = outputFiles.map((file) => ProjectOutputFile.deserialize(this, file));
const config = configuration_js_1.schemaProjectConfiguration.safeParse(configuration);
if (config.success) {
this.configuration = config.data;
}
else {
throw new Error(`Failed to parse project configuration: ${config.error.toString()}`);
}
// Trigger a config 'update' to deploy any modifications it might want to make
this.updateConfiguration({});
}
getName() {
return this.name;
}
getInputFiles() {
return this.inputFiles;
}
hasInputFile(filePath) {
return this.getInputFile(filePath) !== null;
}
getInputFile(filePath) {
return this.inputFiles.find((file) => file.path === filePath) ?? null;
}
addInputFiles(files) {
for (const file of files) {
if (!this.hasInputFile(file.path)) {
const inputFile = new ProjectInputFile(file.path, file.type ?? 'design');
this.inputFiles.push(inputFile);
}
}
this.inputFiles.sort((a, b) => {
return a < b ? -1 : 1;
});
}
removeInputFiles(filePaths) {
this.inputFiles = this.inputFiles.filter((file) => !filePaths.includes(file.path));
}
getOutputFiles() {
return this.outputFiles;
}
hasOutputFile(filePath) {
return this.getOutputFile(filePath) !== null;
}
getOutputFile(filePath) {
return this.outputFiles.find((file) => file.path === filePath) ?? null;
}
addOutputFiles(files) {
for (const file of files) {
const existingOutFile = this.getOutputFile(file.path);
if (existingOutFile) {
// File already exists, so we don't want to add it again.
// But, we should make sure the target ID gets updated and set `stale` to false.
existingOutFile.targetId = file.targetId;
existingOutFile.stale = false;
continue;
}
const outputFile = new ProjectOutputFile(this, file.path, file.targetId);
if (outputFile.target === null)
throw new Error(`Invalid target ID: ${file.targetId}`);
this.outputFiles.push(outputFile);
}
this.outputFiles.sort((a, b) => {
return a < b ? -1 : 1;
});
}
removeOutputFiles(filePaths) {
this.outputFiles = this.outputFiles.filter((file) => !filePaths.includes(file.path));
}
expireOutputFiles() {
for (const file of this.outputFiles) {
file.stale = true;
}
}
getConfiguration() {
return this.configuration;
}
updateConfiguration(configuration) {
this.configuration = {
...this.configuration,
...configuration
};
// Unset 'lingering' output file target IDs
for (const outFile of this.outputFiles) {
if (!outFile.target)
outFile.targetId = null;
}
}
getTarget(id) {
const targets = this.configuration.targets;
return targets.find((target) => target.id === id) ?? null;
}
static serialize(project) {
return {
name: project.name,
inputFiles: project.inputFiles.map((file) => ProjectInputFile.serialize(file)),
outputFiles: project.outputFiles.map((file) => ProjectOutputFile.serialize(file)),
configuration: project.configuration
};
}
static deserialize(data, ..._args) {
const name = data.name;
const inputFiles = data.inputFiles ?? [];
const outputFiles = data.outputFiles ?? [];
const configuration = data.configuration ?? {};
return new Project(name, inputFiles, outputFiles, configuration);
}
static loadFromData(rawData) {
const data = (0, util_js_1.decodeJSON)(rawData);
const project = Project.deserialize(data);
return project;
}
static storeToData(project) {
const data = Project.serialize(project);
return (0, util_js_1.encodeJSON)(data, true);
}
}
exports.Project = Project;
//# sourceMappingURL=project.js.map