Semantic graph types with $.Subject.predicate.Object patterns from Schema.org, GS1, and O*NET.
pnpm add graphdlThe primary way to use graphdl is with the $ proxy:
import $ from 'graphdl'
// Create semantic paths using property access
const path1 = $.Person.worksFor.Organization
const path2 = $.John.hasSkill.TypeScript
const path3 = $.Product.locatedAt.Warehouse
// Convert to string
console.log(String($.Person.hasOccupation.Occupation))
// "$.Person.hasOccupation.Occupation"
// Use in real scenarios
const johnWorksForAcme = $.John.worksFor.Acme
console.log(String(johnWorksForAcme)) // "$.John.worksFor.Acme"import { triple, createTriple, path } from 'graphdl'
// Using builder pattern
const t1 = triple('Person:john').predicate('worksFor').object('Organization:acme').context('https://schema.org').build()
// Using function
const t2 = createTriple('Person:john', 'hasSkill', 'Skill:typescript', {
context: 'https://schema.org',
metadata: { confidence: 0.95 },
})
// Creating semantic paths
const semanticPath = path('Person', 'hasOccupation', 'Occupation')
// Returns: "$.Person.hasOccupation.Occupation"import { graph, node, edge } from 'graphdl'
// Create a semantic graph
const myGraph = graph()
.context('https://schema.org')
.node(
node('john', 'Person', {
name: 'John Doe',
email: 'john@example.com',
})
)
.node(
node('acme', 'Organization', {
name: 'Acme Corp',
})
)
.edge(edge('john', 'worksFor', 'acme'))
.metadata({
created: new Date().toISOString(),
source: 'user-input',
})
.build()
// Export as JSON-LD (with $ prefix)
const jsonld = graph()
.context('https://schema.org')
.nodes([node('john', 'Person', { name: 'John Doe' }), node('acme', 'Organization', { name: 'Acme Corp' })])
.edge(edge('john', 'worksFor', 'acme'))
.toJSONLD()
// Results in:
// {
// $context: 'https://schema.org',
// $graph: [
// { $id: 'john', $type: 'Person', name: 'John Doe' },
// { $id: 'acme', $type: 'Organization', name: 'Acme Corp' }
// ]
// }import $ from 'graphdl'
import type { Thing } from 'schema.org.ai'
import type { ObjectEvent } from 'gs1.org.ai'
import type { Occupation } from 'soc.org.ai'
import { createTriple, graph, node, edge } from 'graphdl'
// Use $ for semantic paths
const personOccupationPath = $.Person.hasOccupation.Occupation
const occupationSkillPath = $.Occupation.requiresSkill.Skill
// Create a person with occupation
const person: Thing = {
$type: 'Person',
$id: 'https://example.com/person/john',
name: 'John Doe',
}
const occupation: Occupation = {
onetCode: '15-1252.00',
title: 'Software Developers',
}
// Link them with a triple
const personOccupation = createTriple(person.$id, 'hasOccupation', occupation.onetCode, { context: 'https://schema.org' })
// Build a graph connecting all three vocabularies
const knowledgeGraph = graph()
.context({
$vocab: 'https://schema.org/',
gs1: 'https://gs1.org/voc/',
onet: 'https://www.onetonline.org/',
})
.node(node(person.$id!, 'Person', person))
.node(node(occupation.onetCode, 'Occupation', occupation))
.edge(edge(person.$id!, 'hasOccupation', occupation.onetCode))
.build()
// Use semantic paths with type safety
console.log(String($.John.worksFor.Acme)) // "$.John.worksFor.Acme"
// GS1 supply chain paths (camelCase)
const shipmentPath = $.Shipment.inTransit.Warehouse
const productPath = $.Product.receiving.DistributionCenter
// O*NET occupation paths
const skillPath = $.Occupation.requiresSkill.Programming
const abilityPath = $.SoftwareDeveloper.requiresAbility.CriticalThinkingimport $ from 'graphdl'
import { parsePath } from 'graphdl'
// Create semantic paths using the $.Subject.predicate.Object pattern
const paths = [
$.Person.hasOccupation.Occupation,
$.Occupation.requiresSkill.Skill,
$.Occupation.requiresAbility.Ability,
$.Organization.owns.Product,
$.Product.locatedAt.Location,
]
// Use the paths
console.log(String($.John.worksFor.Acme))
// "$.John.worksFor.Acme"
// With GS1 dispositions (now camelCase)
$.Shipment.inTransit.Container // "$.Shipment.inTransit.Container"
$.Product.inProgress.Manufacturing // "$.Product.inProgress.Manufacturing"
// With business steps
$.Order.shipping.Customer // "$.Order.shipping.Customer"
$.Inventory.receiving.Warehouse // "$.Inventory.receiving.Warehouse"
// Parse paths back to components
const parsed = parsePath(String($.Person.hasOccupation.Occupation))
console.log(parsed)
// { subject: 'Person', predicate: 'hasOccupation', object: 'Occupation' }interface Triple<S, P, O> {
subject: S
predicate: P
object: O
context?: string
metadata?: TripleMetadata
}interface Graph {
'@context'?: string | Record<string, any>
nodes: Node[]
edges: Edge[]
metadata?: GraphMetadata
}Built-in predicates from:
- Schema.org:
hasOccupation,worksFor,memberOf, etc. - GS1/EPCIS:
containedIn,transformedFrom,locatedAt, etc. - O*NET:
requiresSkill,requiresAbility,performsActivity, etc. - Universal:
is,has,partOf,relatedTo, etc.
GraphDL includes data ingestion scripts for importing industry standard taxonomies and datasets into MDX format with semantic frontmatter.
# Run all ingestion scripts in parallel
pnpm ingest
# Run individual ingestion scripts
pnpm ingest:naics # NAICS industry classifications
pnpm ingest:apqc # APQC process framework
pnpm ingest:unedi # UN/EDIFACT message types
pnpm ingest:zapier # Zapier app integrations-
NAICS - North American Industry Classification System (20 industry sectors)
- Output:
.db/NAICS/ - Format: MDX with
$id: naics:XXand$type: IndustryClassification
- Output:
-
APQC - American Productivity & Quality Center Process Framework (13 categories)
- Output:
.db/APQC/ - Format: MDX with
$id: apqc:X.Xand$type: BusinessProcess
- Output:
-
UN/EDIFACT - UN Electronic Data Interchange For Administration, Commerce and Transport (15 message types)
- Output:
.db/UNEDI/ - Format: MDX with
$id: unedi:XXXXXand$type: EDIMessage
- Output:
-
Zapier - Popular app integrations (15 apps)
- Output:
.db/Zapier/ - Format: MDX with
$id: zapier:app-keyand$type: Integration
- Output:
- Idempotent - Safe to run multiple times, overwrites existing files
- Parallel Execution - All sources run in parallel for maximum efficiency
- Error Handling - Comprehensive error tracking with summary statistics
- Semantic Frontmatter - All files include
$idand$typefor linked data - MDX Format - Human-readable markdown with structured frontmatter
Each ingestion creates MDX files with semantic frontmatter:
---
$id: 'naics:51'
$type: 'IndustryClassification'
code: '51'
title: 'Information'
description: 'Industries engaged in producing and distributing information...'
level: 1
---
# Information (NAICS 51)
Industries engaged in producing and distributing information and cultural products...$- Proxy for creating semantic paths using property access$.Subject.predicate.Object $.John.worksFor.Acme $.Product.locatedAt.Warehouse
triple(subject?)- Create a triple buildercreateTriple(subject, predicate, object, options?)- Create a triple directlygraph()- Create a graph buildernode(id, type, properties?)- Create a nodeedge(source, predicate, target, properties?)- Create an edge
path(subject, predicate, object)- Create a semantic path stringparsePath(pathString)- Parse a semantic path back to components
Error:
WARN Moving // that was installed by a different package manager to "node_modules/.ignored"
ENOENT: no such file or directory, stat '.../ai/packages/graphdl/node_modules/'
Cause: An empty node_modules/ directory exists in the graphdl package. This can happen if:
- You ran npm or yarn by accident in this directory
- A previous pnpm install failed mid-process
- The directory was manually created
Solution:
# From repository root
rm -rf ai/packages/graphdl/node_modules
pnpm installNote: graphdl has zero runtime dependencies (only peer dependencies), so it should never have its own node_modules/ directory when installed via pnpm workspace.
If you see errors like Cannot find module 'graphdl' or import errors:
-
Verify installation:
pnpm list graphdl
-
Check peer dependencies are installed:
pnpm add schema.org.ai gs1.org.ai soc.org.ai
-
Rebuild if needed:
cd ai/packages/graphdl pnpm build
If you see TypeScript errors when importing types from graphdl:
- Ensure peer dependencies are installed (see package.json
peerDependencies) - Check your tsconfig.json includes:
{ "compilerOptions": { "moduleResolution": "node", "esModuleInterop": true, "skipLibCheck": true } }
MIT