Node.js Developer Guide
Other documentationsDemoCommunityGitHub
  • Forest Admin
  • Getting started
    • How it works
    • Quick start
    • Install
      • Create your agent
      • Expose an HTTP endpoint
        • For standalone agents
        • On Express
        • On Koa
        • On Fastify
        • On NestJS
      • Autocompletion & Typings
      • Troubleshooting
    • Migrating legacy agents
      • What's new
      • Pre-requisites
      • Recommendations
      • Migration steps
        • Run new agent in parallel
        • Configure database connection
        • Code transformations
          • API Charts
          • Live Queries
          • Smart Charts
          • Route overrides
          • Smart Actions
          • Smart Fields
          • Smart Relationships
          • Smart Segments
        • Compare schemas
        • Swap agents
      • Post-migration
        • Dropping Sequelize
        • Optimize your agent
  • Data Sources
    • Getting Started
      • Collection selection
      • Naming conflicts
      • Cross-data source relationships
      • Query interface and Native Queries
        • Fields and projections
        • Filters
        • Aggregations
    • Provided data sources
      • SQL (without ORM)
      • Sequelize
      • Mongoose
      • MongoDB
    • Write your own
      • Replication strategy
        • Persistent cache
        • Updating the replica
          • Scheduled rebuilds
          • Change polling
          • Push & Webhooks
        • Schema & References
        • Write handlers
      • Translation strategy
        • Structure declaration
        • Capabilities declaration
        • Read implementation
        • Write implementation
        • Intra-data source Relationships
      • Contribute
  • Agent customization
    • Getting Started
    • Actions
      • Scope and context
      • Result builder
      • Static Forms
      • Widgets in Forms
      • Dynamic Forms
      • Form layout customization
      • Related data invalidation
    • Charts
      • Value
      • Objective
      • Percentage
      • Distribution
      • Leaderboard
      • Time-based
    • Fields
      • Add fields
      • Move, rename and remove fields
      • Override binary field mode
      • Override writing behavior
      • Override filtering behavior
      • Override sorting behavior
      • Validation
    • Hooks
      • Collection hook
      • Collection override
    • Pagination
    • Plugins
      • Provided plugins
        • AWS S3
        • Advanced Export
        • Flattener
      • Write your own
    • Relationships
      • To a single record
      • To multiple records
      • Computed foreign keys
      • Under the hood
    • Search
    • Segments
  • Frontend customization
    • Smart Charts
      • Create a table chart
      • Create a bar chart
      • Create a cohort chart
      • Create a density map
    • Smart Views
      • Create a Map view
      • Create a Calendar view
      • Create a Shipping view
      • Create a Gallery view
      • Create a custom tinder-like validation view
      • Create a custom moderation view
  • Deploying to production
    • Environments
      • Deploy on AWS
      • Deploy on Heroku
      • Deploy on GCP
      • Deploy on Ubuntu
      • Deploy on Azure
    • Development workflow
    • Using branches
    • Deploying your changes
    • Forest Admin CLI commands
      • init
      • login
      • branch
      • switch
      • set-origin
      • push
      • environments:create
      • environments:reset
      • deploy
  • Under the hood
    • .forestadmin-schema.json
    • Data Model
      • Typing
      • Relationships
    • Security & Privacy
Powered by GitBook
On this page
  • Why migrate?
  • Agnostic to web frameworks and ORMs
  • Support multiple data sources
  • Autocompletion and typing system
  • Functional approach
  • Performance

Was this helpful?

  1. Getting started
  2. Migrating legacy agents

What's new

PreviousMigrating legacy agentsNextPre-requisites

Last updated 1 year ago

Was this helpful?

This is the official documentation of the @forestadmin/agent Node.js agent.

Why migrate?

Breaking changes are not fun, but they are necessary to keep improving the Forest Admin product. The new agent architecture is a big step forward in terms of performance, stability, and features.

Forest Admin released its agent in 2016 when Express was the only popular web framework and typing systems were scarcer. The predominant way to do async programming then was with callbacks.

In the ecosystem of the time, the design of our Agent was sound.

  • Its API had a low learning curve because it was based on Express and Sequelize/Mongoose.

  • The accessibility of our API meant a bigger deal than its performance because Forest Admin customers had smaller projects – being easy to use was more important than speed.

  • The company focused on a reduced number of data sources (PostgreSQL, MySQL, Microsoft SQL, MongoDB).

In the meantime, JavaScript’s ecosystem has substantially evolved, and although we could’ve introduced changes in our API at every turn, this would have greatly disturbed our customers’ daily operations.

Agnostic to web frameworks and ORMs

This new Agent no longer cares about either the web framework or the ORM in use – it natively integrates with , , , and .

Customers working on other frameworks can still use the Agent by mounting it in and by using a reverse proxy.

You can also connect to your database directly and use automatic model introspection: you will no longer need to maintain Sequelize.js models if you are using another ORM for your production app.

We still support Sequelize.js and Mongoose.js, which gives you additional benefits – such as improving code reuse from your application, even though it isn’t required anymore.

createAgent()
  .mountOnExpress(expressApp)
  .mountOnKoa(koaApp)
  .mountOnFastify(fastifyApp)
  .mountOnNest(nestApp)
  .mountOnStandalone(3351, '0.0.0.0');

Support multiple data sources

With the advent of the Software-as-a-Service (SaaS) industry, the number of data sources that you need to manage has increased.

Many apps now use specific data sources for specific features – ElasticSearch for search, Redis for caching, etc – and mix relational and non-relational databases.

With our first Agent, the paradigm was to have a single database connection, and Forest Admin released a different library for each data source type.

createAgent()
  .addDataSource(createMongooseDataSource(mongooseInstance))
  .addDataSource(createSequelizeDataSource(sequelizeInstance))
  .addDataSource(createSqlDataSource('postgres://localhost:5432/my_database'));

Autocompletion and typing system

In 2016, the vast majority of projects did not use a typing system.

When coding you will get autocompletion and type-checking on your models.

sandro@forestadmin $ tsc
src/forest/card.ts:6:61: error TS2820
  Type '"customerId"' is not assignable to type '"id" | "is_active" | "customer_id"'.
  Did you mean '"customer_id"'?

6   collection.addManyToOneRelation('customer', 'customer', { foreignKey: 'customerId' });
                                                              ~~~~~~~~~~

Found 1 error in src/forest/card.ts:6

Functional approach

We sell a product made by developers for developers.

As such, our customers have a unique understanding of the value and limits of our product, which makes their feedback more invaluable than in any other industry.

We've made a major change in the way we design our API and are now using a more functional approach: instead of having a generated codebase that you modify, you now start from an empty project and add custom behaviors by registering your logic with side-effect-free functions.

createAgent().customizeCollection('books', books => {
  books.addAction('Allocate ISBN number', {
    scope: 'Single',
    execute: ...
  });
});

Performance

Our first customers were small startups that have grown alongside us. They now harbor dozens of collections and millions of users – we need to be able to scale with them.

Many of the performance improvements that come with this new Agent would not have been possible with the first one because of API stability.

The first Agent’s API is full of compromises between performance and accessibility. Some of those compromises are no longer relevant today, so we have decided to head in a different direction.

We now support multiple data sources in the same project: you can , combine relational and non-relational databases, and use different ORMs for each one.

You are also free to to any data source that you want, even to your in-house APIs.

This is no longer the case and we adapted to that change as well: the new agent is completely written in , and on the databases that are plugged into your agent.

As a customer, the new : you won't be dealing with low-level concepts such as "routes" or "query-string", but instead you will be dealing with "actions", "fields", and "segments".

Express
Fastify
Nest.js
Koa
standalone mode
connect as many as you need
implement your connectors
TypeScript ↗
automatically generates type definitions
API is much higher-level