X-Framework Documentation
website·Indexed 31 days ago
https://www.bluelibs.com/docs/A Node and TypeScript-based server framework featuring a BaseBundle architecture. The ecosystem includes a variety of bundles for MongoDB (v1.8.6), Apollo (v2.1.2), React, NextJS, SQL, and security management, as well as a CLI generator (v1.15.20) and specialized tools for session management, I18N, and S3 uploads.
What's inside X-Framework
- X-Framework is a full-stack framework designed for high-speed development of enterprise applications, CRMs, and serverless backends. It is built on a fixed stack to optimize developer experience, utilizing MongoDB for the database, Apollo/GraphQL for the API layer, and Nova for high-performance relational data fetching (which is designed to be faster than SQL and Mongoose in various scenarios). The administration layer is built using Ant Design.
Overview of Meteor framework features and limitations
Meteor is a JavaScript framework launched in 2012 designed for high developer productivity and real-time capabilities. While innovative, it faced several architectural challenges that impacted its long-term adoption.
Key Features:
- Blaze: A reactive UI layer (Handlebars coupled with jQuery).
- Real-time Data: Everything is real-time via websockets with MongoDB as the default server database.
- Zero-Config Deployment: Simplified cloud deployment via
meteor deploy. - Cross-platform: Ability to transform web apps into native applications using Cordova.
- Atmosphere: A dedicated package ecosystem separate from NPM (prior to version 1.3).
Critical Limitations:
- Database Lock-in: Forced use of MongoDB to access core framework features.
- DDP (Distributed Data Protocol): A proprietary websocket-based RPC mechanism using EJSON. It lacked straightforward clients for non-JS languages (e.g., Python, Ruby) without custom REST endpoints.
- Scaling Issues: Live-data relied on tailing the MongoDB oplog, which caused performance bottlenecks as the number of instances and traffic increased.
- Monolithic Architecture: Coupled frontend and backend, making it difficult to adopt microservices or serverless platforms.
Overview of the BlueLibs Ecosystem
BlueLibs is a TypeScript-based ecosystem of npm packages designed for scalable application development and rapid prototyping. It is organized into three hierarchical layers:
- Foundation: The base layer containing core logic for bundle management (initialization, testing, async event handling), serialization, logging, validation, and integrations with Express, Apollo, GraphQL, and databases (MongoDB, PostgreSQL, MySQL). It includes an abstract security layer with 500+ authentication strategies.
- X-Framework: A fullstack framework utilizing Apollo GraphQL and MongoDB on the backend and React on the frontend. It includes a terminal-based code generator (
x), cronjob support, S3-integrated uploads with image manipulation, and React UI tooling for administration interfaces. - Blueprint: A high-level tool used to generate X-Framework compatible code, including backend collections, GraphQL entities (queries, mutations, inputs), services, CRUDs, and corresponding admin UI forms and paginated lists.
Generate X-Framework project and microservice components
The X-Framework CLI provides several commands to scaffold the architecture of an application:
x:project: Creates a project, defined as a set of interacting microservices (e.g., main API, admin frontend, web frontend).x:microservice: Creates a backend or frontend microservice using the X-Framework.x:bundle: Creates an additional bundle. Use this when logic needs to be reused outside the defaultAppBundle. Avoid if the bundle depends onAppBundle.
Get started with BlueLibs X-Framework and Blueprint
BlueLibs provides a layered architecture consisting of Foundation (common tools), X-Framework (designed for MongoDB, GraphQL, and React), and Blueprint (code generator for X-Framework). To start a new project, you must have MongoDB and Node 16 installed. The process involves installing the X CLI, initializing a project, and generating the blueprint code.# Install the X CLI globally npm i -g @bluelibs/x # Initialize project (follow the interactive prompts) x # Navigate to project directory cd project # Generate Blueprint code npm run blueprint:generate # Start the API npm run start:api # Start the Admin UI npm run start:adminUnderstand Bundles and Services in Bluelibs
Bluelibs uses a modular architecture based on Bundles and Services:
- Bundles: Self-contained modules that encapsulate a domain of logic (e.g., database, API). They provide lifecycle methods like
.prepare()(to set tokens in the container) and.init()(to warm up services or start event loops). Bundles can define dependencies using.extend()andaddDependency(). - Services: Injectable singletons managed by
typeDIand itsContainer. Services encapsulate interaction with entities and are the core components of bundles. Services from one bundle can be imported into another, provided the source bundle is registered in the kernel.
- Bundles: Self-contained modules that encapsulate a domain of logic (e.g., database, API). They provide lifecycle methods like
BlueLibs Core environment support and isomorphism
BlueLibs Core is designed to be isomorphic and runtime-agnostic. It is a lightweight library (~5KB) that can run in Node.js, Deno, the Browser, React Native, and Electron apps, allowing the same architectural concepts to be shared across different environments.Understand the X-Framework project directory structure
X-Framework organizes its frontend architecture into bundles to separate concerns. The core structure includes astartupdirectory for the kernel and main styles, and abundlesdirectory (e.g.,UIAppBundle) containing routes, collections for CRUD interactions, components, page-specific logic, and services.- src - startup - kernel.ts - index.ts - styles.scss # Main entry point for styles - bundles - UIAppBundle - routes.tsx # Imports all routes - UIAppBundle.tsx - collections # CRUD module interactions - index.ts - {CollectionName}.collection.ts - components - index.ts - {ComponentName}.tsx - overrides # Component overrides for other bundles - {ComponentName}.tsx - pages - routes.tsx - {PageName} - routes.tsx - {PageName}.tsx - components # Page-specific components - services - {Name}.service.ts - styles - style.scssAccess Guardian authentication state
Theguardian.stateobject provides real-time information about the user's authentication status. Components using this state will re-render automatically when the authentication status changes.const guardian = useGuardian(); const { initialised, // True after first page load, token reading, and user fetching isLoggedIn, // True if user is authenticated hasInvalidToken, // True if stored token expired during initialization fetchingUserData, // True while the me() query is in progress user, // The current user object } = guardian.state; // Check for specific roles const isAdmin = guardian.hasRole(Roles.ADMIN);Implement a custom Passport authentication strategy
To add a new authentication method (e.g., Facebook), create a class that extendsPassportAuthenticator. You must implementcreateStrategy()to return a Passport strategy androute()to define the Express authentication and callback endpoints. Register the authenticator via thePassportServiceduring bundle initialization.import * as passport from "passport"; import { Strategy as FacebookStrategy } from "passport-facebook"; import { PassportAuthenticator } from "../models/PassportAuthenticator"; export class FacebookAuthenticator extends PassportAuthenticator { createStrategy() { return new FacebookStrategy( { clientID: "XXX", clientSecret: "XXX", callbackURL: "http://localhost:4000/auth/facebook/callback", }, async (accesstoken, refreshToken, profile, done) => { try { const { isNew, user } = await this.findOrCreate(profile.id); if (isNew) { this.securityService.updateUser(user._id, { /* update data */ }); } done(null, user); } catch (err) { done(err); } } ); } route() { // Redirect to provider this.app.get("/auth/facebook", passport.authenticate(this.name)); // Handle callback this.get( "/auth/facebook/callback", {}, async (err, user, req, res, next) => { const token = await this.getToken(user._id); res.redirect(`https://uihost.com/facebook/success?token=${token}`); } ); } } // Registration in AppBundle class AppBundle extends Bundle { async init() { const passportService = this.container.get(PassportService); passportService.register(FacebookAuthenticator); } }Manage user passwords and authentication
Use thePasswordServiceto attach password credentials to a user, validate passwords, and find users by their username. Note thatisPasswordValidtracks failed attempts and may trigger account suspension unlessfailedAuthenticationAttemptsProcessingis set tofalse.import { SecurityService } from "@bluelibs/security-bundle"; import { PasswordService } from "@bluelibs/password-bundle"; const securityService = container.get(SecurityService); const passwordService = container.get(PasswordService); // 1. Create user and attach password data const userId = await securityService.createUser(); await passwordService.attach(userId, { username: "USERNAME", email: "USERNAME@MAIL.COM", password: "PASSWORD", isEmailVerified: false, }); // 2. Find userId by username const userId = await passwordService.findUserIdByUsername("username"); // 3. Validate password (tracks failed attempts) const isValid = await passwordService.isPasswordValid(userId, "PASSWORD"); // 4. Validate password without triggering account lock/cooldown const isValidBypass = await passwordService.isPasswordValid(userId, "PASSWORD", { failedAuthenticationAttemptsProcessing: false, });Implement the Forgot Password flow
The password reset process involves generating a token, validating that token, and then updating the password using that token.// Generate token to be sent via email const token = await passwordService.createTokenForPasswordReset(userId); // Verify the token is still valid const isTokenValid = await passwordService.isResetPasswordTokenValid(userId, token); // Reset the password await passwordService.resetPassword(userId, token, "NEW_PASSWORD");