@nodescript/core
Version:
Visual programming language for Browser and Node
169 lines • 5.26 kB
JavaScript
import { clone } from '../util/clone.js';
import { evaluateEscapes } from '../util/escape.js';
export class PropLineView {
constructor(node, propKey, propLine) {
this.node = node;
this.propKey = propKey;
this.propLine = propLine;
const paramSpec = this.node.getModuleSpec().params[this.propKey] ?? {
schema: { type: 'any' },
};
let schema = paramSpec.schema;
if (['@system/Output', '@system/Result'].includes(this.node.ref)) {
schema = this.graph.moduleSpec.result.schema;
}
this._paramSpec = {
...paramSpec,
schema,
};
}
toJSON() {
return clone(this.propLine);
}
get graph() {
return this.node.graph;
}
get value() {
return this.propLine.value;
}
get linkId() {
return this.propLine.linkId;
}
get linkKey() {
return this.propLine.linkKey;
}
getParamSpec() {
return this._paramSpec;
}
getStaticValue() {
return evaluateEscapes(this.value);
}
isUsingDefaultValue() {
return this.getStaticValue() === '';
}
/**
* Returns the node identified by its linkId.
*/
getLinkNode() {
const { linkId } = this.propLine;
return linkId ? this.graph.getNodeById(linkId) : null;
}
isLinked() {
const { linkId } = this.propLine;
return !!linkId && this.graph.isNodeExists(linkId);
}
canExpand() {
return true;
}
isExpanded() {
return this.canExpand() && this.propLine.expand && this.isLinked();
}
isDeferred() {
return this.getParamSpec().deferred && this.isLinked() && !this.propLine.expand;
}
}
export class PropView extends PropLineView {
constructor(node, propKey, propSpec) {
super(node, propKey, propSpec);
this.propSpec = propSpec;
}
get lineUid() {
return this.node.nodeUid + ':' + this.propKey;
}
getSchema() {
return this.getParamSpec().schema;
}
getEntries() {
return [
...this.getManagedEntries(),
...this.getCustomEntries(),
];
}
/**
* Managed entries appear for each property defined in parent prop's schema.
*
* They are special in a couple ways:
*
* - users can't delete them or change their key
* - the order of managed entries is predefined
* - they have stable ids so that they are consistently persisted
*/
getManagedEntries() {
const schema = this.getSchema();
if (schema.type !== 'object') {
return [];
}
const existingEntries = (this.propSpec.entries ?? []).filter(_ => _.managed);
const entries = [];
for (const key of Object.keys(schema.properties ?? {})) {
const id = key.replace(/[^0-9a-z]/i, '_');
const entrySpec = existingEntries.find(_ => _.id === id) ??
{ id, key, value: '', managed: true, expand: false };
entries.push(new PropEntryView(this, entrySpec));
}
return entries;
}
getCustomEntries() {
const entrySpecs = (this.propSpec.entries ?? []).filter(_ => !_.managed);
return entrySpecs.map(_ => new PropEntryView(this, _));
}
isSupportsEntries() {
const schema = this.getSchema();
const { hideEntries } = this.getParamSpec();
return !hideEntries && (schema.type === 'object' || schema.type === 'array');
}
isUsesEntries() {
return this.isSupportsEntries() && this.isListed() && !this.isLinked();
}
hasEntries() {
return (this.propSpec.entries?.length ?? 0) > 0;
}
isAdvanced() {
return !!this.getParamSpec().advanced;
}
isListed() {
if (!this.isAdvanced()) {
return true;
}
// Advanced props are rendered when either:
// - value is specified and non-default
// - prop is linked
// - prop key is explicitly added to node metadata
// - prop has entries
return !!this.node.metadata.listedProps[this.propKey] ||
!this.isUsingDefaultValue() ||
this.isLinked() ||
this.hasEntries();
}
}
export class PropEntryView extends PropLineView {
constructor(parentProp, propEntrySpec) {
super(parentProp.node, parentProp.propKey, propEntrySpec);
this.parentProp = parentProp;
this.propEntrySpec = propEntrySpec;
}
get id() {
return this.propEntrySpec.id;
}
get key() {
return this.propEntrySpec.key;
}
get lineUid() {
return this.parentProp.lineUid + ':' + this.propEntrySpec.id;
}
isManaged() {
return this.propEntrySpec.managed;
}
getSchema() {
const baseSchema = this.parentProp.getSchema();
switch (baseSchema.type) {
case 'array':
return baseSchema.items ?? { type: 'any' };
case 'object':
return baseSchema.properties?.[this.key] ?? baseSchema.additionalProperties ?? { type: 'any' };
default:
return { type: 'any' };
}
}
}
//# sourceMappingURL=PropView.js.map