# Cross-Module Dependency

## Overview

Each module's `defineModule()` returns `{ db, commands, queries }`. Other modules can reference any of these through the return type. Use `import type` and relative paths — all modules live in the same package.

```typescript
import type { defineModule as definePrimitivesModule } from "../primitives";

type PrimitivesModule = ReturnType<typeof definePrimitivesModule>;
type PrimitivesDB = PrimitivesModule["db"];
type PrimitivesCommands = PrimitivesModule["commands"];
type PrimitivesQueries = PrimitivesModule["queries"];
```

## DB Type Injection (`db/*.ts`)

Inject another module's DB type to create a foreign-key relation. **Only cross-module types use this pattern** — same-module types are imported directly (see [db-relations.md](db-relations.md#intra-module-foreign-keys)).

- Accept external type via `CreateTypeParams` as **required** param (e.g., `unitType: TailorAnyDBType`) — never optional
- Use it directly in `.relation()` — **never use `??` fallback to a stub**:
  - `toward: { type: params.unitType }` (correct)
  - `toward: { type: params.unitType ?? unitStub }` (wrong — hides missing dependency at compile time)
- Define stub types for cross-module dependencies in `lib/_db_deps.ts` (codegen only — replaced at runtime by `defineModule()` params):
  ```typescript
  // lib/_db_deps.ts
  import {
    db,
    unsafeAllowAllGqlPermission,
    unsafeAllowAllTypePermission,
  } from "@tailor-platform/sdk";
  export const unit = db
    .type("Unit", {})
    .permission(unsafeAllowAllTypePermission)
    .gqlPermission(unsafeAllowAllGqlPermission);
  ```
- Import the stub and export a default instance at file bottom:
  ```typescript
  // db/item.ts
  import { unit as unitStub } from "../lib/_db_deps";
  export const item = createItemType({ unitType: unitStub });
  ```
- Add `lib/_db_deps.ts` to `tailor.config.ts` files so codegen can resolve the type:
  ```typescript
  db: { "main-db": { files: [`./db/*.ts`, `./lib/_db_deps.ts`] } }
  ```

## Command References

A module can accept another module's commands as a dependency and call them internally:

- Accept commands via `DefineModuleParams` as dependencies
- Derive the type from the source module's return type

```typescript
// Types
type ConvertQuantity = PrimitivesCommands["convertQuantity"];

// DefineModuleParams
export interface DefineModuleParams {
  primitives: {
    commands: {
      convertQuantity: ConvertQuantity;
    };
  };
}

// Usage in a command
const convertQuantity = params.primitives.commands.convertQuantity;
const result = await convertQuantity(db, input, ctx);
```

## Query References

Same pattern as commands — accept queries via `DefineModuleParams`. See [CQRS read rule](../../erp-kit-shared/references/commands.md#command-side-reads-cqrs-separation) for when commands use injected queries vs inline reads.

```typescript
type ConvertAmount = PrimitivesQueries["convertAmount"];

export interface DefineModuleParams {
  primitives: {
    queries: {
      convertAmount: ConvertAmount;
    };
  };
}
```

## Module Wiring (`module.ts`)

Group all external dependencies (db, commands, queries) under a named key in `DefineModuleParams`:

```typescript
export interface DefineModuleParams<IF extends Record<string, TailorAnyDBField>> {
  item?: CreateItemTypeParams<IF>;
  primitives: {
    db: { unit: PrimitivesDB["unit"] };
    commands: { convertQuantity: PrimitivesCommands["convertQuantity"] };
    queries: { convertAmount: PrimitivesQueries["convertAmount"] };
  };
}

export const defineModule = <const IF extends Record<string, TailorAnyDBField> = EmptyFields>(
  params: DefineModuleParams<IF>,
) => {
  const item = createItemType({
    ...params.item,
    unitType: params.primitives.db.unit,
  });

  return {
    db: { item },
    commands: {
      createItem: makeCreateItem({
        convertQuantity: params.primitives.commands.convertQuantity,
      }),
    },
  };
};
```

## Permission Dependencies

Declare cross-module permission dependencies via `definePermissions`:

```typescript
export const { permissions, own, all } = definePermissions(
  "itemManagement",
  ["createItem", "updateItem", ...] as const,
  { deps: primitivesPermissions.all },
);
```

The `all` export merges own permissions with dependency permissions, so consumers get a complete permission set.
