UpfrontJS Documentation

website·Indexed 31 days ago

https://upfrontjs.com/

A model-centric data handling solution providing a framework for managing API requests, data casting, and entity relationships. It includes features such as the Calliope model system for query building and attribute management, a Collection class for data manipulation, and utility helpers for pagination, event emitting, and global configuration.

Tokens
43.9K
Snippets
258
Records
307
Agent score
61%

What's inside UpfrontJS

  1. Overview of ModelCollection

    ModelCollection is a subclass of Collection that ensures only Model instances are included. It inherits all Collection methods, but overrides several to use the model's is method or primary key for comparisons. Overridden methods include: unique, hasDuplicates, duplicates, diff, only, except, intersect, delete, union, and includes. Additionally, the map method dynamically returns a ModelCollection if the callback returns a Model; otherwise, it returns a standard Collection.
  2. Overview of UpfrontJS data handling

    UpfrontJS is a model-centric data handling solution that allows developers to use expressive, concise syntax similar to back-end MVC frameworks while remaining back-end agnostic. It provides a unified API to abstract data fetching and manipulation, making it a maintainable alternative to repetitive AJAX requests or overly specific state management getters. It can be used for on-demand data fetching or as a complement to state management libraries. It is compatible with multiple environments, including Node.js, React Native, and Electron.
    import User from '@models/User';
    
    // Fetch students where is_student is true and include their grades
    const students = await User.where('is_student', true).with('grades').get();
    
    // Filter students by average grade and extract only their names
    const excellentStudentNames = students
        .filter(student => student.grades.average('value') > 4)
        .pluck('name');
  3. Overview of ModelCollection behavior

    ModelCollection is a subclass of Collection. It ensures that only Model objects are included in the collection. Several inherited methods—including unique, hasDuplicates, duplicates, diff, only, except, intersect, delete, union, and includes—have been updated to use the model's is method or the model's primary key for comparisons. Additionally, the map method dynamically returns a ModelCollection if the callback returns a Model; otherwise, it returns a standard Collection.
  4. Initialize and use the EventEmitter singleton

    The EventEmitter is a singular object used to react to events emitted throughout your app's lifecycle. Events are executed in the order they were added to the emitter. Use EventEmitter.getInstance<T>() to retrieve the singleton instance, where T is a type representing your event definitions.
    import { EventEmitter } from '@upfrontjs/framework';
    import type { MyEvents } from '../types';
    
    const emitter = EventEmitter.getInstance<MyEvents>();
  5. Use ApiResponseHandler to process API responses

    ApiResponseHandler is the default implementation of the HandlesApiResponse interface. It is responsible for processing the ApiResponse objects returned by the ApiCaller method. Developers can override its methods to customize how API responses are handled globally or for specific services.
  6. Handle API responses using ApiResponseHandler

    ApiResponseHandler is the default implementation of the HandlesApiResponse interface. It is responsible for processing the ApiResponse returned by the ApiCaller method. Developers can override its methods to customize how API responses are handled globally within the application.
  7. Initialize and use the EventEmitter singleton

    The EventEmitter is a singular object used to react to events emitted throughout an app's lifecycle. Events are executed in the order they were added to the emitter. To use it, obtain the singleton instance via EventEmitter.getInstance<T>(), where T is a type defining your event names.
    import { EventEmitter } from '@upfrontjs/framework';
    import type { MyEvents } from '../types';
    
    const emitter = EventEmitter.getInstance<MyEvents>();
  8. Implement Accessors and Mutators

    Accessors and Mutators allow you to transform values on the fly when reading or writing attributes. They must follow a strict naming convention: get{AttributeName}Attribute() and set{AttributeName}Attribute(), where the attribute name is in PascalCase.
    import { Model } from '@upfrontjs/framework';
    
    export default class User extends Model {
        // Accessor: called when accessing user.fullName
        getFullNameAttribute(name) {
            return name ?? 'no name set';
        }
    
        // Mutator: called when setting user.fullName = 'Value'
        setFullNameAttribute(name) {
            this.attributes.fullName = name.startsWith(this.title + ' ') 
                ? name.slice(this.title.length + 1) 
                : name;
        }
    }
    
    // Usage
    const user = User.make({ title: 'Dr.', fullName: 'John Doe' });
    console.log(user.fullName); // 'Dr. John Doe'
  9. Build models fluently with FactoryBuilder

    The FactoryBuilder (accessed via Model.factory()) provides a fluent API to customize model creation:

    • times(n): Specifies the number of models to create. If n > 1, it returns a ModelCollection instead of a single model.
    • with(relation): Adds relationships inline. You can pass a model constructor or another FactoryBuilder instance. An optional second argument can specify the relation name.
    // Create 3 users
    User.factory().times(3).create(); // Returns ModelCollection
    
    // Create user with a related Contract
    User.factory().with(Contract).create().contract; // Returns Contract
    
    // Create user with multiple related Shifts
    User.factory().with(Shift.factory().times(2)).create().shifts; // Returns ModelCollection
  10. Determine the target branch for pull requests

    Until the project reaches a stable version (v1), all pull requests must be based on and targeted toward the main branch. Once v1 is reached, main will be merged into the release/0.x branch.
  11. Send API requests without using Models

    You can interact with the API directly using GlobalConfig to retrieve the api caller and apiResponseHandler, bypassing the Model layer entirely. This is useful for generic endpoints or form submissions.
    import { GlobalConfig } from '@upfrontjs/framework';
    
    const config = new GlobalConfig();
    const handler = new (config.get('apiResponseHandler'));
    const api = new (config.get('api'));
    
    const form = new FormData();
    // ... collect form entries
    
    const response = await handler.handle(
        api.call(
            config.get('baseEndPoint').finish('/') + 'form',
            'POST',
            form,
            { 'X-Requested-With': 'Upfront' },
            { query: { parameters: 'to encode' } }
        )
    );