@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
214 lines (180 loc) โข 6.82 kB
text/typescript
import "reflect-metadata";
import {
MetadataRegistry,
SchemaBuilder,
SchemaReflector
} from "../../core";
import { MongoDBAdapter } from "../../adapters/mongodb";
import { Neo4jAdapter } from "../../adapters/neo4j";
import { PostgreSQLAdapter } from "../../adapters/postgresql";
import { Repository } from "../../adapters/repository";
// Import the blog entities
import { User } from "../blog/User";
import { Post } from "../blog/Post";
import { Tag } from "../blog/Tag";
// Example using multiple database adapters
async function main() {
console.log("โก Multi-Database Example โก");
// Create a registry and builder
const registry = new MetadataRegistry();
const builder = new SchemaBuilder(registry);
const reflector = new SchemaReflector(registry);
// Register all blog entities
console.log("\n๐ Registering blog entities...");
builder.registerEntities([User, Post, Tag]);
// Create database adapters with the registry
console.log("\n๐ Creating database adapters...");
const mongoAdapter = new MongoDBAdapter(registry, "mongodb://localhost:27017/blog");
const neo4jAdapter = new Neo4jAdapter(registry, "bolt://localhost:7687");
const pgAdapter = new PostgreSQLAdapter(registry, "postgres://postgres:password@localhost:5432/blog");
// Create repositories for different entities using different adapters
console.log("\n๐ Creating repositories with different adapters...");
const userRepo = new Repository<User>(User, mongoAdapter, registry);
const postRepo = new Repository<Post>(Post, neo4jAdapter, registry);
const tagRepo = new Repository<Tag>(Tag, pgAdapter, registry);
// Example: Create some entities
console.log("\n๐ง Creating example entities...");
const user = new User();
user.id = "user1";
user.name = "John Doe";
user.email = "john@example.com";
const post1 = new Post();
post1.id = "post1";
post1.title = "Introduction to Multi-DB Schemas";
post1.content = "This is a post about using multiple databases with TypeScript schemas...";
post1.createdAt = new Date();
post1.author = user;
const post2 = new Post();
post2.id = "post2";
post2.title = "Building GraphQL APIs";
post2.content = "GraphQL provides a powerful way to expose your data...";
post2.createdAt = new Date();
post2.author = user;
const tag1 = new Tag();
tag1.id = "tag1";
tag1.name = "TypeScript";
const tag2 = new Tag();
tag2.id = "tag2";
tag2.name = "Databases";
// Add tags to posts
post1.tags.push(tag1, tag2);
post2.tags.push(tag1);
// Add posts to user
user.posts.push(post1, post2);
// Validate entities (optional)
console.log("\nโ
Validating entities...");
const userValidation = reflector.validateEntity(user);
console.log(`User valid: ${userValidation.valid}`);
if (!userValidation.valid) {
console.log("User validation errors:", userValidation.errors);
}
const post1Validation = reflector.validateEntity(post1);
console.log(`Post valid: ${post1Validation.valid}`);
if (!post1Validation.valid) {
console.log("Post validation errors:", post1Validation.errors);
}
const tag1Validation = reflector.validateEntity(tag1);
console.log(`Tag valid: ${tag1Validation.valid}`);
if (!tag1Validation.valid) {
console.log("Tag validation errors:", tag1Validation.errors);
}
// Save entities to their respective databases
console.log("\n๐พ Saving entities to their respective databases...");
console.log("Saving user to MongoDB...");
try {
await userRepo.save(user);
console.log("User saved successfully!");
} catch (error) {
console.error("Error saving user:", error);
}
console.log("\nSaving posts to Neo4j...");
try {
await postRepo.save(post1);
await postRepo.save(post2);
console.log("Posts saved successfully!");
} catch (error) {
console.error("Error saving posts:", error);
}
console.log("\nSaving tags to PostgreSQL...");
try {
await tagRepo.save(tag1);
await tagRepo.save(tag2);
console.log("Tags saved successfully!");
} catch (error) {
console.error("Error saving tags:", error);
}
// Query entities
console.log("\n๐ Querying entities from different databases...");
console.log("\nQuerying user from MongoDB...");
try {
const foundUser = await userRepo.findById("user1");
console.log("Found user:", foundUser ? `${foundUser.name} (${foundUser.email})` : "Not found");
} catch (error) {
console.error("Error querying user:", error);
}
console.log("\nQuerying post from Neo4j...");
try {
const foundPost = await postRepo.findById("post1");
console.log("Found post:", foundPost ? `"${foundPost.title}" by ${foundPost.author?.name || 'Unknown'}` : "Not found");
} catch (error) {
console.error("Error querying post:", error);
}
console.log("\nQuerying tag from PostgreSQL...");
try {
const foundTag = await tagRepo.findById("tag1");
console.log("Found tag:", foundTag ? foundTag.name : "Not found");
} catch (error) {
console.error("Error querying tag:", error);
}
// Running native queries
console.log("\n๐ง Running native queries...");
console.log("\nRunning a native MongoDB query...");
try {
const result = await userRepo.runNativeQuery(`
{ "aggregate": "users", "pipeline": [ { "$match": { "email": "john@example.com" } } ] }
`);
console.log("MongoDB query result:", result);
} catch (error) {
console.error("Error running MongoDB query:", error);
}
console.log("\nRunning a native Cypher query...");
try {
const result = await postRepo.runNativeQuery(`
MATCH (p:Post)-[:HAS_TAG]->(t:Tag)
WHERE t.name = $tagName
RETURN p.title, p.content
`, { tagName: "TypeScript" });
console.log("Neo4j query result:", result);
} catch (error) {
console.error("Error running Neo4j query:", error);
}
console.log("\nRunning a native SQL query...");
try {
const result = await tagRepo.runNativeQuery(`
SELECT t.name, COUNT(pt.post_id) as post_count
FROM tags t
LEFT JOIN post_tags pt ON t.id = pt.tag_id
GROUP BY t.name
`);
console.log("PostgreSQL query result:", result);
} catch (error) {
console.error("Error running PostgreSQL query:", error);
}
// Clean up connection pools
console.log("\n๐งน Cleaning up connections...");
try {
if (typeof (neo4jAdapter as any).close === 'function') {
await (neo4jAdapter as any).close();
}
if (typeof (pgAdapter as any).close === 'function') {
await (pgAdapter as any).close();
}
} catch (error) {
console.error("Error closing connections:", error);
}
console.log("\nโจ Example complete! โจ");
}
// Run the example
main().catch(error => {
console.error("Error running example:", error);
});