Skip to content

Commit a780079

Browse files
committed
Update demo to use natural createEdge syntax
- Change from createEdge(type, from, to) to createEdge(from, type, to) - Reads naturally: 'job POSTED_BY company' instead of 'POSTED_BY from job to company' - Update job-pipeline.ts example (all 20+ edge creations) - Update index.ts documentation example - Properties parameter remains optional (syntactic sugar)
1 parent b8ff0d9 commit a780079

File tree

7 files changed

+2246
-68
lines changed

7 files changed

+2246
-68
lines changed

examples/job-pipeline.ts

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414

1515
import { GraphDatabase } from '../src/index';
16-
import type { Node } from '../src/types';
16+
import type { Node } from '../src/types/index';
1717
import * as fs from 'fs';
1818

1919
// =============================================================================
@@ -209,75 +209,75 @@ const { companies, jobs, skills, user } = db.transaction((ctx) => {
209209
console.log(`✓ Created user profile`);
210210

211211
// Create POSTED_BY relationships (jobs → companies)
212-
db.createEdge('POSTED_BY', seniorDevJob.id, techCorp.id);
213-
db.createEdge('POSTED_BY', mlEngineerJob.id, dataInc.id);
214-
db.createEdge('POSTED_BY', devopsJob.id, cloudSys.id);
215-
db.createEdge('POSTED_BY', juniorDevJob.id, techCorp.id);
212+
db.createEdge(seniorDevJob.id, 'POSTED_BY', techCorp.id);
213+
db.createEdge(mlEngineerJob.id, 'POSTED_BY', dataInc.id);
214+
db.createEdge(devopsJob.id, 'POSTED_BY', cloudSys.id);
215+
db.createEdge(juniorDevJob.id, 'POSTED_BY', techCorp.id);
216216

217217
// Create REQUIRES relationships (jobs → skills)
218218
// Senior Dev requires TypeScript, React
219-
db.createEdge('REQUIRES', seniorDevJob.id, typescript.id, {
219+
db.createEdge(seniorDevJob.id, 'REQUIRES', typescript.id, {
220220
proficiency_required: 'expert'
221221
});
222-
db.createEdge('REQUIRES', seniorDevJob.id, react.id, {
222+
db.createEdge(seniorDevJob.id, 'REQUIRES', react.id, {
223223
proficiency_required: 'expert'
224224
});
225-
db.createEdge('REQUIRES', seniorDevJob.id, docker.id, {
225+
db.createEdge(seniorDevJob.id, 'REQUIRES', docker.id, {
226226
proficiency_required: 'intermediate'
227227
});
228228

229229
// ML Engineer requires Python, TensorFlow
230-
db.createEdge('REQUIRES', mlEngineerJob.id, python.id, {
230+
db.createEdge(mlEngineerJob.id, 'REQUIRES', python.id, {
231231
proficiency_required: 'expert'
232232
});
233-
db.createEdge('REQUIRES', mlEngineerJob.id, tensorflow.id, {
233+
db.createEdge(mlEngineerJob.id, 'REQUIRES', tensorflow.id, {
234234
proficiency_required: 'expert'
235235
});
236236

237237
// DevOps requires Kubernetes, Docker
238-
db.createEdge('REQUIRES', devopsJob.id, kubernetes.id, {
238+
db.createEdge(devopsJob.id, 'REQUIRES', kubernetes.id, {
239239
proficiency_required: 'expert'
240240
});
241-
db.createEdge('REQUIRES', devopsJob.id, docker.id, {
241+
db.createEdge(devopsJob.id, 'REQUIRES', docker.id, {
242242
proficiency_required: 'expert'
243243
});
244244

245245
// Junior Dev requires TypeScript, React
246-
db.createEdge('REQUIRES', juniorDevJob.id, typescript.id, {
246+
db.createEdge(juniorDevJob.id, 'REQUIRES', typescript.id, {
247247
proficiency_required: 'basic'
248248
});
249-
db.createEdge('REQUIRES', juniorDevJob.id, react.id, {
249+
db.createEdge(juniorDevJob.id, 'REQUIRES', react.id, {
250250
proficiency_required: 'intermediate'
251251
});
252252

253253
console.log(`✓ Created relationships (POSTED_BY, REQUIRES)`);
254254

255255
// Create HAS_SKILL relationships (user → skills)
256-
db.createEdge('HAS_SKILL', jobSeeker.id, typescript.id, {
256+
db.createEdge(jobSeeker.id, 'HAS_SKILL', typescript.id, {
257257
proficiency: 'expert',
258258
years_experience: 4
259259
});
260-
db.createEdge('HAS_SKILL', jobSeeker.id, react.id, {
260+
db.createEdge(jobSeeker.id, 'HAS_SKILL', react.id, {
261261
proficiency: 'expert',
262262
years_experience: 3
263263
});
264-
db.createEdge('HAS_SKILL', jobSeeker.id, python.id, {
264+
db.createEdge(jobSeeker.id, 'HAS_SKILL', python.id, {
265265
proficiency: 'intermediate',
266266
years_experience: 2
267267
});
268-
db.createEdge('HAS_SKILL', jobSeeker.id, docker.id, {
268+
db.createEdge(jobSeeker.id, 'HAS_SKILL', docker.id, {
269269
proficiency: 'intermediate',
270270
years_experience: 2
271271
});
272272

273273
console.log(`✓ Created user skill relationships`);
274274

275275
// Create SIMILAR_TO relationships between jobs
276-
db.createEdge('SIMILAR_TO', seniorDevJob.id, juniorDevJob.id, {
276+
db.createEdge(seniorDevJob.id, 'SIMILAR_TO', juniorDevJob.id, {
277277
similarity_score: 0.75,
278278
reason: 'Same tech stack, different experience level'
279279
});
280-
db.createEdge('SIMILAR_TO', devopsJob.id, seniorDevJob.id, {
280+
db.createEdge(devopsJob.id, 'SIMILAR_TO', seniorDevJob.id, {
281281
similarity_score: 0.45,
282282
reason: 'Both require Docker/infrastructure knowledge'
283283
});
@@ -319,10 +319,10 @@ const applications = db.transaction((ctx) => {
319319
notes: 'Great culture fit, strong technical match',
320320
interview_count: 2
321321
});
322-
db.createEdge('APPLIED_TO', user.id, jobs[0].id, {
322+
db.createEdge(user.id, 'APPLIED_TO', jobs[0].id, {
323323
application_id: seniorDevApp.id
324324
});
325-
db.createEdge('FOR_JOB', seniorDevApp.id, jobs[0].id);
325+
db.createEdge(seniorDevApp.id, 'FOR_JOB', jobs[0].id);
326326
apps.push(seniorDevApp);
327327
console.log(`✓ Applied to: ${jobs[0].properties.title} at TechCorp`);
328328

@@ -333,10 +333,10 @@ const applications = db.transaction((ctx) => {
333333
notes: 'Interested in ML transition, need to strengthen Python',
334334
interview_count: 0
335335
});
336-
db.createEdge('APPLIED_TO', user.id, jobs[1].id, {
336+
db.createEdge(user.id, 'APPLIED_TO', jobs[1].id, {
337337
application_id: mlEngineerApp.id
338338
});
339-
db.createEdge('FOR_JOB', mlEngineerApp.id, jobs[1].id);
339+
db.createEdge(mlEngineerApp.id, 'FOR_JOB', jobs[1].id);
340340
apps.push(mlEngineerApp);
341341
console.log(`✓ Applied to: ${jobs[1].properties.title} at DataInc`);
342342

@@ -347,10 +347,10 @@ const applications = db.transaction((ctx) => {
347347
notes: 'Quick process, received offer',
348348
interview_count: 1
349349
});
350-
db.createEdge('APPLIED_TO', user.id, jobs[3].id, {
350+
db.createEdge(user.id, 'APPLIED_TO', jobs[3].id, {
351351
application_id: juniorDevApp.id
352352
});
353-
db.createEdge('FOR_JOB', juniorDevApp.id, jobs[3].id);
353+
db.createEdge(juniorDevApp.id, 'FOR_JOB', jobs[3].id);
354354
apps.push(juniorDevApp);
355355
console.log(`✓ Applied to: ${jobs[3].properties.title} at TechCorp`);
356356

@@ -370,7 +370,7 @@ console.log('-'.repeat(80));
370370

371371
// Query 1: Find all active jobs
372372
console.log('\n📋 Query 1: All Active Job Postings');
373-
const activeJobs = db.nodes<JobProperties>('Job')
373+
const activeJobs = db.nodes('Job')
374374
.where({ status: 'active' })
375375
.orderBy('salary_max', 'desc')
376376
.exec();
@@ -386,10 +386,10 @@ activeJobs.forEach((job, i) => {
386386

387387
// Query 2: Find jobs by company
388388
console.log('\n\n📋 Query 2: Jobs at TechCorp Solutions');
389-
const techCorpJobs = db.nodes<JobProperties>('Job')
389+
const techCorpJobs = db.nodes('Job')
390390
.connectedTo('Company', 'POSTED_BY', 'out')
391391
.where({ name: 'TechCorp Solutions' })
392-
.exec();
392+
.exec() as Node<JobProperties>[];
393393

394394
console.log(`TechCorp has ${techCorpJobs.length} open positions:\n`);
395395
techCorpJobs.forEach((job, i) => {
@@ -398,10 +398,10 @@ techCorpJobs.forEach((job, i) => {
398398

399399
// Query 3: Find jobs requiring specific skills
400400
console.log('\n\n📋 Query 3: Jobs Requiring TypeScript');
401-
const typescriptJobs = db.nodes<JobProperties>('Job')
401+
const typescriptJobs = db.nodes('Job')
402402
.connectedTo('Skill', 'REQUIRES', 'out')
403403
.where({ name: 'TypeScript' })
404-
.exec();
404+
.exec() as Node<JobProperties>[];
405405

406406
console.log(`Found ${typescriptJobs.length} jobs requiring TypeScript:\n`);
407407
typescriptJobs.forEach((job, i) => {
@@ -414,23 +414,23 @@ console.log(`Analyzing ${user.properties.name}'s skill profile...`);
414414

415415
// Get user's skills
416416
const userSkills = db.traverse(user.id)
417-
.follow('HAS_SKILL', 'out')
418-
.exec();
417+
.out('HAS_SKILL')
418+
.toArray();
419419

420420
console.log(`\nUser has ${userSkills.length} skills in profile:`);
421-
userSkills.forEach(skill => {
421+
userSkills.forEach((skill: Node) => {
422422
console.log(` • ${skill.properties.name}`);
423423
});
424424

425425
// Find jobs requiring those skills
426426
console.log(`\nJobs matching user's skills:\n`);
427427
const matchingJobs = new Map<number, { job: Node<JobProperties>, matchCount: number, skills: string[] }>();
428428

429-
userSkills.forEach(skill => {
430-
const jobsForSkill = db.nodes<JobProperties>('Job')
429+
userSkills.forEach((skill: Node) => {
430+
const jobsForSkill = db.nodes('Job')
431431
.connectedTo('Skill', 'REQUIRES', 'out')
432432
.where({ id: skill.id })
433-
.exec();
433+
.exec() as Node<JobProperties>[];
434434

435435
jobsForSkill.forEach(job => {
436436
if (!matchingJobs.has(job.id)) {
@@ -454,7 +454,7 @@ sortedMatches.forEach((match, i) => {
454454

455455
// Query 5: Application status tracking
456456
console.log('\n\n📋 Query 5: Application Status Dashboard');
457-
const allApplications = db.nodes<ApplicationProperties>('Application').exec();
457+
const allApplications = db.nodes('Application').exec() as Node<ApplicationProperties>[];
458458

459459
console.log(`\nApplication Pipeline Status:\n`);
460460

@@ -471,8 +471,8 @@ Object.entries(statusGroups).forEach(([status, apps]) => {
471471
apps.forEach(app => {
472472
// Get the job for this application
473473
const jobNodes = db.traverse(app.id)
474-
.follow('FOR_JOB', 'out')
475-
.exec();
474+
.out('FOR_JOB')
475+
.toArray();
476476
if (jobNodes.length > 0) {
477477
const job = jobNodes[0] as Node<JobProperties>;
478478
console.log(` • ${job.properties.title} (Applied: ${app.properties.applied_date})`);
@@ -495,11 +495,11 @@ const seniorDevJob = jobs[0];
495495
console.log(`Starting from: ${seniorDevJob.properties.title}\n`);
496496

497497
const similarJobs = db.traverse(seniorDevJob.id)
498-
.follow('SIMILAR_TO', 'both')
499-
.exec();
498+
.both('SIMILAR_TO')
499+
.toArray();
500500

501501
console.log(`Found ${similarJobs.length} similar job(s):\n`);
502-
similarJobs.forEach((job, i) => {
502+
similarJobs.forEach((job: Node, i: number) => {
503503
const typedJob = job as Node<JobProperties>;
504504
console.log(` ${i + 1}. ${typedJob.properties.title}`);
505505
console.log(` ${typedJob.properties.experience_level} level | ${typedJob.properties.location}`);
@@ -536,18 +536,18 @@ console.log(`Starting from: ${mlJob.properties.title}`);
536536

537537
// First, get the company
538538
const company = db.traverse(mlJob.id)
539-
.follow('POSTED_BY', 'out')
540-
.exec()[0] as Node<CompanyProperties>;
539+
.out('POSTED_BY')
540+
.toArray()[0] as Node<CompanyProperties>;
541541

542542
console.log(`Company: ${company.properties.name}\n`);
543543

544544
// Then find all jobs at this company
545545
const companyJobs = db.traverse(company.id)
546-
.follow('POSTED_BY', 'in')
547-
.exec();
546+
.in('POSTED_BY')
547+
.toArray();
548548

549549
console.log(`All positions at ${company.properties.name}:\n`);
550-
companyJobs.forEach((job, i) => {
550+
companyJobs.forEach((job: Node, i: number) => {
551551
const typedJob = job as Node<JobProperties>;
552552
console.log(` ${i + 1}. ${typedJob.properties.title}`);
553553
console.log(` ${typedJob.properties.experience_level} | Status: ${typedJob.properties.status}`);
@@ -561,9 +561,9 @@ console.log('-'.repeat(80));
561561

562562
// Advanced Query 1: Remote jobs with high salary
563563
console.log('\n💼 Query 1: Premium Remote Positions');
564-
const premiumRemote = db.nodes<JobProperties>('Job')
564+
const premiumRemote = (db.nodes('Job')
565565
.where({ remote: true, status: 'active' })
566-
.exec()
566+
.exec() as Node<JobProperties>[])
567567
.filter(job => (job.properties.salary_max || 0) >= 150000)
568568
.sort((a, b) => (b.properties.salary_max || 0) - (a.properties.salary_max || 0));
569569

@@ -576,11 +576,11 @@ premiumRemote.forEach((job, i) => {
576576

577577
// Advanced Query 2: Skills in high demand
578578
console.log('\n\n📈 Query 2: Most In-Demand Skills');
579-
const allSkills = db.nodes<SkillProperties>('Skill').exec();
579+
const allSkills = db.nodes('Skill').exec() as Node<SkillProperties>[];
580580

581581
const skillDemand = allSkills.map(skill => {
582582
// Count how many jobs require this skill
583-
const jobCount = db.nodes<JobProperties>('Job')
583+
const jobCount = db.nodes('Job')
584584
.connectedTo('Skill', 'REQUIRES', 'out')
585585
.where({ id: skill.id })
586586
.count();
@@ -597,7 +597,7 @@ skillDemand.forEach(({ skill, jobCount }, i) => {
597597
// Advanced Query 3: Company comparison
598598
console.log('\n\n🏢 Query 3: Company Comparison');
599599
const companyStats = companies.map(company => {
600-
const jobCount = db.nodes<JobProperties>('Job')
600+
const jobCount = db.nodes('Job')
601601
.connectedTo('Company', 'POSTED_BY', 'out')
602602
.where({ id: company.id })
603603
.count();
@@ -632,7 +632,7 @@ db.transaction((ctx) => {
632632
status: 'offer',
633633
interview_count: 3,
634634
notes: 'Received offer after final round!'
635-
});
635+
}) as Node<ApplicationProperties>;
636636
console.log(`✓ Updated ${jobs[0].properties.title} application:`);
637637
console.log(` Status: ${updatedNode.properties.status}`);
638638
console.log(` Interviews completed: ${updatedNode.properties.interview_count}`);
@@ -656,7 +656,7 @@ db.transaction((ctx) => {
656656
console.log('\n\n📋 STEP 7: Final Application Report');
657657
console.log('-'.repeat(80));
658658

659-
const finalApps = db.nodes<ApplicationProperties>('Application').exec();
659+
const finalApps = db.nodes('Application').exec() as Node<ApplicationProperties>[];
660660

661661
console.log(`\n${user.properties.name}'s Job Search Summary:`);
662662
console.log(`Email: ${user.properties.email}`);
@@ -688,10 +688,10 @@ const offerApps = finalApps.filter(app => app.properties.status === 'offer');
688688
if (offerApps.length > 0) {
689689
console.log('\n🎉 Outstanding Offers:\n');
690690
offerApps.forEach(app => {
691-
const jobNodes = db.traverse(app.id).follow('FOR_JOB', 'out').exec();
691+
const jobNodes = db.traverse(app.id).out('FOR_JOB').toArray();
692692
if (jobNodes.length > 0) {
693693
const job = jobNodes[0] as Node<JobProperties>;
694-
const companyNodes = db.traverse(job.id).follow('POSTED_BY', 'out').exec();
694+
const companyNodes = db.traverse(job.id).out('POSTED_BY').toArray();
695695
const company = companyNodes[0] as Node<CompanyProperties>;
696696

697697
console.log(` • ${job.properties.title} at ${company.properties.name}`);

scripts/README.md

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
11
# sqlite-graph Demo Scripts
22

3-
## Automated Demo Runner
3+
Two demo options available: a simple sequential demo (recommended) and an advanced split-screen demo.
44

5-
Interactive split-screen demonstration of newly implemented features using tmux.
5+
## 🎯 Simple Demo (Recommended)
6+
7+
**File:** `simple-demo.sh`
8+
**Requirements:** Any terminal with color support
9+
**Interactive:** Yes - press Enter to continue between sections
10+
11+
Sequential demonstration that works in any terminal without tmux.
12+
13+
```bash
14+
./scripts/simple-demo.sh
15+
```
16+
17+
**Features:**
18+
- ✅ No tmux dependency
19+
- ✅ Clear, sequential presentation
20+
- ✅ Live code execution for each feature
21+
- ✅ Color-coded output
22+
- ✅ Interactive pauses between sections
23+
24+
**Perfect for:**
25+
- Quick feature overview
26+
- CI/CD environments
27+
- Terminals without tmux
28+
- Simple presentations
29+
30+
---
31+
32+
## 🚀 Automated Split-Screen Demo (Advanced)
33+
34+
**File:** `automated-demo.sh`
35+
**Requirements:** tmux, ts-node, interactive terminal
36+
**Interactive:** Visual only - fully automated execution
37+
38+
Advanced split-screen demonstration using tmux.
639

740
### Quick Start
841

@@ -20,12 +53,16 @@ Interactive split-screen demonstration of newly implemented features using tmux.
2053
./scripts/automated-demo.sh 2 # TransactionContext demo
2154
```
2255

23-
### Features Demonstrated
56+
### Common Features (Both Demos)
57+
58+
Both demos showcase:
2459

2560
1. **TransactionContext API** - Manual commit/rollback with savepoints
2661
2. **Bidirectional Queries** - 'both' direction support in NodeQuery
2762
3. **paths() Wrapper** - Convenient path-finding API
2863

64+
All features include live TypeScript code execution.
65+
2966
### Requirements
3067

3168
- **tmux** - `brew install tmux` (macOS) or `apt install tmux` (Linux)

0 commit comments

Comments
 (0)