@izumisy-tailor/omakase-modules 0.1.0 → 0.2.0

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,92 @@
1
+ # Order Payment Status Scenario
2
+
3
+ ## Overview
4
+ This document captures a reference flow where the order module owns the canonical order status while collaborating with optional billing, authorization, and cash receipt modules. The order module remains usable as a standalone component—for example, back-office staff can record invoice or payment outcomes manually—while downstream modules add automation by reacting to order events and pushing their results back through status history entries. The shared contract that keeps order independent is defined in [Order Module Core Contract](../order-module-core-contract.md).
5
+
6
+ ## Module Dependencies
7
+
8
+ | Module (package path) | Declared dependencies | Purpose |
9
+ | --- | --- | --- |
10
+ | Order (`packages/order-module`) | — | Publishes the `order.orderIntent` contract, stores canonical orders, and exposes status history consumed by downstream financial modules. |
11
+ | Payment authorization (`packages/payment-authorization-module`) | Order | Manages authorization holds/captures against external PSPs and appends payment statuses to `orderStatusHistory`. |
12
+ | Billing (`packages/billing-module`) | Order, Payment authorization | Generates invoices (manually or automatically), links them to authorizations, and writes billing milestones into `orderStatusHistory`. |
13
+ | Cash receipt (`packages/cash-receipt-module`) | Order, Billing | Records cash inflows, allocates them to invoices, and publishes settlement statuses into `orderStatusHistory`. |
14
+
15
+ ## TailorDB Tables and Views
16
+ ### Payment authorization module
17
+ - `authorization.request`: Outbound authorization attempts for a given order.
18
+ - `authorization.result`: Holds/voids/captures returned from the PSP.
19
+ - Appends `payment:*` entries (e.g., `payment:authorized`, `payment:capture_failed`) to `orderStatusHistory` via the order dependency.
20
+
21
+ ### Billing module
22
+ - `billing.invoice`: Invoices generated for orders.
23
+ - `billing.invoiceStatus`: Derived view summarizing invoice state (issued, posted, settled).
24
+ - Appends `billing:*` milestones (e.g., `billing:invoice_issued`, `billing:settled`) to `orderStatusHistory` and maintains projections for finance dashboards.
25
+
26
+ ### Cash receipt module
27
+ - `cash.receipt`: Records individual cash inflows.
28
+ - `cash.receiptAllocation`: Maps receipts to invoices.
29
+ - Appends `cash:*` history entries (`cash:payment_applied`, `cash:refund_requested`) to provide audit traces within `orderStatusHistory`.
30
+
31
+ ## Order Status
32
+
33
+ Baseline `order:*` statuses are documented in [Order Module Core Contract](../order-module-core-contract.md#order-status-vocabulary). Financial automation contributes the following additional entries:
34
+
35
+ | Label | Writer | Trigger timing | Notes |
36
+ | --- | --- | --- | --- |
37
+ | `payment:authorization_pending` | Payment authorization | Immediately after `paymentAuthorizationIntake` enqueues an authorization attempt. | Communicates that an authorization request is in flight. |
38
+ | `payment:authorized` | Payment authorization | When the PSP returns a successful authorization or capture. | Used to gate invoice issuance or fulfilment release. |
39
+ | `payment:capture_failed` | Payment authorization | Upon PSP decline or technical failure. | Prompts support teams to investigate or retry. |
40
+ | `billing:invoice_requested` | Billing | When `billingOrderIntake` decides to create an invoice. | Marks the start of the billing workflow even before the invoice record exists. |
41
+ | `billing:invoice_issued` | Billing | After an invoice is generated. | Downstream consumers can inform customers or trigger collections. |
42
+ | `billing:settled` | Billing | Once the invoice is fully settled in billing systems. | Often paired with cash entries for complete reconciliation. |
43
+ | `cash:payment_applied` | Cash receipt | When cash is allocated to the invoice covering the order. | Confirms funds have been received and matched. |
44
+ | `cash:refund_requested` | Cash receipt | If a refund or reversal is initiated. | Allows order timelines to reflect outstanding customer adjustments. |
45
+
46
+ ## Executor Triggers
47
+
48
+ | Trigger table (module) | Writers (modules) | Activation timing | Target executor (module) | Responsibility |
49
+ | --- | --- | --- | --- | --- |
50
+ | `order.order` (order) | Order (owner), back-office operators | Record creation or update (CDC) | `billingOrderIntake` (billing) | React to new or updated orders, create invoices when automation is enabled, and append `billing:invoice_requested` statuses. |
51
+ | `order.order` (order) | Order (owner), back-office operators | Record creation or update (CDC) | `paymentAuthorizationIntake` (payment authorization) | Initiate or refresh authorization attempts based on order state or manual triggers; append `payment:authorization_pending` status. |
52
+ | `authorization.result` (payment authorization) | Payment authorization (owner) | Record creation or update (CDC) | `authorizationStatusWriter` (payment authorization) | Append authorization outcomes to `orderStatusHistory` (`payment:authorized`, `payment:capture_failed`) and refresh module projections. |
53
+ | `billing.invoice` (billing) | Billing (owner), operators | Record creation or update (CDC) | `billingStatusWriter` (billing) | Append invoice lifecycle entries (`billing:invoice_issued`, `billing:invoice_posted`) to `orderStatusHistory`. |
54
+ | `billing.invoiceStatus` (billing) | Billing (derived) | View refresh | `billingSettlementWriter` (billing) | Append settlement milestones (`billing:settled`) and update finance dashboards. |
55
+ | `cash.receiptAllocation` (cash receipt) | Cash receipt (owner) | Record creation or update (CDC) | `cashReceiptOrderWriter` (cash receipt) | Append `cash:payment_applied` entries and emit reconciliation tasks when allocations differ from expectations. |
56
+
57
+ ## Flow
58
+ 1. A new order intent is submitted (automated integration or operator input). The order module validates it, persists `order.order`, and emits a CDC event.
59
+ 2. The billing and payment authorization modules listen to that CDC stream. If enabled, their executors (`billingOrderIntake`, `paymentAuthorizationIntake`) create invoices or authorization requests and append pending statuses (`billing:invoice_requested`, `payment:authorization_pending`). Otherwise they ignore the event, allowing manual workflows.
60
+ 3. Authorization results are written to `authorization.result`. The `authorizationStatusWriter` executor appends outcomes such as `payment:authorized` or `payment:capture_failed` to `orderStatusHistory`, enabling order consumers to track financial progress without exposing PSP details.
61
+ 4. Billing lifecycle changes (automation or manual invoice entry) update `billing.invoice` / `billing.invoiceStatus`. Billing executors append milestones (`billing:invoice_issued`, `billing:settled`) to `orderStatusHistory` and refresh their projections.
62
+ 5. Cash receipts allocate payments to invoices via `cash.receiptAllocation`. The cash receipt executor appends settlement statuses (`cash:payment_applied`) so customer service teams can view payment confirmations from the order timeline.
63
+ 6. Operators can always append manual entries to `orderStatusHistory` (e.g., `manual:write_off`) to reflect adjustments; downstream modules treat those entries as authoritative signals and reconcile their own records accordingly.
64
+
65
+ ```mermaid
66
+ sequenceDiagram
67
+ actor Operator
68
+ participant Order
69
+ participant Billing
70
+ participant Auth as PaymentAuth
71
+ participant Cash
72
+
73
+ Operator->>Order: submit orderIntent (manual or automated)
74
+ Order->>Order: orderIntentIngestor creates order.order
75
+ Order-->>Billing: order.order CDC event
76
+ Billing->>Billing: billingOrderIntake decides on automation
77
+ Billing->>Order: append billing:* status history entries
78
+ Order-->>Auth: order.order CDC event
79
+ Auth->>Auth: paymentAuthorizationIntake initiates auth request
80
+ Auth->>Order: append payment:* status history entries
81
+ Billing->>Billing: invoice lifecycle progresses
82
+ Billing->>Order: append billing:settled when complete
83
+ Cash-->>Billing: cash.receiptAllocation links receipt to invoice
84
+ Cash->>Order: append cash:payment_applied status
85
+ ```
86
+
87
+ ## Design Considerations
88
+ - Keep configuration dependencies directional: downstream financial modules depend on order, not the other way around, following the guidance in `../order-module-core-contract.md`.
89
+ - Downstream modules append to `orderStatusHistory` using namespace-qualified status codes instead of mutating `order.order` fields, preserving the clean core.
90
+ - CDC-driven automation should be idempotent and tolerant of manual changes, reconciling rather than overwriting operator inputs.
91
+ - Maintain documented vocabularies for `payment:*`, `billing:*`, and `cash:*` statuses so shared dashboards interpret them consistently.
92
+ - Leverage projections (e.g., `order.financialStatusProjection`) for read-heavy contexts while keeping `orderStatusHistory` as the authoritative audit trail.
@@ -0,0 +1,95 @@
1
+ # Procurement Order Scenario
2
+
3
+ ## Overview
4
+ This document illustrates how an order module cooperates with a procurement module when customer demand is fulfilled through supplier purchase orders rather than internal stock. The order module remains a clean, customer-facing source of truth, while procurement owns supplier relationships, purchase orders, and inbound logistics. The goal is to let organizations operate mixed models (stocked items vs. drop-ship) without embedding procurement concerns into the core order schema. The shared order contract that keeps the core independent is described in [Order Module Core Contract](../order-module-core-contract.md).
5
+
6
+ ## Module Dependencies
7
+
8
+ | Module (package path) | Declared dependencies | Purpose |
9
+ | --- | --- | --- |
10
+ | Order (`packages/order-module`) | — | Publishes the `order.orderIntent` contract, stores canonical orders, and exposes status history for downstream modules. |
11
+ | Procurement (`packages/procurement-module`) | Order, Commerce core | Generates and tracks supplier purchase orders, manages inbound shipments, and appends procurement milestones to `orderStatusHistory`. |
12
+ | Commerce core (`packages/commerce-core-module`) | — | Provides product master data, supplier catalogs, and lead-time metadata consumed by procurement. |
13
+ | Inventory (`packages/inventory-module`) | Procurement, Commerce core | Optionally tracks goods received into stock or cross-docking locations. |
14
+ | Billing (`packages/billing-module`) | Order | Handles customer invoicing; may wait for procurement confirmation before finalizing revenue. |
15
+
16
+ ## TailorDB Tables and Views
17
+ ### Procurement module
18
+ - `procurement.purchaseOrder`: Supplier-facing purchase orders referencing `orderId` and line allocations.
19
+ - `procurement.supplier`: Master data for suppliers, including lead times, payment terms, and partner IDs.
20
+ - `procurement.inboundShipment`: Tracks ASN (advance shipping notice), shipment status, and expected arrival.
21
+ - `procurement.exceptions`: Captures issues such as supplier delays, quantity shortages, or quality holds.
22
+ - `procurement.orderStatus`: Projection of procurement milestones per order (PO issued, supplier confirmed, shipment dispatched, received).
23
+ - Appends `procurement:*` entries to `orderStatusHistory` for shared visibility while keeping detailed supplier data inside procurement-owned tables.
24
+
25
+ ### Inventory module (optional)
26
+ - Uses core inventory tables (`inventory.stock`, `inventory.stockLedger`, etc.) as defined in `../core/inventory-module.md` to reflect inbound receipts and stock updates; not redefined here.
27
+ - `inventory.receipt`: Scenario-specific record for booking inbound shipments into stock or cross-dock locations.
28
+
29
+ ## Order Status
30
+
31
+ Baseline `order:*` statuses are defined in [Order Module Core Contract](../order-module-core-contract.md#order-status-vocabulary). Procurement adds the following milestones:
32
+
33
+ | Label | Writer | Trigger timing | Notes |
34
+ | --- | --- | --- | --- |
35
+ | `procurement:po_issued` | Procurement module | Immediately after `procurementOrderIntake` creates a purchase order. | Indicates supplier engagement has started. |
36
+ | `procurement:po_confirmed` | Procurement module | When the supplier confirms the purchase order. | Confirms expected ship dates and quantities. |
37
+ | `procurement:asn_received` | Procurement module | Upon receiving an ASN or shipment notice. | Signals inbound logistics to prepare for receipt. |
38
+ | `procurement:received` | Procurement module / Inventory module | When goods are fully received and reconciled. | Allows billing or fulfilment to proceed confidently. |
39
+ | `procurement:short_shipment` | Procurement module | If received quantity is less than ordered. | Highlights the need for back-order or customer communication. |
40
+ | `procurement:blocking_exception` | Procurement module | When an exception (delay, quality hold) blocks fulfilment. | Downstream modules should pause until resolved. |
41
+
42
+ ## Executor Triggers
43
+
44
+ | Trigger table (module) | Writers (modules) | Activation timing | Target executor (module) | Responsibility |
45
+ | --- | --- | --- | --- | --- |
46
+ | `order.order` (order) | Order (owner), operators | Record creation or update (CDC) | `procurementOrderIntake` (procurement) | Decide whether a purchase order is needed based on product supply policies and current stock; create or update `procurement.purchaseOrder` rows. |
47
+ | `procurement.purchaseOrder` (procurement) | Procurement (owner) | Record creation or update (CDC) | `procurementPOStatusProjector` (procurement) | Update supplier confirmations, expected ship dates, and project milestones into `procurement.orderStatus`. |
48
+ | `procurement.inboundShipment` (procurement) | Procurement (owner), suppliers via EDI | Record creation or update (CDC) | `procurementInboundCoordinator` (inventory) | Trigger inbound logistics tasks, e.g., allocate receiving docks or generate `inventory.receipt` placeholders. |
49
+ | `inventory.receipt` (inventory) | Inventory (owner) | Record creation (CDC) | `procurementReceiptReconciler` (procurement) | Match receipts to purchase orders, update quantities received, and close out procurement exceptions. |
50
+ | `procurement.exceptions` (procurement) | Procurement (owner), operators | Record creation or update (CDC) | `procurementExceptionProjector` (procurement) | Reflect exception state in `procurement.orderStatus` and expose signals (e.g., blocks) for downstream modules. |
51
+
52
+ ## Flow
53
+ 1. An order intent is submitted. After validation, the order module persists `order.order` and emits a CDC event that triggers `procurementOrderIntake`.
54
+ 2. Procurement evaluates supply policies, available stock, and supplier contracts. If a supplier order is required, it creates `procurement.purchaseOrder` entries linking each order line to a supplier and expected ship date, and appends `procurement:po_issued` to `orderStatusHistory`.
55
+ 3. Suppliers confirm the purchase order through EDI/API or operator input. `procurement.purchaseOrder` updates drive `procurementPOStatusProjector`, which writes milestones (confirmed, delayed, partial) into `procurement.orderStatus` and appends corresponding entries (e.g., `procurement:po_confirmed`) to `orderStatusHistory`.
56
+ 4. When suppliers send advance shipping notices, `procurement.inboundShipment` records are created. `procurementInboundCoordinator` may allocate receiving resources or pre-create `inventory.receipt` placeholders while recording `procurement:asn_received` in the shared history.
57
+ 5. Upon physical receipt, the inventory module records `inventory.receipt`, triggering `procurementReceiptReconciler` to update received quantities, close or escalate procurement exceptions, and append `procurement:received` or `procurement:short_shipment` statuses for order-facing consumers.
58
+ 6. Any exceptions (short shipments, quality holds, supplier delays) are logged in `procurement.exceptions`. `procurementExceptionProjector` updates `procurement.orderStatus` and surfaces blocking flags via `orderStatusHistory` so downstream modules can pause fulfilment or billing.
59
+ 7. Once procurement confirms completion, order and billing experiences reference `procurement.orderStatus` alongside the shared history to release fulfilment and issue invoices when appropriate.
60
+
61
+ ```mermaid
62
+ sequenceDiagram
63
+ actor Customer
64
+ participant Order
65
+ participant Procurement
66
+ actor Supplier
67
+ participant Inventory
68
+ participant Billing
69
+
70
+ Customer->>Order: submit orderIntent
71
+ Order->>Order: orderIntentIngestor creates order.order
72
+ Order-->>Procurement: order.order CDC event
73
+ Procurement->>Procurement: procurementOrderIntake creates purchaseOrder
74
+ Procurement->>Order: append procurement:po_issued status
75
+ Procurement->>Supplier: send purchase order
76
+ Supplier-->>Procurement: confirmation updates purchaseOrder
77
+ Procurement->>Order: append procurement:po_confirmed status
78
+ Supplier-->>Procurement: send inboundShipment/ASN
79
+ Procurement->>Order: append procurement:asn_received status
80
+ Procurement->>Inventory: procurementInboundCoordinator prepares receipt
81
+ Inventory->>Inventory: record inventory.receipt
82
+ Inventory-->>Order: append procurement:received / procurement:short_shipment statuses
83
+ Procurement->>Procurement: procurementExceptionProjector updates orderStatus view
84
+ Procurement-->>Order: expose orderStatus for fulfillment/billing decisions
85
+ Order-->>Billing: release for invoicing once procurement complete
86
+ ```
87
+
88
+ ## Design Considerations
89
+ - Keep procurement logic modular so order can operate without it (e.g., stocked items). The intake executor should be configuration-driven (per SKU, channel, or merchant) and must adhere to `../order-module-core-contract.md`.
90
+ - Purchase orders may aggregate multiple customer orders; ensure `procurement.purchaseOrder` links to both supplier PO numbers and individual order line allocations.
91
+ - Exceptions should be first-class records with lifecycle management, enabling reporting and SLA tracking.
92
+ - Append procurement milestones to `orderStatusHistory` with namespace-qualified codes (`procurement:*`) so order-facing teams share a single timeline.
93
+ - Inventory integration is optional: drop-ship flows might bypass inventory entirely, while cross-docking requires temporary receipts.
94
+ - Billing should respect procurement status, especially when revenue recognition depends on supplier confirmation or goods receipt.
95
+ - Expose `procurement.orderStatus` as a read-only interface for order, billing, or customer-facing channels rather than duplicating timelines inside the order schema.
@@ -0,0 +1,256 @@
1
+ # Creating Modules
2
+
3
+ This guide explains how to create reusable Omakase Modules that can be shared across applications.
4
+
5
+ ## Module Structure
6
+
7
+ A typical module package has this structure:
8
+
9
+ ```
10
+ my-module/
11
+ package.json
12
+ tsconfig.json
13
+ src/
14
+ module.ts # Module definition
15
+ types.ts # Configuration types
16
+ tailordb/
17
+ index.ts # TailorDB exports
18
+ context.ts # Type definitions for tables
19
+ my-table.ts # Table builders
20
+ resolvers/
21
+ my-resolver.ts
22
+ executors/
23
+ my-executor.ts
24
+ ```
25
+
26
+ ## 1. Define the Module
27
+
28
+ Create the module definition with `defineModule`:
29
+
30
+ ```typescript
31
+ // src/module.ts
32
+ import { defineModule } from "@izumisy-tailor/omakase-modules/builder";
33
+ import type { ModuleConfig } from "./types";
34
+ import type { MyModuleTables } from "./tailordb/context";
35
+ import * as pkg from "../package.json";
36
+
37
+ export default defineModule<ModuleConfig, MyModuleTables>({
38
+ packageName: pkg.name,
39
+ });
40
+ ```
41
+
42
+ The `packageName` must match the `name` field in your `package.json`.
43
+
44
+ ## 2. Define Configuration Types
45
+
46
+ Define what configuration options your module accepts:
47
+
48
+ ```typescript
49
+ // src/types.ts
50
+ import { TailorField } from "@tailor-platform/sdk";
51
+
52
+ type DataModelConfiguration = {
53
+ docNumberPrefix?: string;
54
+ customAttributes?: Record<string, TailorField<any>>;
55
+ };
56
+
57
+ export type ModuleConfig = {
58
+ dataModel?: {
59
+ product?: DataModelConfiguration;
60
+ category?: DataModelConfiguration;
61
+ };
62
+ };
63
+ ```
64
+
65
+ ## 3. Define Table Types
66
+
67
+ Create type definitions for your module's tables:
68
+
69
+ ```typescript
70
+ // src/tailordb/context.ts
71
+ import type { TailorDBType } from "@tailor-platform/sdk";
72
+ import type { ModuleConfig } from "../types";
73
+
74
+ export type MyModuleTables = {
75
+ product: TailorDBType;
76
+ category: TailorDBType;
77
+ };
78
+
79
+ export type ModuleFactoryContext = {
80
+ config: ModuleConfig;
81
+ };
82
+ ```
83
+
84
+ ## 4. Build Tables with Configuration
85
+
86
+ Use `withModuleConfiguration` to access configuration when building tables:
87
+
88
+ ```typescript
89
+ // src/tailordb/index.ts
90
+ import { withModuleConfiguration } from "@izumisy-tailor/omakase-modules/builder";
91
+ import type { MyModuleTables } from "./context";
92
+ import moduleDef from "../module";
93
+ import { buildProductTable } from "./product";
94
+ import { buildCategoryTable } from "./category";
95
+
96
+ const tables = await withModuleConfiguration(moduleDef, (context) => {
97
+ const category = buildCategoryTable(context);
98
+ const product = buildProductTable(context, { category });
99
+
100
+ return { product, category } satisfies MyModuleTables;
101
+ });
102
+
103
+ export const productTable = tables.product;
104
+ export const categoryTable = tables.category;
105
+ ```
106
+
107
+ ```typescript
108
+ // src/tailordb/product.ts
109
+ import { db } from "@tailor-platform/sdk";
110
+ import type { ModuleFactoryContext } from "./context";
111
+
112
+ export const buildProductTable = (
113
+ { config }: ModuleFactoryContext,
114
+ deps: { category: TailorDBType }
115
+ ) => {
116
+ const customAttributes = config.dataModel?.product?.customAttributes || {};
117
+ const docNumberPrefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
118
+
119
+ return db.type("Product", {
120
+ name: db.string(),
121
+ sku: db.string().unique(),
122
+ categoryId: db.uuid({ optional: true }).relation({
123
+ type: "keyOnly",
124
+ toward: { type: deps.category },
125
+ }),
126
+ docNumber: db.docNumber({ prefix: docNumberPrefix }),
127
+ ...customAttributes,
128
+ ...db.fields.timestamps(),
129
+ });
130
+ };
131
+ ```
132
+
133
+ ## 5. Declare Dependencies on Other Modules
134
+
135
+ If your module depends on other modules, use `ModuleDependency`:
136
+
137
+ ```typescript
138
+ // src/types.ts
139
+ import type { ModuleDependency } from "@izumisy-tailor/omakase-modules/builder";
140
+ import type commerceCoreModule from "omakase-module-commerce-core";
141
+
142
+ export type ModuleConfig = {
143
+ dataModel?: { /* ... */ };
144
+ dependencies: {
145
+ commerce: ModuleDependency<typeof commerceCoreModule>;
146
+ };
147
+ };
148
+ ```
149
+
150
+ This ensures type-safe dependency injection when users configure your module.
151
+
152
+ ## File Export Requirements
153
+
154
+ Due to Tailor SDK API requirements, **TailorDB** and **Resolvers/Executors** have different export patterns:
155
+
156
+ **TailorDB**: Should use a single `index.ts` barrel export. All table definitions should be exported from one file. This is **strongly recommended** because it allows you to use `satisfies` to verify that all required tables are defined for the module:
157
+
158
+ ```typescript
159
+ // src/tailordb/index.ts
160
+ const tables = await withModuleConfiguration(moduleDef, (context) => {
161
+ const category = buildCategoryTable(context);
162
+ const product = buildProductTable(context, { category });
163
+
164
+ // Type error if any required table is missing
165
+ return { product, category } satisfies MyModuleTables;
166
+ });
167
+ ```
168
+
169
+ ```
170
+ src/tailordb/
171
+ index.ts # Exports all tables
172
+ product.ts # Table builder (not directly exported)
173
+ category.ts # Table builder (not directly exported)
174
+ ```
175
+
176
+ **Resolvers/Executors**: Must be exported as **separate files**. Each resolver or executor must be in its own file and cannot be barrel-exported from an `index.ts`:
177
+
178
+ ```
179
+ src/resolvers/
180
+ getProduct.ts # Each resolver in its own file
181
+ listProducts.ts
182
+ src/executors/
183
+ onProductCreated.ts # Each executor in its own file
184
+ onOrderPlaced.ts
185
+ ```
186
+
187
+ This is because the Tailor SDK processes resolver and executor files individually, expecting each file to contain a single definition with a default export.
188
+
189
+ ## 6. Configure Package Exports
190
+
191
+ Set up your `package.json` to export the built files.
192
+
193
+ > **Important**: The export paths `./backend/tailordb`, `./backend/resolvers/*`, and `./backend/executors/*` are **required** and must not be changed. The module system expects these exact paths to locate module files.
194
+
195
+ ```json
196
+ {
197
+ "name": "my-module",
198
+ "type": "module",
199
+ "exports": {
200
+ ".": {
201
+ "default": "./dist/module.mjs",
202
+ "types": "./dist/module.d.mts"
203
+ },
204
+ "./backend/tailordb": {
205
+ "default": "./dist/tailordb/index.mjs",
206
+ "types": "./dist/tailordb/index.d.mts"
207
+ },
208
+ "./backend/resolvers/*": {
209
+ "default": "./dist/resolvers/*.mjs",
210
+ "types": "./dist/resolvers/*.d.mts"
211
+ },
212
+ "./backend/executors/*": {
213
+ "default": "./dist/executors/*.mjs",
214
+ "types": "./dist/executors/*.d.mts"
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ Note that TailorDB uses an `index.mjs` barrel export, while resolvers and executors use wildcard patterns to export individual files.
221
+
222
+ ## Best Practices
223
+
224
+ ### Use Factory Functions for Tables
225
+
226
+ Always use factory functions (like `buildProductTable`) instead of directly exporting table definitions. This allows configuration to be injected.
227
+
228
+ ### Type Your Tables
229
+
230
+ Use `satisfies` to ensure your returned tables match the expected type:
231
+
232
+ ```typescript
233
+ return { product, category } satisfies MyModuleTables;
234
+ ```
235
+
236
+ ### Provide Sensible Defaults
237
+
238
+ Always provide default values for optional configuration:
239
+
240
+ ```typescript
241
+ const prefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
242
+ ```
243
+
244
+ ### Export Table References
245
+
246
+ Export individual table references for use in other modules:
247
+
248
+ ```typescript
249
+ export const productTable = tables.product;
250
+ ```
251
+
252
+ This allows other modules to reference your tables in relations and executors.
253
+
254
+ ## Next Steps
255
+
256
+ - See [Using Modules](./using-modules.md) for how applications consume your module
@@ -0,0 +1,174 @@
1
+ # Using Modules in Your Application
2
+
3
+ This guide explains how to use pre-built Omakase Modules in your Tailor Platform application.
4
+
5
+ ## Prerequisites
6
+
7
+ - A Tailor Platform application
8
+ - Modules installed as dependencies (e.g., `omakase-module-commerce-core`)
9
+
10
+ ## 1. Configure Modules
11
+
12
+ Use `loadModules` to configure the modules your application needs:
13
+
14
+ ```typescript
15
+ // modules.ts
16
+ import { loadModules } from "@izumisy-tailor/omakase-modules";
17
+ import { db } from "@tailor-platform/sdk";
18
+ import ecommerceCoreModule from "omakase-module-commerce-core";
19
+
20
+ export default loadModules((loader) => {
21
+ loader.add(
22
+ ecommerceCoreModule.configure({
23
+ config: {
24
+ dataModel: {
25
+ product: {
26
+ docNumberPrefix: "MY-PROD",
27
+ customAttributes: {
28
+ customStatus: db.enum(["new", "used", "refurbished"]),
29
+ },
30
+ },
31
+ },
32
+ },
33
+ })
34
+ );
35
+
36
+ return loader;
37
+ });
38
+ ```
39
+
40
+ Each module exposes a `configure()` method that accepts a type-safe configuration object. The available options are defined by the module author.
41
+
42
+ ## 2. Set Up tsconfig.json
43
+
44
+ Configure path aliases in `tsconfig.json` to enable module configuration loading:
45
+
46
+ ```json
47
+ {
48
+ "compilerOptions": {
49
+ "paths": {
50
+ "@izumisy-tailor/omakase-modules/config/loader": ["./modules.ts"]
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ This tells the module system where to find your configuration file.
57
+
58
+ ## 3. Reference Modules in tailor.config.ts
59
+
60
+ Use `getModulesReference` to include module files in your Tailor configuration:
61
+
62
+ ```typescript
63
+ // tailor.config.ts
64
+ import { defineConfig } from "@tailor-platform/sdk";
65
+ import { getModulesReference } from "@izumisy-tailor/omakase-modules/config/sdk";
66
+ import modules from "./modules";
67
+
68
+ const moduleReference = getModulesReference(modules);
69
+
70
+ export default defineConfig({
71
+ name: "my-app",
72
+ db: {
73
+ main: {
74
+ files: ["./src/tailordb/*.ts", ...moduleReference.tailordb],
75
+ },
76
+ },
77
+ resolver: {
78
+ "main-pipeline": {
79
+ files: ["./src/resolvers/*.ts", ...moduleReference.resolver],
80
+ },
81
+ },
82
+ executor: {
83
+ files: ["./src/executors/**/*.ts", ...moduleReference.executor],
84
+ },
85
+ });
86
+ ```
87
+
88
+ ## 4. Handle Module Dependencies
89
+
90
+ When modules depend on other modules, you need to wire them together:
91
+
92
+ ```typescript
93
+ // modules.ts
94
+ import { loadModules } from "@izumisy-tailor/omakase-modules";
95
+ import ecommerceCoreModule from "omakase-module-commerce-core";
96
+ import orderModule from "omakase-module-order";
97
+ import inventoryModule from "omakase-module-inventory";
98
+
99
+ export default loadModules((loader) => {
100
+ // Add the base module first
101
+ const $commerce = loader.add(
102
+ ecommerceCoreModule.configure({
103
+ config: { /* ... */ },
104
+ })
105
+ );
106
+
107
+ // Pass the commerce module as a dependency
108
+ const $order = loader.add(
109
+ orderModule.configure({
110
+ config: {
111
+ dependencies: {
112
+ commerce: $commerce,
113
+ },
114
+ },
115
+ })
116
+ );
117
+
118
+ // Inventory depends on both commerce and order
119
+ loader.add(
120
+ inventoryModule.configure({
121
+ config: {
122
+ dbNamespace: "main",
123
+ dependencies: {
124
+ commerce: $commerce,
125
+ order: $order,
126
+ },
127
+ },
128
+ })
129
+ );
130
+
131
+ return loader;
132
+ });
133
+ ```
134
+
135
+ The `loader.add()` method returns the configured module, which can then be passed as a dependency to other modules.
136
+
137
+ ## Common Configuration Options
138
+
139
+ Most modules support these common configuration patterns:
140
+
141
+ ### Custom Attributes
142
+
143
+ Add custom fields to module tables:
144
+
145
+ ```typescript
146
+ config: {
147
+ dataModel: {
148
+ product: {
149
+ customAttributes: {
150
+ myCustomField: db.string(),
151
+ priority: db.int(),
152
+ },
153
+ },
154
+ },
155
+ }
156
+ ```
157
+
158
+ ### Document Number Prefixes
159
+
160
+ Customize document number prefixes:
161
+
162
+ ```typescript
163
+ config: {
164
+ dataModel: {
165
+ order: {
166
+ docNumberPrefix: "ORD-2024",
167
+ },
168
+ },
169
+ }
170
+ ```
171
+
172
+ ## Next Steps
173
+
174
+ - See [Creating Modules](./creating-modules.md) if you want to build your own reusable modules
package/package.json CHANGED
@@ -1,35 +1,27 @@
1
1
  {
2
2
  "name": "@izumisy-tailor/omakase-modules",
3
3
  "private": false,
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "description": "Modularization mechanism for Tailor Platform application powered by Tailor SDK",
6
6
  "type": "module",
7
7
  "files": [
8
- "dist"
8
+ "src",
9
+ "docs"
9
10
  ],
10
11
  "exports": {
11
12
  ".": {
12
- "default": "./dist/config/index.mjs",
13
- "types": "./dist/config/index.d.mts"
13
+ "default": "./src/config/index.ts"
14
14
  },
15
15
  "./config/sdk": {
16
- "default": "./dist/config/sdk/index.mjs",
17
- "types": "./dist/config/sdk/index.d.mts"
16
+ "default": "./src/config/sdk/index.ts"
18
17
  },
19
18
  "./builder": {
20
- "default": "./dist/builder/index.mjs",
21
- "types": "./dist/builder/index.d.mts"
19
+ "default": "./src/builder/index.ts"
22
20
  },
23
21
  "./config/loader": {
24
- "default": "./dist/stub-loader/index.mjs",
25
- "types": "./dist/stub-loader/index.d.mts"
22
+ "default": "./src/stub-loader/index.ts"
26
23
  }
27
24
  },
28
- "scripts": {
29
- "build": "tsdown",
30
- "dev": "tsdown --watch",
31
- "type-check": "tsc"
32
- },
33
25
  "keywords": [
34
26
  "tailor-platform",
35
27
  "tailor-sdk",
@@ -38,13 +30,15 @@
38
30
  ],
39
31
  "author": "Tailor Inc.",
40
32
  "license": "MIT",
41
- "packageManager": "pnpm@10.22.0",
42
33
  "devDependencies": {
43
34
  "@types/node": "^25.0.3",
44
35
  "tsdown": "^0.18.0",
45
36
  "typescript": "^5"
46
37
  },
47
38
  "peerDependencies": {
48
- "@tailor-platform/sdk": "^0.17.0"
39
+ "@tailor-platform/sdk": "^0.20.0"
40
+ },
41
+ "scripts": {
42
+ "type-check": "tsc"
49
43
  }
50
- }
44
+ }