@mariachi/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ ---
2
+ description: Mariachi framework conventions and patterns. Use when building with @mariachi/* packages. Read the docs in this package before writing code.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Mariachi Framework (consumer)
7
+
8
+ When working in a project that uses Mariachi, read these files from the installed package:
9
+
10
+ **Quick reference (same content as root `.mariachi/` in the framework repo):**
11
+
12
+ - `node_modules/@mariachi/core/.mariachi/architecture.md` — Three-layer architecture (Facade → Controller → Service), import boundaries, naming conventions
13
+ - `node_modules/@mariachi/core/.mariachi/conventions.md` — TypeScript/ESM rules, dependency rules, error handling, anti-patterns
14
+ - `node_modules/@mariachi/core/.mariachi/packages.md` — All 28 packages with when to use each one
15
+ - `node_modules/@mariachi/core/.mariachi/patterns.md` — Adapter factory, abstract service class, DI container, context propagation, Zod at boundaries
16
+
17
+ **Step-by-step recipes:**
18
+
19
+ - `node_modules/@mariachi/core/docs/recipes/add-domain-entity.md` — Schema, repository, service, handler, controller, tests
20
+ - `node_modules/@mariachi/core/docs/recipes/add-background-job.md` — Job definition, worker registration, scheduling
21
+ - `node_modules/@mariachi/core/docs/recipes/add-webhook-endpoint.md` — WebhookController with direct/queue modes
22
+ - `node_modules/@mariachi/core/docs/recipes/add-integration.md` — Third-party integration with credentials and retry
23
+ - `node_modules/@mariachi/core/docs/recipes/wiring-and-bootstrap.md` — Full initialization order from config to running servers
24
+
25
+ **Decision trees and gotchas:** `node_modules/@mariachi/core/docs/ai-guide.md`
26
+
27
+ ## Critical Rules
28
+
29
+ - Relative imports are extensionless: `import { foo } from './bar'` (not `'./bar.js'`)
30
+ - Controllers never import services — always use `communication.call()`
31
+ - Every operation takes `Context` as first argument — never drop context
32
+ - Throw typed errors (`MariachiError` subclasses), never raw `Error`
33
+ - Use factory functions (`createCache`, `createSearch`), never instantiate adapters directly
34
+ - Validate with Zod at boundaries (controller input, handler schemas, job payloads)
35
+
36
+ **To use this rule in Cursor:** Copy this file to your project's `.cursor/rules/` (e.g. `.cursor/rules/mariachi.mdc`) so Cursor picks it up. Paths above are relative to your project root where `node_modules/@mariachi/core` is installed.
@@ -0,0 +1,46 @@
1
+ # Mariachi Architecture
2
+
3
+ ## Three-Layer Request Flow
4
+
5
+ ```
6
+ HTTP Request → Facade → Controller → Communication Layer → Service
7
+ ```
8
+
9
+ | Layer | Location | Responsibility |
10
+ |-------|----------|----------------|
11
+ | **Facade** | Your API app (e.g. `src/servers/`) | Fastify server, auth strategies, rate limiting |
12
+ | **Controller** | Your API app (e.g. `src/controllers/`) | Parse/validate input (Zod), call `communication.call()` |
13
+ | **Service** | Your services app (e.g. `src/<domain>/`) | Business logic, DB, cache, events, jobs |
14
+
15
+ ## Import Boundaries
16
+
17
+ - **Controllers** may import: `@mariachi/api-facade`, `@mariachi/communication`, `zod`
18
+ - **Services** may import: any `@mariachi/*` package
19
+ - **Controllers never import services directly** — always go through the communication layer
20
+
21
+ ## Project Structure
22
+
23
+ Organize your app in three layers:
24
+
25
+ - **API app** — HTTP servers + controllers (Facade + Controller layers)
26
+ - **Services app** — Domain services + communication handlers (Service layer)
27
+ - **Worker app** — BullMQ job workers and schedules
28
+
29
+ ## Naming Conventions
30
+
31
+ | Artifact | Convention | Example |
32
+ |----------|-----------|---------|
33
+ | Controller | `<Domain>Controller` in `<domain>.controller.ts` | `UsersController` |
34
+ | Service | `<Domain>Service` object in `<domain>.service.ts` | `UsersService` |
35
+ | Handler | `register<Domain>Handlers` in `<domain>.handler.ts` | `registerUsersHandlers` |
36
+ | Job | `<Action>Job` object in `<action>.job.ts` | `SendEmailJob` |
37
+ | Schema table | `<domain>Table` via `defineTable` | `usersTable` |
38
+ | Repository | `Drizzle<Domain>Repository` | `DrizzleUsersRepository` |
39
+ | Procedure name | `<domain>.<action>` | `users.create` |
40
+
41
+ ## Key Entry Points
42
+
43
+ - `bootstrap()` from `@mariachi/lifecycle` — loads config, creates observability, sets up DI container
44
+ - `createCommunication()` from `@mariachi/communication` — returns in-process communication layer
45
+ - `FastifyAdapter` from `@mariachi/api-facade` — builds HTTP server with auth and rate limiting
46
+ - Register your domain handlers with the communication layer so controllers can call them via `communication.call('<domain>.<action>', ctx, input)`
@@ -0,0 +1,109 @@
1
+ # Mariachi Conventions
2
+
3
+ ## TypeScript and ESM
4
+
5
+ - **All packages use ESM** (`"type": "module"` in every `package.json`)
6
+ - **Build tool:** tsup (ESM + CJS dual output, declaration files, sourcemaps)
7
+ - **TypeScript:** strict mode, ES2022 target, `"moduleResolution": "bundler"`
8
+ - **Relative imports are extensionless:** `import { foo } from './bar'` (not `'./bar.js'`). The `"moduleResolution": "bundler"` tsconfig setting and tsup handle resolution.
9
+ - **Cross-package imports use bare specifiers:** `import { Context } from '@mariachi/core'` (no extension)
10
+ - **All packages export from `src/index.ts`** as the single public entry point
11
+
12
+ ### tsup Config (every package)
13
+
14
+ ```ts
15
+ export default defineConfig({
16
+ entry: ['src/index.ts'],
17
+ format: ['esm', 'cjs'],
18
+ dts: true,
19
+ clean: true,
20
+ sourcemap: true,
21
+ splitting: false,
22
+ });
23
+ ```
24
+
25
+ ### tsconfig (every package)
26
+
27
+ Extend a shared base or use standard options. No additional compiler options needed unless the package has special requirements.
28
+
29
+ ## File Organization
30
+
31
+ - One file per concern: `types.ts`, `schema.ts`, `adapter.ts`, `middleware.ts`
32
+ - Adapters go in `src/adapters/` subdirectory
33
+ - Middleware goes in `src/middleware/` subdirectory
34
+ - Schema definitions go in `src/schema/` subdirectory
35
+ - Tests go alongside source in `test/` or `__tests__/` subdirectory
36
+
37
+ ## Dependency Rules
38
+
39
+ - `@mariachi/core` has zero internal dependencies (only `zod`)
40
+ - Other packages may depend on `@mariachi/core` freely
41
+ - Packages should depend on abstractions, not implementations (e.g., depend on `@mariachi/database`, not `@mariachi/database-postgres`)
42
+ - Apps may depend on any package
43
+ - Circular dependencies between packages are not allowed
44
+
45
+ ## Error Handling
46
+
47
+ - Always throw typed errors extending `MariachiError` from `@mariachi/core`
48
+ - Each package has its own error class: `DatabaseError`, `AuthError`, `CacheError`, etc.
49
+ - Never throw raw `Error` or string exceptions across package boundaries
50
+ - Errors map to HTTP status codes via `errorToHttpStatus()` in the API facade layer
51
+
52
+ ## Anti-Patterns (Do Not Do These)
53
+
54
+ **Do not import services from controllers.**
55
+ Controllers must only call `communication.call()`. Never import a service or its handler directly.
56
+
57
+ ```ts
58
+ // WRONG
59
+ import { UsersService } from '../../services/users/users.service';
60
+ const result = await UsersService.create(ctx, input);
61
+
62
+ // CORRECT
63
+ const result = await communication.call('users.create', ctx, input);
64
+ ```
65
+
66
+ **Do not use `process.env` outside `@mariachi/config`.**
67
+ All configuration flows through `loadConfig()` and `useConfig()`. Direct env access scatters configuration and bypasses validation.
68
+
69
+ ```ts
70
+ // WRONG
71
+ const dbUrl = process.env.DATABASE_URL;
72
+
73
+ // CORRECT
74
+ const config = useConfig();
75
+ const dbUrl = config.database.url;
76
+ ```
77
+
78
+ Exception: `PORT`, `ADMIN_PORT`, `WEBHOOK_PORT` in app entry points are acceptable since they're startup-only values.
79
+
80
+ **Do not skip context propagation.**
81
+ Every operation takes a `Context` as its first argument. Never create a new context mid-flow or drop context between layers.
82
+
83
+ ```ts
84
+ // WRONG
85
+ const user = await UsersService.create({ email, name });
86
+
87
+ // CORRECT
88
+ const user = await UsersService.create(ctx, { email, name });
89
+ ```
90
+
91
+ **Do not expose the Drizzle client directly.**
92
+ All database access goes through repository classes that extend `DrizzleRepository`. The ORM is an implementation detail.
93
+
94
+ **Do not hardcode adapter choices.**
95
+ Use factory functions (`createCache`, `createSearch`, `createJobQueue`) with config. Never instantiate adapters directly in application code.
96
+
97
+ ```ts
98
+ // WRONG
99
+ const cache = new RedisCacheAdapter({ url: 'redis://localhost' });
100
+
101
+ // CORRECT
102
+ const cache = createCache({ adapter: 'redis', url: config.redis.url });
103
+ ```
104
+
105
+ **Do not write migration files by hand.**
106
+ Schema changes go through the `defineTable` DSL in `@mariachi/database`. Migrations are generated by `drizzle-kit`.
107
+
108
+ **Do not register the same procedure name twice.**
109
+ Communication procedure names (`users.create`, `billing.charge`, etc.) must be globally unique. Duplicate registrations will silently overwrite each other.
@@ -0,0 +1,66 @@
1
+ # Mariachi Packages
2
+
3
+ Quick reference for all 28 packages. Use this to decide which package to reach for.
4
+
5
+ ## Foundation
6
+
7
+ | Package | Use when you need... | Factory / Entry |
8
+ |---------|---------------------|-----------------|
9
+ | `@mariachi/core` | Types, errors, context, DI container, `Result<T,E>` | `getContainer()`, `createContext()`, `KEYS` |
10
+ | `@mariachi/config` | Typed config from env, secrets, feature flags | `loadConfig()`, `useConfig()` |
11
+ | `@mariachi/observability` | Logging, tracing, metrics, error tracking | `createObservability(config)` |
12
+ | `@mariachi/lifecycle` | App bootstrap, startup/shutdown hooks, health checks | `bootstrap()` |
13
+
14
+ ## Communication & API
15
+
16
+ | Package | Use when you need... | Factory / Entry |
17
+ |---------|---------------------|-----------------|
18
+ | `@mariachi/communication` | Inter-module procedure calls with middleware | `createCommunication()` |
19
+ | `@mariachi/api-facade` | HTTP servers with auth, rate limiting, controllers | `new FastifyAdapter()`, `BaseController` |
20
+ | `@mariachi/server` | Low-level Fastify adapter (used by api-facade) | `FastifyServerAdapter` |
21
+ | `@mariachi/webhooks` | Inbound webhook endpoints with auth and logging | `WebhookController`, `WebhookServer` |
22
+
23
+ ## Data & Storage
24
+
25
+ | Package | Use when you need... | Factory / Entry |
26
+ |---------|---------------------|-----------------|
27
+ | `@mariachi/database` | Schema definitions, repository interface, types | `defineTable()`, `column`, `Database` |
28
+ | `@mariachi/database-postgres` | PostgreSQL + Drizzle ORM implementation | `createPostgresDatabase()`, `DrizzleRepository` |
29
+ | `@mariachi/cache` | Redis caching, distributed locks, memoization | `createCache()`, `createLock()` |
30
+ | `@mariachi/storage` | File/object storage (S3, local) | `Storage`, `DefaultStorage` |
31
+
32
+ ## Async & Events
33
+
34
+ | Package | Use when you need... | Factory / Entry |
35
+ |---------|---------------------|-----------------|
36
+ | `@mariachi/events` | Pub/sub event bus (Redis or NATS) | `createEventBus()` |
37
+ | `@mariachi/jobs` | Background job queue and scheduling (BullMQ) | `createJobQueue()`, `defineJob` |
38
+ | `@mariachi/realtime` | WebSocket connections, channels, broadcasting | `Realtime`, `WSAdapter` |
39
+
40
+ ## Security & Access
41
+
42
+ | Package | Use when you need... | Factory / Entry |
43
+ |---------|---------------------|-----------------|
44
+ | `@mariachi/auth` | JWT, API keys, OAuth, RBAC | `createAuth()`, `createAuthorization()` |
45
+ | `@mariachi/auth-clerk` | Clerk authentication, webhook verification (Svix) | `createClerkAuth()`, `ClerkWebhookController` |
46
+ | `@mariachi/tenancy` | Multi-tenant isolation (subdomain, header, JWT) | `createTenantResolver()`, `createTenancyMiddleware()` |
47
+ | `@mariachi/rate-limit` | Redis sliding-window rate limiting | `createRateLimiter()` |
48
+
49
+ ## Domain Features
50
+
51
+ | Package | Use when you need... | Factory / Entry |
52
+ |---------|---------------------|-----------------|
53
+ | `@mariachi/billing` | Stripe payments, subscriptions, credits, webhooks | `createBilling()`, `StripeAdapter` |
54
+ | `@mariachi/notifications` | Email (Resend), SMS, push, in-app notifications | `Notifications`, `createEmailAdapter()` |
55
+ | `@mariachi/search` | Full-text search (Typesense) | `createSearch()` |
56
+ | `@mariachi/ai` | AI/LLM sessions, tools, prompts, agent loops | `createAI()`, `runAgent()` |
57
+ | `@mariachi/audit` | Append-only audit logging | `createAuditLogger()` |
58
+ | `@mariachi/integrations` | Third-party integration pattern | `defineIntegrationFn()` |
59
+
60
+ ## Tooling
61
+
62
+ | Package | Use when you need... | Factory / Entry |
63
+ |---------|---------------------|-----------------|
64
+ | `@mariachi/testing` | In-memory test doubles, factories | `createTestHarness()`, `TestRepository` |
65
+ | `@mariachi/create` | Code scaffolding and validation rules | `mariachi generate` |
66
+ | `@mariachi/cli` | CLI binary | `mariachi init/generate/validate` |
@@ -0,0 +1,71 @@
1
+ # Mariachi Core Patterns
2
+
3
+ ## 1. Adapter Factory
4
+
5
+ Every external dependency is behind an adapter. A factory function selects the implementation from config.
6
+
7
+ ```ts
8
+ const cache = createCache({ adapter: 'redis', url: process.env.REDIS_URL });
9
+ const search = createSearch({ adapter: 'typesense', ... });
10
+ const jobQueue = createJobQueue({ adapter: 'bullmq', redisUrl: ... }, logger);
11
+ ```
12
+
13
+ Production adapters: Redis, PostgreSQL, Stripe, Typesense, BullMQ, Resend, S3, OpenAI.
14
+ Test doubles live in `@mariachi/testing` (e.g. `TestCacheClient`, `TestEventBus`).
15
+
16
+ ## 2. Abstract Service Class
17
+
18
+ Each package exposes: `X` (abstract) → `DefaultX extends X`. The abstract class layers observability, error handling, and hooks on top of raw adapters.
19
+
20
+ ```ts
21
+ export abstract class Notifications implements Instrumentable { ... }
22
+ export class DefaultNotifications extends Notifications { ... }
23
+ ```
24
+
25
+ Subclass `DefaultX` when custom behavior is needed.
26
+
27
+ ## 3. Instrumentable & Disposable
28
+
29
+ Two interfaces from `@mariachi/core` that every service implements:
30
+
31
+ - **Instrumentable**: `{ logger, tracer?, metrics? }` — pulled from the DI container
32
+ - **Disposable**: `{ connect(), disconnect(), isHealthy() }` — lifecycle management
33
+
34
+ ## 4. DI Container
35
+
36
+ Global container via `getContainer()` with well-known `KEYS`:
37
+
38
+ ```ts
39
+ import { getContainer, KEYS } from '@mariachi/core';
40
+ const container = getContainer();
41
+ container.register(KEYS.Logger, logger);
42
+ const logger = container.resolve<Logger>(KEYS.Logger);
43
+ ```
44
+
45
+ `bootstrap()` registers `Config` and `Logger` automatically. Other services register themselves as needed.
46
+
47
+ ## 5. Context Propagation
48
+
49
+ Every operation receives a `Context` carrying identity and tracing:
50
+
51
+ ```ts
52
+ interface Context {
53
+ traceId: string;
54
+ userId: string | null;
55
+ tenantId: string | null;
56
+ scopes: string[];
57
+ identityType: string;
58
+ logger: Logger;
59
+ }
60
+ ```
61
+
62
+ Never lose context between layers. Pass `ctx` through communication calls, service methods, and event handlers.
63
+
64
+ ## 6. Zod Schemas at Boundaries
65
+
66
+ Validate at entry points, not deep in business logic:
67
+
68
+ - **Controller**: parse request body with Zod before calling communication
69
+ - **Handler registration**: declare `schema: { input, output }` with Zod schemas
70
+ - **Job definition**: declare `schema` for job payload
71
+ - **Config**: `AppConfigSchema` validates all configuration at load time
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # @mariachi/core
2
+
3
+ Shared types, typed errors, `Context`, DI container, `Result<T,E>`, and retry utilities for the Mariachi framework.
4
+
5
+ ## Framework documentation
6
+
7
+ When you install any `@mariachi/*` package, this documentation is included so you don't lose the framework's conventions and recipes.
8
+
9
+ ### Quick reference (same as repo `.mariachi/`)
10
+
11
+ - **[.mariachi/architecture.md](./.mariachi/architecture.md)** — Three-layer flow, import boundaries, naming
12
+ - **[.mariachi/conventions.md](./.mariachi/conventions.md)** — TypeScript/ESM, dependency rules, anti-patterns
13
+ - **[.mariachi/packages.md](./.mariachi/packages.md)** — All 28 packages and when to use each
14
+ - **[.mariachi/patterns.md](./.mariachi/patterns.md)** — Adapter factory, DI container, context, Zod at boundaries
15
+
16
+ ### Full docs
17
+
18
+ - **[docs/architecture.md](./docs/architecture.md)** — Architecture with mermaid diagrams, package overview, adapter pattern
19
+ - **[docs/conventions.md](./docs/conventions.md)** — Same as .mariachi with full detail
20
+ - **[docs/packages.md](./docs/packages.md)** — Same as .mariachi
21
+ - **[docs/patterns.md](./docs/patterns.md)** — Same as .mariachi
22
+ - **[docs/integrations.md](./docs/integrations.md)** — How to add third-party integrations
23
+ - **[docs/ai-guide.md](./docs/ai-guide.md)** — Decision trees, package cheat sheet, common gotchas
24
+ - **[docs/runbook.md](./docs/runbook.md)** — Environment variables, CLI commands, validation
25
+ - **[docs/adr/001-adapter-pattern.md](./docs/adr/001-adapter-pattern.md)** — ADR: adapter pattern
26
+ - **[docs/improvements/](./docs/improvements/)** — Draft improvements (e.g. notifications/realtime/NATS)
27
+
28
+ ### Step-by-step recipes
29
+
30
+ - [docs/recipes/add-domain-entity.md](./docs/recipes/add-domain-entity.md) — Schema, repository, service, handler, controller, tests
31
+ - [docs/recipes/add-background-job.md](./docs/recipes/add-background-job.md) — Job definition, worker registration, scheduling
32
+ - [docs/recipes/add-webhook-endpoint.md](./docs/recipes/add-webhook-endpoint.md) — WebhookController with direct/queue modes
33
+ - [docs/recipes/add-integration.md](./docs/recipes/add-integration.md) — Third-party integration with credentials and retry
34
+ - [docs/recipes/wiring-and-bootstrap.md](./docs/recipes/wiring-and-bootstrap.md) — Full initialization order from config to running servers
35
+
36
+ ### Cursor / AI assistants
37
+
38
+ A Cursor rule file is included so your IDE can use the framework conventions:
39
+
40
+ - **Copy** `node_modules/@mariachi/core/.cursor/rules/mariachi.mdc` into your project's `.cursor/rules/` (e.g. as `mariachi.mdc`). The rule points the AI at the docs in this package.
41
+
42
+ After `pnpm add @mariachi/core`, all of the above paths are available under `node_modules/@mariachi/core/`.