Skip to content

createApp

createApp(options) builds an App — a bounded context with its container, plugins, wires, and runtime.

Signature

ts
function createApp(options: CreateAppOptions): App

CreateAppOptions

ts
interface CreateAppOptions {
  readonly appName: string
  readonly plugins?: readonly PluginDefinition[]
  readonly handlers?: readonly ActionDefinition[]
  // The container the App owns. Pass a pre-configured one to override
  // the default; otherwise an in-memory container is created.
  readonly container?: Container
  // Optional logger. Defaults to ConsoleLogger.
  readonly logger?: Logger
}

Example

ts
import { createApp, defineRegistry, definePlugin } from "@nwire/app"
import { forgePlugins } from "@nwire/forge"

import { Submission } from "./actor"
import { submissionsByStudent, listSubmissions } from "./projections"
import { autoGrade } from "./workflows/auto-grade"
import { submitAnswer, gradeAnswer } from "./actions"

export function buildSubmissionsApp() {
  return createApp({
    appName: "submissions",
    registry: defineRegistry({
      handlers:    [submitAnswer, gradeAnswer, listSubmissions],
      actors:      [Submission],
      projections: [submissionsByStudent],
      workflows:   [autoGrade],
    }),
    plugins: [
      definePlugin("custom-store", ({ bind }) => {
        bind("notification.queue", new InMemoryNotificationQueue())
      }),
      ...forgePlugins(),
    ],
  })
}

App handle

ts
interface App {
  readonly appName: string
  readonly container: Container
  readonly runtime: Runtime
  readonly interface: { readonly wires: ReadonlyArray<Wire> }

  wire(binding: Binding, handler: HandlerDef): this
  provide(name: string, value: unknown): this
  start(): Promise<void>
  stop(): Promise<void>
}

Boot the App, register wires, mount under an endpoint:

ts
const app = buildSubmissionsApp()
app.wire(post("/submissions"), submitAnswer)
await app.start()

await endpoint("submissions", { port: 3000 })
  .use(httpKoa())
  .mount(app)
  .run()

Multi-app composition

For multi-BC apps, use appCompose(...):

ts
import { appCompose } from "@nwire/app"

const submissions = buildSubmissionsApp()
const enrollments = buildEnrollmentsApp()

const monolith = appCompose(submissions, enrollments)
// monolith.interface.wires contains both apps' wires tagged with source
// adopters mount monolith and dispatch each request through the source
// App's container per wire — no cross-App container leakage

Multi-tenancy

Apps don't declare a tenant model; tenancy lives on envelope.tenant which threads through every dispatch. HTTP adopters read x-tenant from the request by default; bus adopters preserve it across services.

See Multi-tenancy for the patterns.

See also

MIT licensed.