@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
175 lines (174 loc) • 7.36 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigurationSchema = ConfigurationSchema;
exports.ConfigurationReference = ConfigurationReference;
const mobx_state_tree_1 = require("mobx-state-tree");
const configurationSlot_1 = __importDefault(require("./configurationSlot"));
const util_1 = require("./util");
const mst_1 = require("../util/types/mst");
function isEmptyObject(thing) {
return (typeof thing === 'object' &&
!Array.isArray(thing) &&
thing !== null &&
Object.keys(thing).length === 0);
}
function isEmptyArray(thing) {
return Array.isArray(thing) && thing.length === 0;
}
function preprocessConfigurationSchemaArguments(modelName, inputSchemaDefinition, inputOptions = {}) {
var _a;
if (typeof modelName !== 'string') {
throw new Error('first arg must be string name of the model that this config schema goes with');
}
let schemaDefinition = inputSchemaDefinition;
let options = inputOptions;
if ((_a = inputOptions.baseConfiguration) === null || _a === void 0 ? void 0 : _a.jbrowseSchemaDefinition) {
schemaDefinition = {
...inputOptions.baseConfiguration.jbrowseSchemaDefinition,
...schemaDefinition,
};
options = {
...inputOptions.baseConfiguration.jbrowseSchemaOptions,
...inputOptions,
};
options.baseConfiguration = undefined;
}
return { schemaDefinition, options };
}
function makeConfigurationSchemaModel(modelName, schemaDefinition, options) {
const modelDefinition = {};
let identifier;
if (options.explicitlyTyped) {
modelDefinition.type = mobx_state_tree_1.types.optional(mobx_state_tree_1.types.literal(modelName), modelName);
}
if (options.explicitIdentifier && options.implicitIdentifier) {
throw new Error(`Cannot have both explicit and implicit identifiers in ${modelName}`);
}
if (options.explicitIdentifier) {
if (typeof options.explicitIdentifier === 'string') {
modelDefinition[options.explicitIdentifier] = mobx_state_tree_1.types.identifier;
identifier = options.explicitIdentifier;
}
else {
modelDefinition.id = mobx_state_tree_1.types.identifier;
identifier = 'id';
}
}
else if (options.implicitIdentifier) {
if (typeof options.implicitIdentifier === 'string') {
modelDefinition[options.implicitIdentifier] = mst_1.ElementId;
identifier = options.implicitIdentifier;
}
else {
modelDefinition.id = mst_1.ElementId;
identifier = 'id';
}
}
const volatileConstants = {
isJBrowseConfigurationSchema: true,
jbrowseSchema: {
modelName,
definition: schemaDefinition,
options,
},
};
for (const [slotName, slotDefinition] of Object.entries(schemaDefinition)) {
if (((0, mobx_state_tree_1.isType)(slotDefinition) && (0, mobx_state_tree_1.isLateType)(slotDefinition)) ||
(0, util_1.isConfigurationSchemaType)(slotDefinition)) {
modelDefinition[slotName] = slotDefinition;
}
else if (typeof slotDefinition === 'string' ||
typeof slotDefinition === 'number') {
volatileConstants[slotName] = slotDefinition;
}
else if (typeof slotDefinition === 'object') {
if (!slotDefinition.type) {
throw new Error(`no type set for config slot ${modelName}.${slotName}`);
}
try {
modelDefinition[slotName] = (0, configurationSlot_1.default)(slotName, slotDefinition);
}
catch (e) {
throw new Error(`invalid config slot definition for ${modelName}.${slotName}: ${e}`);
}
}
else {
throw new Error(`invalid configuration schema definition, "${slotName}" must be either a valid configuration slot definition, a constant, or a nested configuration schema`);
}
}
let completeModel = mobx_state_tree_1.types
.model(`${modelName}ConfigurationSchema`, modelDefinition)
.actions(self => ({
setSubschema(slotName, data) {
if (!(0, util_1.isConfigurationSchemaType)(modelDefinition[slotName])) {
throw new Error(`${slotName} is not a subschema, cannot replace`);
}
const newSchema = (0, mobx_state_tree_1.isStateTreeNode)(data)
? data
: modelDefinition[slotName].create(data);
self[slotName] = newSchema;
return newSchema;
},
}));
if (Object.keys(volatileConstants).length) {
completeModel = completeModel.volatile(() => volatileConstants);
}
if (options.actions) {
completeModel = completeModel.actions(options.actions);
}
if (options.views) {
completeModel = completeModel.views(options.views);
}
if (options.extend) {
completeModel = completeModel.extend(options.extend);
}
const identifierDefault = identifier ? { [identifier]: 'placeholderId' } : {};
const modelDefault = options.explicitlyTyped
? { type: modelName, ...identifierDefault }
: identifierDefault;
const defaultSnap = (0, mobx_state_tree_1.getSnapshot)(completeModel.create(modelDefault));
completeModel = completeModel.postProcessSnapshot(snap => {
const newSnap = {};
let matchesDefault = true;
for (const [key, value] of Object.entries(snap)) {
if (matchesDefault) {
if (typeof defaultSnap[key] === 'object' && typeof value === 'object') {
if (JSON.stringify(defaultSnap[key]) !== JSON.stringify(value)) {
matchesDefault = false;
}
}
else if (defaultSnap[key] !== value) {
matchesDefault = false;
}
}
if (value !== undefined &&
volatileConstants[key] === undefined &&
!isEmptyObject(value) &&
!isEmptyArray(value)) {
newSnap[key] = value;
}
}
if (matchesDefault) {
return {};
}
return newSnap;
});
if (options.preProcessSnapshot) {
completeModel = completeModel.preProcessSnapshot(options.preProcessSnapshot);
}
return mobx_state_tree_1.types.optional(completeModel, modelDefault);
}
function ConfigurationSchema(modelName, inputSchemaDefinition, inputOptions) {
const { schemaDefinition, options } = preprocessConfigurationSchemaArguments(modelName, inputSchemaDefinition, inputOptions);
const schemaType = makeConfigurationSchemaModel(modelName, schemaDefinition, options);
schemaType.isJBrowseConfigurationSchema = true;
schemaType.jbrowseSchemaDefinition = schemaDefinition;
schemaType.jbrowseSchemaOptions = options;
return schemaType;
}
function ConfigurationReference(schemaType) {
return mobx_state_tree_1.types.union(mobx_state_tree_1.types.reference(schemaType), schemaType);
}
;