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.

Tokens
56.6K
Snippets
332
Records
360
Agent score
62%

What's inside X-Framework

  1. Overview of X-Framework architecture

    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.
  2. 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.
  3. 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:

    1. 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.
    2. 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.
    3. 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.
  4. 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 default AppBundle. Avoid if the bundle depends on AppBundle.
  5. 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:admin
  6. Understand 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() and addDependency().
    • Services: Injectable singletons managed by typeDI and its Container. 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.
  7. 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.
  8. Understand the X-Framework project directory structure

    X-Framework organizes its frontend architecture into bundles to separate concerns. The core structure includes a startup directory for the kernel and main styles, and a bundles directory (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.scss
  9. Access Guardian authentication state

    The guardian.state object 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);
  10. Implement a custom Passport authentication strategy

    To add a new authentication method (e.g., Facebook), create a class that extends PassportAuthenticator. You must implement createStrategy() to return a Passport strategy and route() to define the Express authentication and callback endpoints. Register the authenticator via the PassportService during 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);
      }
    }
  11. Manage user passwords and authentication

    Use the PasswordService to attach password credentials to a user, validate passwords, and find users by their username. Note that isPasswordValid tracks failed attempts and may trigger account suspension unless failedAuthenticationAttemptsProcessing is set to false.
    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,
    });
  12. 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");