DEV Community

Medard Mandane
Medard Mandane

Posted on

Splitting Wasp TS Config?

Splitting Wasp TS Config, Can we do it? (Updated)

Overview

The early support for TS config of Wasp was introduced in v0.15. It's been out for a while. Some of the goals were to support multiple Wasp files, take advantage of built-in TypeScript support for most editors, and lessen the burden of maintaining the codebase. Unfortunately, at the moment, splitting or using multiple Wasp files is a feature we can anticipate in future updates.

However, there is a way we can reduce the lines of code in the wasp file

Part 1: Extracting the pages from main.wasp.ts in 2 steps

One of the ways we can reduce the code in main.wasp.ts is by moving the pages to a different file and exporting it from there. (Can I call this Factory Pattern?)

Step 1: Move the page constants in a file, I'll call it pages.config.ts. Then return.

// pages.config.ts
import { App } from 'wasp-config'

export const pagesConfig = (app: App) => {
  const landingPage = app.page('LandingPage', {
    component: { importDefault: 'LandingPage', from: '@src/landing-page/LandingPage' }
  });
  // other pages

  return {
    landingPage,
    // other pages
  }
}
Enter fullscreen mode Exit fullscreen mode

** I suggest you also nest the file inside a dedicated directory, maybe name it wasp-config

Step 2: Import the pages in main.wasp.ts, pass the app instance to pagesConfig

// main.wasp.ts

import { pagesConfig } from './pages.config.ts'
// other code

const { 
  landingPage,
  // other pages
} from pagesConfig(app)

app.route('LandingPageRoute', { path: '/', to: landingPage });
Enter fullscreen mode Exit fullscreen mode

Part 2: Extracting jobs, query, actions and other configs

Step 1: Move the config to a variable in a new file, let's call it jobs.config.ts. I will give an example for jobs, but the same applies for queries or actions.

// jobs.config.ts

// import the appropriate type to avoid ts errors
import { App, JobConfig } from "wasp-config";

export const jobConfigs = (app: App) => {
  const dailyStatsJobConfig: JobConfig = {
    executor: 'PgBoss',
      perform: {
      fn: { import: 'calculateDailyStats', from: '@src/analytics/stats' }
    },
    entities: ['User', 'DailyStats', 'Logs', 'PageViewSource']
  }

  return {
    dailyStatsJobConfig
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Import and use the config in main.wasp.ts, same with what we did for pages

// main.wasp.ts

import { jobConfigs } from './jobs.config.ts'
// other code

const { 
  dailyStatsJobConfig,
} from jobConfigs(app)

app.job('dailyStatsJob', dailyStatsJobConfig);
Enter fullscreen mode Exit fullscreen mode

Wrap Up

By doing all these extractions, we can significantly reduce the code and somehow organize main.wasp.ts while we wait for the official support for multiple wasp files.

** Please let me know if you have questions or if you found a better solution.

Oh Wait, THERE IS ANOTHER WAY (Update)

Okay, so while working more on the organizing my wasp file I found another way to reduce and organize the code.

Extracting pages, actions -- everything

a more organized main.wasp.ts

Lets first take a look at my main.wasp.ts

import { initApp } from './wasp-config/core.wasp.js'
import { initRoutes } from './wasp-config/routes.wasp.js'
import { initActions } from './wasp-config/actions.wasp.js'
import { initJobs } from './wasp-config/jobs.wasp.js'

// Configure the app here
const app = initApp(
  'OpenSaaS App',
  {
    title: 'OpenSaaS App',
    wasp: { version: '^0.15.0' },
    head: [
      "<meta charset='utf-8' />",
      "<meta name='description' content='Your apps main description and features.' />",
      "<meta name='author' content='OpenSaaS App' />"
      // other meta tags
    ],
  }
);
initRoutes(app);
initActions(app);
initJobs(app);

export default app;
Enter fullscreen mode Exit fullscreen mode

That's just a few lines of and you can immediately tell what's happening here. By organizing it this way, we can work on each section separately. It is also beneficial for devs new to Wasp-lang. This is easier to digest (my personal opinion)

Diving into each section

Below is how I coded each section of the main.wasp.ts. I decided to separate the configs from the declarations because I want to see the list of pages, actions etc clearly

A look at mycore.wasp.ts
import { App, AppConfig, AuthConfig, ClientConfig, DbConfig, EmailSenderConfig } from 'wasp-config'

export const initApp = (appName: string, appConfig: AppConfig): App => {
  const app = new App(appName, appConfig);
  const { authConfig, dbConfig, clientConfig, emailSenderConfig } = config();
  app.auth(authConfig);
  app.db(dbConfig);
  app.client(clientConfig);
  app.emailSender(emailSenderConfig); 
  return app
}
const config = () => {
  const authConfig: AuthConfig = {
    userEntity: 'User',
    // other auth config
  }
  const dbConfig: DbConfig = {
    // db config
  }
  const clientConfig: ClientConfig = {
    // client config
  }
  const emailSenderConfig: EmailSenderConfig = {
    provider: 'SMTP',
    // email sender config
  }
  return { authConfig, dbConfig, clientConfig, emailSenderConfig }
}
Enter fullscreen mode Exit fullscreen mode

** I will just show how I coded the core config. Anyway, I used the same pattern for other sections.

If you want to see a full example using OpenSaaS template please check this gist https://gist.github.com/medardm/263b2c933186eb1a496fa743c756edc7

Top comments (2)

Collapse
 
matijasos profile image
Matija Sosic

Nice one! What have you been using Wasp for?

Collapse
 
medardm profile image
Medard Mandane

Hi Matija! Been using wasp for mostly internal projects that I am not allowed to disclose. But planning to use it for a crypto + ai project in the near future.