@semtalk/tbase
v1.0.38
Published
`tbase` is the in-memory model layer behind SemTalk. It gives you one object graph that holds:
Readme
@semtalk/tbase
tbase is the in-memory model layer behind SemTalk. It gives you one object graph that holds:
- classes and instances
- typed attributes and relations
- business concepts like methods, states, and compositions
- system-class metadata like labels and edit-dialog tab specs
- diagrams, nodes, and JSON/XML persistence
This guide is meant to get a new engineer productive quickly.
Mental Model
There are three layers that matter most in day-to-day work:
ObjectBaseHolds the whole model and acts as the factory, registry, and lookup service.- model objects
SemTalkClass,SemTalkInstance,SemTalkAssociation,SemTalkAttribute, and the business/system variants. - serializers and UI metadata
OB2JSON,OB2XML, labels, andTabSpecdefinitions.
The most important rule is:
- create everything from
ObjectBase - navigate and mutate from the returned objects
- persist with
OB2JSONorOB2XML
Importing
import {
ObjectBase,
OB2JSON,
SemTalkRelation,
SemTalkValueType,
} from "@semtalk/tbase";Quick Start
import { ObjectBase, OB2JSON } from "@semtalk/tbase";
const tb = new ObjectBase();
tb.SetModelAttribute("modname", "DemoModel");
const person = tb.MakeClass("Person");
const company = tb.MakeClass("Company");
const alice = person.MakeInstance("Alice");
alice.SetValue("firstName", "Alice");
alice.SetValue("isActive", true);
alice.MakeAssociation("worksFor", company);
const codec = new OB2JSON();
const json = codec.SaveJSON(tb);
const loaded = new ObjectBase();
codec.LoadJSON(loaded, json);If you only remember one workflow, remember that one.
Core Concepts
ObjectBase
ObjectBase is the root container for the whole model.
Common things you do with it:
- create objects:
MakeClass,MakeBusinessClass,MakeSystemClass,MakeInstance - create reusable types:
MakeAttributeType,MakeAssociationType,MakeMethodType,MakeStateType,MakeDiagramType - find objects:
FindClass,FindInstance,FindAssociationType,FindObjectByID - enumerate:
AllClasses,AllInstances,AllObjects,AllAssociationTypes - persist: pass it to
OB2JSONorOB2XML
Typical setup:
const tb = new ObjectBase();
tb.SetModelAttribute("modname", "OrderModel");
tb.SetModelAttribute("currentnsp", "en");Useful model attributes:
modname: model namecurrentnsp: active language/namespaceshowNamespace: whether captions show namespaces
Classes and Instances
Use classes for types and instances for concrete objects.
const person = tb.MakeClass("Person");
const alice = person.MakeInstance("Alice");Important methods on classes:
MakeInstance(name?)AddSubclassOf(superClass)SuperClasses()AllSuperClasses()AllSubClasses()IsParent(classOrSuperClass)
Important methods on instances:
ClassOf()SetClass(newClass)ToClass()
Attributes
The simplest way to work with attributes is through SetValue and GetValue.
alice.SetValue("priority", "high");
const value = alice.GetValue("priority");Under the hood, tbase creates an attribute type if needed and then creates an attribute on the object.
If you need the real attribute object:
const attr = alice.MakeAttribute("isActive", false);
attr.ValueType = SemTalkValueType.Boolean;
attr.Min = 0;
attr.Max = 1;Useful attribute APIs:
FindAttribute(nameOrType)Attributes()AllAttributes()AllAttributeTypes()GetAttributeOwner(nameOrType)
Inheritance behavior:
- local attributes shadow inherited ones with the same attribute type name
AllAttributes()returns local attributes first, then inherited onesGetAttributeOwner()returns the nearest class in the hierarchy that defines the attribute
Associations
Relations are first-class objects.
alice.MakeAssociation("worksFor", company);Useful APIs:
MakeAssociation(nameOrType, toObject)Associations()InvAssociations()HasDirectLink(nameOrType, target)HasLink(nameOrType, target)LinkedObjects(nameOrType, recursive?)InvLinkedObjects(nameOrType, recursive?)AllAssociations()
Notes:
MakeAssociation()reuses an existing link if the same source, relation type, and target already existHasLink()follows recursive paths and is cycle-safeAllAssociations()includes inherited associations; in raw results it can also include the actualsubClassOf_inheritance link
Inheritance and Validity
Hierarchy lookup is a major part of tbase.
Examples:
const root = tb.MakeBusinessClass("Root");
const middle = tb.MakeBusinessClass("Middle");
const leaf = tb.MakeBusinessClass("Leaf");
middle.AddSubclassOf(root);
leaf.AddSubclassOf(middle);
root.SetValue("shared", "root");
middle.SetValue("shared", "middle");
leaf.GetAttributeOwner("shared"); // middle's attribute
leaf.AllAttributes(); // local first, inherited afterIsValid(dst, rel) is used when deciding whether a relation is allowed to connect to a target object.
In practice:
- class relations can be inherited from superclasses
- target subclasses are accepted when the relation points to a parent class
- unrelated targets are rejected
Business Classes
SemTalkBusinessClass extends SemTalkClass with business semantics:
- methods
- states
- compositions
Create one with:
const order = tb.MakeBusinessClass("Order");Methods and States
order.MakeMethod("Approve");
order.MakeState("Ready");Useful APIs:
- methods:
MakeMethod,FindMethod,FindAMethod,Methods,AllMethods,AllMethodTypes - states:
MakeState,FindState,FindAState,States,AllStates,AllStateTypes
Inheritance behavior matches attributes:
- local definition wins
- inherited methods/states are visible via the
All...andFindA...helpers
Composition
Compositions are business-specific constraints or conditions attached to an object.
Example:
const ownerClass = tb.MakeBusinessClass("OwnerBusiness");
const owner = ownerClass.MakeInstance("Owner");
const composed = tb.MakeBusinessClass("Order");
const methodType = tb.MakeMethodType("Approve");
const stateType = tb.MakeStateType("Ready");
const attributeType = tb.MakeAttributeType("Priority");
owner.MakeComposition(
composed,
methodType,
stateType,
attributeType,
null,
"=",
false,
"High",
);Useful APIs:
MakeComposition(...)Composition()DeleteComposition()- inverse lists like
InvCompositions()
System Classes
SemTalkSystemClass is where UI behavior and rendering metadata live.
Create one with:
const taskSystem = tb.MakeSystemClass("TaskSystem");Typical use:
- define labels for shapes
- define edit-dialog tabs
- hold UI flags like
Hide,Composeable,Refineable
Business or normal classes often inherit from a system class, directly or indirectly:
const baseTask = tb.MakeClass("BaseTask");
const task = tb.MakeBusinessClass("Task");
baseTask.AddSubclassOf(taskSystem);
task.AddSubclassOf(baseTask);When label resolution runs, tbase walks up the hierarchy to the actual system class.
Labels
Labels define how objects are rendered in diagrams.
Useful APIs on SemTalkSystemClass:
MakeLabel(text, master)MakeClassLabel(text, master)Labels(master?)ClassLabels(master?)FindLabelForMaster(master, text?)
Example:
const taskSystem = tb.MakeSystemClass("TaskSystem");
taskSystem.MakeLabel("Task: Name", "");
taskSystem.MakeClassLabel("Class: Name", "");The label engine supports master-specific labels and the historic slot syntax used by the old Visio-based version.
Tab Specs for Edit Dialogs
Tab specs live on SemTalkSystemClass and define which tabs the UI should show for class and instance dialogs.
Get the definition object:
const system = tb.MakeSystemClass("TaskSystem");
const tabs = system.TabSpecDefinitions();There are four main kinds:
1. Plain tab specs
Simple named tabs.
tabs.MakeTabSpec("General", false); // instance dialog
tabs.MakeTabSpec("Class Data", true); // class dialogKey fields:
Text: visible titleIsClass:truefor class dialogs,falsefor instance dialogsVisibleIndex: sort order
2. Generic relation tabs
Tabs backed by a relation.
tabs.MakeGenericTabSpec(
"Related Orders",
"worksFor",
"Order",
true,
false,
false,
false,
);Arguments:
text: tab titlerelname: relation type nametoobj: target class nameisinst: include instancesisinv: inverse directionisuni: treat as unidirectionalisclass: class dialog or instance dialog
3. Generic attribute tabs
Tabs backed by a list of attributes.
tabs.MakeGenericAttributeTabSpec(
"Audit",
"Metadata",
["CreatedBy", "ChangedBy", "Created", "Changed"],
false,
);4. Tab-spec list tabs
Tabs that group other tabs.
tabs.MakeTabSpecListTabSpec(
"Advanced",
"Details",
["Audit", "Relations"],
false,
);Useful retrieval methods:
TabSpecs()ClassTabSpecs()InstanceTabSpecs()GenericTabSpecs()GenericAttributeTabSpecs()FindTabSpec(name)
Persistence
JSON
OB2JSON is the most relevant serializer for current work.
import { ObjectBase, OB2JSON } from "@semtalk/tbase";
const codec = new OB2JSON();
const json = codec.SaveJSON(tb);
const loaded = new ObjectBase();
codec.LoadJSON(loaded, json);Round-trip coverage in tests currently includes:
- model attributes
- classes and instances
- inheritance links
- attributes and falsy values like
falseand0 - associations
- comments and color metadata
XML
OB2XML also exists, but use JSON first unless you specifically need XML compatibility.
Search and Lookup
Useful global lookup methods on ObjectBase:
FindClass(name)FindBusinessClass(name)FindSystemClass(name)FindInstance(name)FindObjectByID(id)SearchObjects(text)SearchNodes(text, pagingFrom?, pagingTo?)
Prefer ID-based lookup when objects may be renamed.
Events
ObjectBase emits many events internally through PostEvent, for example:
- create/delete
- rename
- attribute changes
- association changes
- load/save
The current callback mechanism uses the internal _callbacks array and expects callback objects with a getMessage(...) method. It works, but it is closer to internal infrastructure than a polished public API, so treat it carefully.
Common Patterns
Create a reusable relation type first
tb.MakeAssociationType(SemTalkRelation.SemTalkProperty, "worksFor");
alice.MakeAssociation("worksFor", company);This is not strictly required, but it can make model setup more explicit.
Start simple with SetValue
Prefer:
obj.SetValue("priority", "high");Only drop down to MakeAttribute() when you need metadata such as:
ValueTypeMinMaxWeight
Use hierarchy helpers instead of manually walking associations
Prefer:
AllAttributes()AllAssociations()FindAMethod()FindAState()GetAttributeOwner()
They encode the shadowing and inheritance rules already.
Gotchas
MakeClass("Name")and similar factory methods return existing objects if the name already exists.- Anonymous instances are auto-named like
ClassName.<id>. - Renaming a class updates anonymous instance names, but not explicitly named instances.
AllAssociations()is a raw association view and can include inheritance links likesubClassOf_.- Inheritance shadowing is name-based for attributes, methods, states, and association types.
- Prefer
FindObjectByID()when identity matters more than caption or name.
Small Cookbook
Build a tiny hierarchy
const root = tb.MakeBusinessClass("Root");
const child = tb.MakeBusinessClass("Child");
child.AddSubclassOf(root);
root.SetValue("priority", "high");
console.log(child.GetValue("priority"));
console.log(child.GetAttributeOwner("priority")?.Owner.ObjectName);Traverse a relation graph
const a = tb.MakeClass("A");
const b = tb.MakeClass("B");
const c = tb.MakeClass("C");
a.MakeAssociation("rel", b);
b.MakeAssociation("rel", c);
console.log(a.HasLink("rel", c)); // true
console.log(a.LinkedObjects("rel", true)); // [b, c]Configure a system class for UI
const system = tb.MakeSystemClass("TaskSystem");
system.MakeLabel("Task: Name", "");
system.MakeClassLabel("Task Type: Name", "");
const tabs = system.TabSpecDefinitions();
tabs.MakeTabSpec("General", false);
tabs.MakeGenericAttributeTabSpec("Audit", "Metadata", ["CreatedBy", "ChangedBy"], false);Where to Look Next
Good source files for learning the code:
Good examples in tests:
Package Maintenance
npm login
npm run build
npm publish --access=public