### Example Stratify Application Tree Output Source: https://stratifyjs.github.io/docs/application This is an example of the output from `describeTree()` for a simple application structure. ```text 🌳 mod root@m1 (encapsulate=true) 📦 mod child@m2 (encapsulate=true) 📦 mod sibling@m3 (encapsulate=true) ``` -------------------------------- ### Install Stratify Core Package Source: https://stratifyjs.github.io/docs/installation Install the core Stratify package directly using npm if you prefer manual setup over using the CLI to generate a project. ```bash npm install @stratify/core ``` -------------------------------- ### Create and Expose Provider Source: https://stratifyjs.github.io/docs/providers Defines a provider named 'usersRepository' that exposes a 'get' method. Includes optional 'onReady' and 'onClose' hooks for setup and cleanup. ```javascript import { createProvider } from "@stratify/core"; const UsersRepository = createProvider({ name: "usersRepository", expose: () => ({ get: (id) => ({ id, name: "Ada" }), }), // Optional hooks: onReady: async ({ deps, value }) => { /* Some setup */}, onClose: async ({ deps, value }) => { /* Some cleanup */}, }); ``` -------------------------------- ### Application Entrypoint Source: https://stratifyjs.github.io/docs/dip Initializes and starts the Stratify application using the defined `RootModule`. The application listens on port 3000. ```typescript // src/app.ts import { createApp } from "@stratify/core"; import { RootModule } from "./modules/root.module"; const app = await createApp({ root: RootModule }); await app.listen({ port: 3000 }); ``` -------------------------------- ### Create and Register Session Installer Source: https://stratifyjs.github.io/docs/installers This snippet demonstrates how to create a custom installer for session management using Fastify plugins. It registers `@fastify/cookie` and `@fastify/session`, requiring a secret for session security. Use this when session functionality is needed within your application. ```javascript import { createInstaller, createModule } from "@stratify/core"; import fastifyCookie from "@fastify/cookie"; import fastifySession from "@fastify/session"; // Register Fastify core plugins const SessionInstaller = createInstaller({ name: "session", install: async ({ fastify }) => { // If you need to access decorators exposed by plugins // during build time, e.g. to create adapters. // You would have to await the registration: // await fastify.register fastify.register(fastifyCookie); fastify.register(fastifySession, { secret: "a secret with minimum length of 32 characters", }); }, }); const InfrastructureModule = createModule({ name: "infrastructure", encapsulate: false, installers: [SessionInstaller], }); ``` -------------------------------- ### Create Standard Stratify Application Source: https://stratifyjs.github.io/docs/application Use `createApp` to initialize a Stratify application with a root module. The application is automatically prepared with `fastify.ready()` and can be started with `app.listen()`. ```javascript import { createApp } from "@stratify/core"; const app = await createApp({ root, serverOptions: {}, overrides: {}, }); await app.listen({ port: 3000 }); ``` -------------------------------- ### Create Application Hooks with Fastify Source: https://stratifyjs.github.io/docs/hooks Define application lifecycle hooks using `createHooks` with `type: 'app'`. This example adds onReady and onClose hooks for server setup and resource cleanup. ```javascript const appHooks = createHooks({ type: "app", name: "lifecycle", build: ({ builder }) => { builder.addHook("onReady", async () => { // Some setup... }); builder.addHook("onClose", async () => { // Closing resources... }); }, }); ``` -------------------------------- ### Register `@fastify/redis` Installer Source: https://stratifyjs.github.io/docs/adapters Registers the `@fastify/redis` plugin using `createInstaller`. This installer must be registered at a higher-level module with `encapsulate: false`. ```typescript // src/installers/redis.installer.ts import { createInstaller } from "@stratify/core"; import fastifyRedis from "@fastify/redis"; export const RedisInstaller = createInstaller({ name: "redis", install: async ({ fastify }) => { await fastify.register(fastifyRedis, { url: process.env.REDIS_URL, }); }, }); ``` -------------------------------- ### Install Stratify CLI Globally Source: https://stratifyjs.github.io/docs/installation Install the Stratify CLI globally using npm. This command is required before you can use other stratify-cli commands. ```bash npm install -g @stratify/cli ``` -------------------------------- ### Create New Stratify Application Source: https://stratifyjs.github.io/docs/installation Generate a new Stratify application using the installed CLI. This creates a project with ESLint, Prettier, and a modular structure. ```bash npx stratify-cli new my-app ``` -------------------------------- ### Create a Root Module in Stratify Source: https://stratifyjs.github.io/docs/modules Define a root module using `createModule` from `@stratify/core`. Ensure a unique name and configure encapsulation, controllers, hooks, installers, and submodules as needed. ```javascript import { createModule } from "@stratify/core"; const RootModule = createModule({ name: "root", // Required unique name encapsulate: true, // Encapsulate the module (default: true) controllers: [], // HTTP controllers (routes) hooks: [], // Application or HTTP lifecycle hooks installers: [], // Install Fastify utilities (plugins, compilers, parsers, etc.) subModules: [], // Nested modules (domain composition) }); ``` -------------------------------- ### Full Hierarchy Display of Stratify Application Tree Source: https://stratifyjs.github.io/docs/application When modules contain hooks, installers, controllers, adapters, and providers, `describeTree()` displays each layer with dependency nesting for a comprehensive view. ```text 🌳 mod root@m1 (encapsulate=true) 📦 mod sibling@m2 (encapsulate=false) ⚙️ installer a 🔧 prov siblingProv@p1 ⚙️ installer b 🧭 controller a 🔌 adp siblingAdapter 🔧 prov siblingDependent@p2 🔧 prov siblingProv@p1 ``` -------------------------------- ### Create HTTP Hooks with Fastify Source: https://stratifyjs.github.io/docs/hooks Use `createHooks` to define HTTP lifecycle hooks for Fastify. Ensure all handlers are async functions. This example adds onRequest and onResponse hooks. ```javascript import { createHooks } from "@stratify/core"; const httpHooks = createHooks({ // Optional name (used by tree printer) name: "core-http", type: "http", // Optional dependency maps deps: { profiles }, // Optional adapters maps adaps: {}, build: ({ builder }) => { // All handlers must be async. builder.addHook("onRequest", async (req, reply) => { if (!req.headers.authorization) { return reply.code(401).send({ error: "Unauthorized" }); } }); builder.addHook("onResponse", async (_req, reply) => { reply.header("x-content-type-options", "nosniff"); }); }, }); ``` -------------------------------- ### Inspect Stratify Application Tree Source: https://stratifyjs.github.io/docs/application Utilize `describeTree()` to generate a human-readable representation of the Stratify application's module and dependency hierarchy. This includes submodules, hooks, installers, controllers, adapters, and providers. ```typescript import { createApp, createModule } from "@stratify/core"; const root = createModule({ name: "root", subModules: [ createModule({ name: "child" }), createModule({ name: "sibling" }), ], }); const app = await createApp({ root }); console.log(app.describeTree()); ``` -------------------------------- ### Create Project Structure Source: https://stratifyjs.github.io/docs/dip Sets up the necessary directories and files for a Stratify project following the Dependency Inversion Principle. ```bash mkdir -p src/{contracts,services,controllers,bindings,modules} touch src/app.ts touch src/contracts/mailer.ts touch src/services/send-welcome-email.ts touch src/controllers/notifications.controller.ts touch src/bindings/smtp-mailer.ts touch src/modules/notifications.module.ts touch src/modules/root.module.ts ``` -------------------------------- ### Create a Controller with Routes Source: https://stratifyjs.github.io/docs/controllers Define a controller with routes using the `createController` function. Handlers must be async and can infer types from TypeBox schemas. ```javascript import { createController } from "@stratify/core"; import { Type } from "@sinclair/typebox"; const UsersController = createController({ // Optional name (used by tree printer) name: "users", // Optional dependency maps deps: { profiles }, // Optional adapters maps adaps: {}, // async build callback with routes builder build: ({ builder, deps }) => { builder.addRoute({ method: "GET", url: "/users/:id", schema: { // Optional TypeBox schema params: Type.Object({ id: Type.String() }), }, // Handlers must be async handler: async (req) => { const id = req.params.id; // Type is inferred as `string` return deps.profiles.find(id); }, }); }, }); ``` -------------------------------- ### Create Stratify Application with Custom Fastify Instance Source: https://stratifyjs.github.io/docs/application Provide your own Fastify instance to `createApp`. Note that Stratify will call `fastify.ready()` internally on the provided instance. ```javascript import Fastify from "fastify"; import { createApp } from "@stratify/core"; const fastifyInstance = Fastify({ // Server options }); // Some configuration... const app = await createApp({ fastifyInstance, root }); await app.listen({ port: 3000 }); ``` -------------------------------- ### Create Controller Using Domain Service Source: https://stratifyjs.github.io/docs/dip Builds a controller `NotificationsController` that utilizes the `SendWelcomeEmail` service. It defines a POST route to trigger the welcome email. ```typescript // src/controllers/notifications.controller.ts import { createController } from "@stratify/core"; import { Type } from "@sinclair/typebox"; import { SendWelcomeEmail } from "../services/send-welcome-email"; export const NotificationsController = createController({ name: "notifications", deps: { SendWelcomeEmail }, build: ({ builder, deps }) => { builder.addRoute({ method: "POST", url: "/welcome", schema: { body: Type.Object({ to: Type.String({ format: "email" }) }), }, handler: async (req, reply) => { await deps.SendWelcomeEmail.execute(req.body.to); return { ok: true }; }, }); }, }); ``` -------------------------------- ### Create `@fastify/redis` Adapter Source: https://stratifyjs.github.io/docs/adapters Creates an adapter to expose the Redis client, which becomes available via `fastify.redis` after the `@fastify/redis` plugin is registered. ```typescript // src/adapters/redis.adapter.ts import { createAdapter } from "@stratify/core"; import { redisInstaller } from "../installers/redis.installer"; export const RedisAdapter = createAdapter({ expose: ({ fastify }) => fastify.redis, }); ``` -------------------------------- ### Create Fastify Version Adapter Source: https://stratifyjs.github.io/docs/adapters Exposes the running Fastify version using `createAdapter`. This adapter can then be used by controllers. ```typescript import { createAdapter, createController } from "@stratify/core"; // Adapter that exposes the running Fastify version export const VersionAdapter = createAdapter({ expose: ({ fastify }) => fastify.version, }); export const VersionController = createController({ deps: { version: VersionAdapter }, build: ({ builder, deps }) => { builder.addRoute({ method: "GET", url: "/version", handler: async () => ({ version: deps.version }), }); }, }); ``` -------------------------------- ### Create Domain Service with Contract Dependency Source: https://stratifyjs.github.io/docs/dip Creates a domain service `SendWelcomeEmail` that depends on the `Mailer` contract. The `mailer` dependency is injected via `deps`. ```typescript // src/services/send-welcome-email.ts import { createProvider } from "@stratify/core"; import { Mailer } from "../contracts/mailer"; export const SendWelcomeEmail = createProvider({ name: "send-welcome-email", deps: { mailer: Mailer }, expose: ({ mailer }) => ({ async execute(to: string) { mailer.send(to, "Welcome to Stratify!"); }, }), }); ``` -------------------------------- ### Implement Concrete Mailer Provider Source: https://stratifyjs.github.io/docs/dip Provides a concrete implementation `SmtpMailer` for the `Mailer` contract. This provider logs the email sending action to the console. ```typescript // src/bindings/smtp-mailer.ts import { createProvider } from "@stratify/core"; import { MAILER_TOKEN, Mailer } from "../contracts/mailer"; export const SmtpMailer: typeof Mailer = createProvider({ name: MAILER_TOKEN, expose: () => ({ send(to: string, body: string) { console.log(`[SMTP] ${to} -> ${body}`); }, }), }); ``` -------------------------------- ### Define Real Payment Provider and Controller Source: https://stratifyjs.github.io/docs/providers Sets up a real 'payment' provider and a 'PaymentController' that depends on it. This is part of demonstrating global provider overrides. ```typescript const RealPayment = createProvider({ name: "payment", expose: () => ({ charge: () => "real" }), }); const PaymentController = createController({ deps: { payment: RealPayment }, build: ({ builder, deps }) => { builder.addRoute({ method: "GET", url: "/pay", handler: async () => deps.payment.charge(), }); }, }); const PaymentModule = createModule({ name: "payment-module", controllers: [PaymentController], }); ``` -------------------------------- ### Attach Controller to a Module Source: https://stratifyjs.github.io/docs/controllers Create a module and attach controllers to it using the `createModule` function. This groups related controllers. ```javascript const UsersModule = createModule({ name: "users", controllers: [UsersController], }); ``` -------------------------------- ### Local Provider Override for Testing Source: https://stratifyjs.github.io/docs/providers Clones an existing provider ('ProfilesProvider') and replaces a specific dependency ('usersRepository') with a fake implementation for unit testing. ```typescript const ProfileTestProvider = ProfilesProvider.withProviders((deps) => ({ ...deps, usersRepository: fakeUsersRepository, })); const profiles = await ProfileTestProvider.resolve(); ``` -------------------------------- ### Configure Root Module Source: https://stratifyjs.github.io/docs/dip Defines the `RootModule` which aggregates other modules, in this case, including the `NotificationsModule`. ```typescript // src/modules/root.module.ts import { createModule } from "@stratify/core"; import { NotificationsModule } from "./notifications.module"; export const RootModule = createModule({ name: "root", subModules: [NotificationsModule], }); ``` -------------------------------- ### Attach Hooks to a Module Source: https://stratifyjs.github.io/docs/hooks Integrate defined HTTP and application hooks into a Stratify module using the `hooks` property in `createModule`. ```javascript const root = createModule({ name: "root", hooks: [httpHooks, appHooks], }); ``` -------------------------------- ### Global Provider Override with Fake Source: https://stratifyjs.github.io/docs/providers Creates a fake 'payment' provider and uses it to override the real one when bootstrapping the application. This is useful for integration and e2e tests. ```typescript const FakePayment = createProvider({ name: "payment", expose: () => ({ charge: () => "fake" }), }); const app = await createApp({ root: PaymentModule, overrides: [FakePayment], }); const res = await app.inject({ method: "GET", url: "/pay" }); assert.strictEqual(res.body, "fake"); ``` -------------------------------- ### Create Dependent Provider Source: https://stratifyjs.github.io/docs/providers Defines a 'profiles' provider that depends on the 'usersRepository' provider. It exposes a 'find' method that utilizes the dependency. ```javascript // Domain service depending on another provider const Profiles = createProvider({ name: "profiles", // You can also do `deps: { UsersRepository }` deps: { usersRepo: UsersRepository }, expose: ({ usersRepo }) => ({ find: async (id) => usersRepo.get(id), }), }); ``` -------------------------------- ### Bind Contract to Provider in Module Source: https://stratifyjs.github.io/docs/dip Configures the `NotificationsModule` to bind the `Mailer` contract to the `SmtpMailer` implementation. This makes `SmtpMailer` available wherever `Mailer` is depended upon. ```typescript // src/modules/notifications.module.ts import { createModule } from "@stratify/core"; import { NotificationsController } from "../controllers/notifications.controller"; import { SmtpMailer } from "../bindings/smtp-mailer"; export const NotificationsModule = createModule({ name: "notifications", controllers: [NotificationsController], bindings: [SmtpMailer], // binds the "mailer" contract to SmtpMailer }); ``` -------------------------------- ### Declare Mailer Contract Source: https://stratifyjs.github.io/docs/dip Defines the abstract Mailer contract using Stratify's `contract` function. This contract specifies the `send` method signature. ```typescript // src/contracts/mailer.ts import { contract } from "@stratify/core"; export const MAILER_TOKEN = "mailer"; export const Mailer = contract<{ send(to: string, body: string): void; }>(MAILER_TOKEN); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.