A tree-shakable TypeScript implementation of spytial, usable for language integration.
- Client-side only: No Node.js dependencies and tree-shakable.
- Custom Elements for easy embedding in web apps
- Selector Synthesis: Auto-generate CnD selector expressions from examples
- Schema Descriptions: Generate LLM-friendly descriptions of data structures
Generate schema-level descriptions of data instances in multiple formats for LLM consumption, documentation, or analysis. Describes the shape of the data (types, relations, arities) rather than instance-level data.
import { generateAlloySchema, generateSQLSchema, generateTextDescription } from 'spytial-core';
// Generate Alloy-style schema (sig-based)
const alloySchema = generateAlloySchema(dataInstance);
// Output:
// sig Node {
// left: Node
// right: Node
// key: Int
// }
// Generate SQL-style schema (table-based)
const sqlSchema = generateSQLSchema(dataInstance);
// Output:
// CREATE TABLE Node (
// id VARCHAR PRIMARY KEY
// );
// CREATE TABLE left (
// source_Node VARCHAR REFERENCES Node(id),
// target_Node VARCHAR REFERENCES Node(id)
// );
// Generate human-readable description
const textSchema = generateTextDescription(dataInstance);
// Output:
// Types:
// - Node (3 atoms)
// Relations:
// - left: Node -> Node (2 tuples)
// - right: Node -> Node (1 tuple)
// - key: Node -> Int (3 tuples)Use cases:
- LLM Integration: Provide context to language models for generating selectors or constraints
- Documentation: Auto-generate schema documentation for data instances
- Analysis: Understand the structure of complex data models
See Schema Descriptor API for full options and examples.
- CnD (Constraint & Directive) Layout System: Declarative constraint-based graph layouts
- WebCola Integration: Physics-based constraint solver with overlap avoidance
- Multi-format Support: Alloy/Forge, JSON, DOT, Racket, Pyret, TLA+
- Interactive Input Graphs: Built-in components for constraint-aware graph editing
- Projection Support: Dynamic UI controls for Forge/Alloy projection atom selection
Automatically generate selector expressions from examples without writing complex queries:
Note: Synthesis requires SGraphQueryEvaluator. Not available with ForgeEvaluator.
import { synthesizeAtomSelector, synthesizeBinarySelector,
isSynthesisSupported, SGraphQueryEvaluator } from 'spytial-core';
// Check if synthesis is available for your evaluator
const evaluator = new SGraphQueryEvaluator();
if (!isSynthesisSupported(evaluator)) {
console.warn('Synthesis not supported for this evaluator');
}
// Select some atoms and generate the selector
const selector = synthesizeAtomSelector([{
atoms: [alice, bob, charlie],
dataInstance: myInstance
}]);
// Returns e.g., "Student & Adult"
// Generate binary relation selectors for pairs
const pairSelector = synthesizeBinarySelector([{
pairs: [[alice, bob], [charlie, diana]],
dataInstance: myInstance
}]);
// Returns e.g., "friend" or "coworker & SameOffice"Use synthesis to build authoring tools where users select nodes visually and constraints are generated automatically. See Selector Synthesis Documentation for details.
npm install spytial-coreimport { LayoutInstance, parseLayoutSpec, SGraphQueryEvaluator } from 'spytial-core';
// Your CnD spec
const spec = `
right(friend)
align left(Student)
color blue(Professor)
`;
const layoutSpec = parseLayoutSpec(spec);
const evaluator = new SGraphQueryEvaluator();
evaluator.initialize({ sourceData: myDataInstance });
const layoutInstance = new LayoutInstance(layoutSpec, evaluator);
const result = layoutInstance.generateLayout(myDataInstance, {});
// Use result.layout with your visualization libraryimport {
synthesizeAtomSelector,
synthesizeBinarySelector,
createOrientationConstraint,
createColorDirective
} from 'spytial-core';
// User selects nodes in your UI
const selectedAtoms = [aliceAtom, bobAtom, charlieAtom];
// Synthesize a selector that matches these atoms
const selector = synthesizeAtomSelector([{
atoms: selectedAtoms,
dataInstance: myInstance
}]);
// Generate CnD directives
const colorDirective = createColorDirective(selector, '#ff0000');
const orientationConstraint = createOrientationConstraint(selector, ['right']);
// Full spec
const cndSpec = `
${orientationConstraint}
${colorDirective}
`;See the full documentation for advanced synthesis features.
For Forge/Alloy instances with projections, use the ProjectionControls component to let users dynamically select which atoms to project:
import { ProjectionControls, LayoutInstance } from 'spytial-core';
// Generate layout with projections
const layoutResult = layoutInstance.generateLayout(dataInstance, projections);
// Render projection controls with the projection data
<ProjectionControls
projectionData={layoutResult.projectionData}
onProjectionChange={(type, atomId) => {
// Update projection for this type
projections[type] = atomId;
// Regenerate layout with new projections
const newLayout = layoutInstance.generateLayout(dataInstance, projections);
}}
/>The projectionData returned from generateLayout() includes:
type: The signature being projectedprojectedAtom: The currently selected atomatoms: All available atoms for this type
See webcola-demo/projection-controls-demo-vanilla.html for a working example.
Visualize selector and evaluator results by highlighting nodes directly in the graph. This feature allows you to examine selector results in context without triggering a layout refresh.
// Evaluate a unary selector
const result = evaluator.evaluate('Student');
const nodeIds = result.selectedAtoms();
// Highlight the nodes
const graph = document.querySelector('webcola-cnd-graph');
graph.highlightNodes(nodeIds);// Evaluate a binary selector
const result = evaluator.evaluate('friend');
const pairs = result.selectedTwoples(); // [["Alice", "Bob"], ["Charlie", "Diana"]]
// Highlight with visual correspondence
graph.highlightNodePairs(pairs);
// Or with badges showing 1/2 correspondence
graph.highlightNodePairs(pairs, { showBadges: true });// Remove all node highlights
graph.clearNodeHighlights();- Unary selectors: Orange border with glow effect
- Binary selectors:
- First elements: Blue border (e.g., the source of a relation)
- Second elements: Red border (e.g., the target of a relation)
- Optional badges: Shows "1" and "2" to indicate correspondence
See webcola-demo/node-highlighter-demo.html for an interactive demo.
You can use the browser bundle directly from a CDN:
- jsDelivr:
https://cdn.jsdelivr.net/npm/spytial-core/dist/browser/spytial-core-complete.global.js - unpkg:
https://unpkg.com/spytial-core/dist/browser/spytial-core-complete.global.js
Once loaded, use via the global CndCore object:
<script src="https://cdn.jsdelivr.net/npm/spytial-core/dist/browser/spytial-core-complete.global.js"></script>
<script>
const { synthesizeAtomSelector, synthesizeBinarySelector } = CndCore;
// Your code here
const selector = synthesizeAtomSelector([...]);
</script>Generate schema-level descriptions of data instances for LLM consumption or documentation.
Generate an Alloy-style schema with signatures and fields.
import { generateAlloySchema } from 'spytial-core';
const schema = generateAlloySchema(dataInstance, {
includeBuiltInTypes: false, // Exclude built-in types like Int, String
includeTypeHierarchy: true, // Include 'extends' clauses
includeArityHints: false // Add multiplicity hints (one, lone, some, set)
});
// Example output:
// sig Node {
// left: Node
// right: Node
// key: Int
// }Options:
includeBuiltInTypes(default:false) - Include built-in types (Int, String, etc.)includeTypeHierarchy(default:true) - Show type inheritance withextendsincludeArityHints(default:false) - Add multiplicity keywords (experimental)
Generate SQL CREATE TABLE statements for types and relations.
import { generateSQLSchema } from 'spytial-core';
const schema = generateSQLSchema(dataInstance, {
includeBuiltInTypes: false,
includeTypeHierarchy: true
});
// Example output:
// CREATE TABLE Node (
// id VARCHAR PRIMARY KEY
// );
//
// CREATE TABLE left (
// source_Node VARCHAR REFERENCES Node(id),
// target_Node VARCHAR REFERENCES Node(id)
// );Options:
includeBuiltInTypes(default:false) - Include built-in typesincludeTypeHierarchy(default:true) - Add comments showing type inheritance
Generate a human-readable plain text description.
import { generateTextDescription } from 'spytial-core';
const description = generateTextDescription(dataInstance, {
includeBuiltInTypes: false
});
// Example output:
// Types:
// - Node (5 atoms)
// - Person (3 atoms)
//
// Relations:
// - left: Node -> Node (2 tuples)
// - friend: Person -> Person (4 tuples)Options:
includeBuiltInTypes(default:false) - Include built-in types
synthesizeAtomSelector(examples, maxDepth?)- Generate unary selectors (for atoms)synthesizeBinarySelector(examples, maxDepth?)- Generate binary selectors (for pairs)synthesizeAtomSelectorWithExplanation(examples, maxDepth?)- With provenance treesynthesizeBinarySelectorWithExplanation(examples, maxDepth?)- With provenance tree
createOrientationConstraint(selector, directions)- Generate orientation constraint stringscreateAlignmentConstraint(selector, alignment)- Generate alignment constraint stringscreateColorDirective(selector, color)- Generate color directive strings
ProjectionControls- Interactive UI for selecting projection atoms (Forge/Alloy)CombinedInputComponent- Complete data visualization with REPL and layout interfaceInstanceBuilder- Visual graph editor for building data instancesReplInterface/PyretReplInterface- REPL components for interactive evaluation
LayoutInstance- Generate layouts from CnD specsSGraphQueryEvaluator- Evaluate selector expressionsAlloyDataInstance,JSONDataInstance, etc. - Data format adapters
The <webcola-cnd-graph> custom element provides methods for interacting with the rendered graph:
highlightNodes(nodeIds: string[])- Highlight nodes by ID (unary selectors)highlightNodePairs(pairs: string[][], options?)- Highlight node pairs with first/second correspondence (binary selectors)clearNodeHighlights()- Remove all node highlights
getAllRelations()- Get all unique relation nameshighlightRelation(relName: string)- Highlight edges by relation nameclearHighlightRelation(relName: string)- Clear relation highlighting
renderLayout(instanceLayout, options?)- Render a layout with optional prior positionsclear()- Clear the graph and reset stategetNodePositions()- Get current positions of all nodes
See docs/ for detailed documentation.
MIT
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request