@izumisy-tailor/omakase-modules 0.1.0 → 0.3.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.
- package/README.md +47 -0
- package/docs/tutorials/creating-modules.md +296 -0
- package/docs/tutorials/using-modules.md +224 -0
- package/package.json +17 -28
- package/src/builder/helpers.ts +91 -0
- package/src/builder/index.ts +9 -0
- package/src/builder/register.ts +50 -0
- package/src/config/index.ts +1 -0
- package/src/config/module-loader.ts +93 -0
- package/src/config/sdk/index.ts +1 -0
- package/src/config/sdk/paths.ts +49 -0
- package/src/config/sdk/wrapper/base.ts +141 -0
- package/src/config/sdk/wrapper/generator.ts +52 -0
- package/src/config/sdk/wrapper/strategies.ts +102 -0
- package/dist/builder/index.d.mts +0 -3
- package/dist/builder/index.mjs +0 -35
- package/dist/config/index.d.mts +0 -2
- package/dist/config/index.mjs +0 -62
- package/dist/config/sdk/index.d.mts +0 -10
- package/dist/config/sdk/index.mjs +0 -14
- package/dist/helpers-CNjRbrYN.d.mts +0 -29
- package/dist/index-BoAL29Di.d.mts +0 -38
- package/dist/module-loader-B4sA1i0A.d.mts +0 -38
- package/dist/stub-loader/index.d.mts +0 -2
- package/dist/stub-loader/index.mjs +0 -31
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Omakase Modules
|
|
2
|
+
|
|
3
|
+
A **configurable module system** for Tailor Platform. Define reusable modules with type-safe configurations and share them across applications.
|
|
4
|
+
|
|
5
|
+
## Motivation
|
|
6
|
+
|
|
7
|
+
When building applications on Tailor Platform, you often face these challenges:
|
|
8
|
+
|
|
9
|
+
1. **Reusability**: You want to reuse common data models and business logic (e.g., e-commerce, inventory, orders) across multiple applications
|
|
10
|
+
2. **Customizability**: While modules should be reusable, you need to customize them for application-specific requirements
|
|
11
|
+
3. **Dependency Management**: Module dependencies should be explicitly defined and managed in a type-safe manner
|
|
12
|
+
|
|
13
|
+
Omakase Modules is designed to solve these challenges by providing a flexible, type-safe module system.
|
|
14
|
+
|
|
15
|
+
## Key Features
|
|
16
|
+
|
|
17
|
+
- **Module Definition**: Define modules with `defineModule` and declare type-safe configuration schemas
|
|
18
|
+
- **Module Configuration**: Configure modules at the application level, injecting custom attributes and prefixes
|
|
19
|
+
- **Dependency Management**: Explicitly define inter-module dependencies with the `ModuleDependency` type
|
|
20
|
+
- **Configuration Injection**: Inject configurations into TailorDB, Resolvers, and Executors using `withModuleConfiguration`
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm add @izumisy-tailor/omakase-modules
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
- [Using Modules](./docs/tutorials/using-modules.md) - How to use pre-built modules in your application
|
|
31
|
+
- [Creating Modules](./docs/tutorials/creating-modules.md) - How to create reusable modules
|
|
32
|
+
|
|
33
|
+
## API Reference
|
|
34
|
+
|
|
35
|
+
### `@izumisy-tailor/omakase-modules`
|
|
36
|
+
|
|
37
|
+
- `loadModules(configurator)` - Load and configure modules in your application
|
|
38
|
+
|
|
39
|
+
### `@izumisy-tailor/omakase-modules/builder`
|
|
40
|
+
|
|
41
|
+
- `defineModule<Config, Tables>(options)` - Define a new module
|
|
42
|
+
- `withModuleConfiguration(module, factory)` - Access module configuration in TailorDB, Resolvers, and Executors
|
|
43
|
+
- `ModuleDependency<T>` - Type utility for declaring module dependencies
|
|
44
|
+
|
|
45
|
+
### `@izumisy-tailor/omakase-modules/config/sdk`
|
|
46
|
+
|
|
47
|
+
- `getModulesReference(loadedModules)` - Generate file path references for `tailor.config.ts`
|
|
@@ -0,0 +1,296 @@
|
|
|
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 and table types export
|
|
15
|
+
types.ts # Configuration types
|
|
16
|
+
tailordb/
|
|
17
|
+
index.ts # TailorDB exports with tableNames
|
|
18
|
+
my-table.ts # Table builders
|
|
19
|
+
resolvers/
|
|
20
|
+
my-resolver.ts
|
|
21
|
+
executors/
|
|
22
|
+
my-executor.ts
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 1. Define the Module
|
|
26
|
+
|
|
27
|
+
Create the module definition with `defineModule`:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// src/module.ts
|
|
31
|
+
import {
|
|
32
|
+
defineModule,
|
|
33
|
+
type TablesFromNames,
|
|
34
|
+
} from "@izumisy-tailor/omakase-modules/builder";
|
|
35
|
+
import type { ModuleConfig } from "./types";
|
|
36
|
+
import { tableNames } from "./tailordb";
|
|
37
|
+
import * as pkg from "../package.json";
|
|
38
|
+
|
|
39
|
+
export default defineModule<ModuleConfig, TablesFromNames<typeof tableNames>>({
|
|
40
|
+
packageName: pkg.name,
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The `packageName` must match the `name` field in your `package.json`. The `TablesFromNames` utility type derives the table types from `tableNames`, ensuring they stay in sync.
|
|
45
|
+
|
|
46
|
+
## 2. Define Configuration Types
|
|
47
|
+
|
|
48
|
+
Define what configuration options your module accepts:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// src/types.ts
|
|
52
|
+
import { TailorField } from "@tailor-platform/sdk";
|
|
53
|
+
|
|
54
|
+
type DataModelConfiguration = {
|
|
55
|
+
docNumberPrefix?: string;
|
|
56
|
+
customAttributes?: Record<string, TailorField<any>>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type ModuleConfig = {
|
|
60
|
+
dataModel?: {
|
|
61
|
+
product?: DataModelConfiguration;
|
|
62
|
+
category?: DataModelConfiguration;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 3. Build Tables with Configuration
|
|
68
|
+
|
|
69
|
+
Use `withModuleConfiguration` to access configuration when building tables:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// src/tailordb/index.ts
|
|
73
|
+
import {
|
|
74
|
+
withModuleConfiguration,
|
|
75
|
+
type TablesFromNames,
|
|
76
|
+
} from "@izumisy-tailor/omakase-modules/builder";
|
|
77
|
+
import moduleDef from "../module";
|
|
78
|
+
import { buildProductTable } from "./product";
|
|
79
|
+
import { buildCategoryTable } from "./category";
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* List of table names exported by this module.
|
|
83
|
+
* This is the single source of truth for table definitions.
|
|
84
|
+
*/
|
|
85
|
+
export const tableNames = ["product", "category"] as const;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Factory function that creates tailordb tables with the given module configuration.
|
|
89
|
+
* This is called by the wrapper files generated by getModulesReference.
|
|
90
|
+
*/
|
|
91
|
+
export default withModuleConfiguration(moduleDef, (context) => {
|
|
92
|
+
const category = buildCategoryTable(context);
|
|
93
|
+
const product = buildProductTable(context, { category });
|
|
94
|
+
|
|
95
|
+
return { product, category } satisfies TablesFromNames<typeof tableNames>;
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> **Important**: The `tableNames` export is required for the wrapper generator to create named exports for each table.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// src/tailordb/product.ts
|
|
103
|
+
import { type ModuleFactoryContext } from "@izumisy-tailor/omakase-modules/builder";
|
|
104
|
+
import { db, type TailorDBType } from "@tailor-platform/sdk";
|
|
105
|
+
import type { ModuleConfig } from "../types";
|
|
106
|
+
|
|
107
|
+
export const buildProductTable = (
|
|
108
|
+
{ config }: ModuleFactoryContext<ModuleConfig>,
|
|
109
|
+
deps: { category: TailorDBType }
|
|
110
|
+
) => {
|
|
111
|
+
const customAttributes = config.dataModel?.product?.customAttributes || {};
|
|
112
|
+
const docNumberPrefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
|
|
113
|
+
|
|
114
|
+
return db.type("Product", {
|
|
115
|
+
name: db.string(),
|
|
116
|
+
sku: db.string().unique(),
|
|
117
|
+
categoryId: db.uuid({ optional: true }).relation({
|
|
118
|
+
type: "keyOnly",
|
|
119
|
+
toward: { type: deps.category },
|
|
120
|
+
}),
|
|
121
|
+
docNumber: db.docNumber({ prefix: docNumberPrefix }),
|
|
122
|
+
...customAttributes,
|
|
123
|
+
...db.fields.timestamps(),
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 4. Declare Dependencies on Other Modules
|
|
129
|
+
|
|
130
|
+
If your module depends on other modules, use `ModuleDependency`:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// src/types.ts
|
|
134
|
+
import type { ModuleDependency } from "@izumisy-tailor/omakase-modules/builder";
|
|
135
|
+
import type commerceCoreModule from "omakase-module-commerce-core";
|
|
136
|
+
|
|
137
|
+
export type ModuleConfig = {
|
|
138
|
+
dataModel?: { /* ... */ };
|
|
139
|
+
dependencies: {
|
|
140
|
+
commerce: ModuleDependency<typeof commerceCoreModule>;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
This ensures type-safe dependency injection when users configure your module.
|
|
146
|
+
|
|
147
|
+
### Using Dependency Tables in TailorDB
|
|
148
|
+
|
|
149
|
+
When your module needs to reference tables from dependency modules, use `loadedModules.getTables()` in an async factory function:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// src/tailordb/index.ts
|
|
153
|
+
import { withModuleConfiguration } from "@izumisy-tailor/omakase-modules/builder";
|
|
154
|
+
import moduleDef from "../module";
|
|
155
|
+
import commerceModuleTables from "omakase-module-commerce-core/backend/tailordb";
|
|
156
|
+
|
|
157
|
+
export default withModuleConfiguration(
|
|
158
|
+
moduleDef,
|
|
159
|
+
async (context, loadedModules) => {
|
|
160
|
+
// Get tables from dependency modules
|
|
161
|
+
const { product, productVariant } = await loadedModules.getTables(
|
|
162
|
+
commerceModuleTables
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const inventory = buildInventoryTable(context, { product, productVariant });
|
|
166
|
+
// ...
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Using Dependency Tables in Executors
|
|
172
|
+
|
|
173
|
+
Executors can also access dependency tables:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// src/executors/myExecutor.ts
|
|
177
|
+
import { withModuleConfiguration } from "@izumisy-tailor/omakase-modules/builder";
|
|
178
|
+
import { createExecutor, recordCreatedTrigger } from "@tailor-platform/sdk";
|
|
179
|
+
import commerceModuleTables from "omakase-module-commerce-core/backend/tailordb";
|
|
180
|
+
import moduleDef from "../module";
|
|
181
|
+
|
|
182
|
+
export default withModuleConfiguration(
|
|
183
|
+
moduleDef,
|
|
184
|
+
async (_context, loadedModules) => {
|
|
185
|
+
const { productVariant } = await loadedModules.getTables(
|
|
186
|
+
commerceModuleTables
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
return createExecutor({
|
|
190
|
+
name: "my-executor",
|
|
191
|
+
trigger: recordCreatedTrigger({ type: productVariant }),
|
|
192
|
+
operation: { /* ... */ },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## File Export Requirements
|
|
199
|
+
|
|
200
|
+
Due to Tailor SDK API requirements, **TailorDB** and **Resolvers/Executors** have different export patterns:
|
|
201
|
+
|
|
202
|
+
**TailorDB**: Should use a single `index.ts` barrel export with a `tableNames` constant and a default factory function. This is **strongly recommended** because:
|
|
203
|
+
1. It allows you to use `satisfies` to verify that all required tables are defined
|
|
204
|
+
2. The `tableNames` export enables the wrapper generator to create named exports
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// src/tailordb/index.ts
|
|
208
|
+
export const tableNames = ["product", "category"] as const;
|
|
209
|
+
|
|
210
|
+
export default withModuleConfiguration(moduleDef, (context) => {
|
|
211
|
+
const category = buildCategoryTable(context);
|
|
212
|
+
const product = buildProductTable(context, { category });
|
|
213
|
+
|
|
214
|
+
// Type error if any required table is missing
|
|
215
|
+
return { product, category } satisfies TablesFromNames<typeof tableNames>;
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
src/tailordb/
|
|
221
|
+
index.ts # Exports tableNames and default factory
|
|
222
|
+
product.ts # Table builder (not directly exported)
|
|
223
|
+
category.ts # Table builder (not directly exported)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**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`:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
src/resolvers/
|
|
230
|
+
getProduct.ts # Each resolver in its own file
|
|
231
|
+
listProducts.ts
|
|
232
|
+
src/executors/
|
|
233
|
+
onProductCreated.ts # Each executor in its own file
|
|
234
|
+
onOrderPlaced.ts
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
This is because the Tailor SDK processes resolver and executor files individually, expecting each file to contain a single definition with a default export.
|
|
238
|
+
|
|
239
|
+
## 5. Configure Package Exports
|
|
240
|
+
|
|
241
|
+
Set up your `package.json` to export the module files.
|
|
242
|
+
|
|
243
|
+
> **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.
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"name": "my-module",
|
|
248
|
+
"type": "module",
|
|
249
|
+
"exports": {
|
|
250
|
+
".": "./src/module.ts",
|
|
251
|
+
"./backend/tailordb": "./src/tailordb/index.ts",
|
|
252
|
+
"./backend/resolvers/*": "./src/resolvers/*.ts",
|
|
253
|
+
"./backend/executors/*": "./src/executors/*.ts"
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Note that TailorDB uses an `index.ts` barrel export, while resolvers and executors use wildcard patterns to export individual files.
|
|
259
|
+
|
|
260
|
+
> **Design Note**: Modules always export TypeScript source files directly—there is no need to build or bundle them. The Tailor SDK handles TypeScript compilation and bundling as part of its deployment process, so providing raw `.ts` files eliminates unnecessary build steps and keeps the module development workflow simple.
|
|
261
|
+
|
|
262
|
+
## Best Practices
|
|
263
|
+
|
|
264
|
+
### Use Factory Functions for Tables
|
|
265
|
+
|
|
266
|
+
Always use factory functions (like `buildProductTable`) instead of directly exporting table definitions. This allows configuration to be injected.
|
|
267
|
+
|
|
268
|
+
### Type Your Tables
|
|
269
|
+
|
|
270
|
+
Use `satisfies` with `TablesFromNames` to ensure your returned tables match the expected type:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
return { product, category } satisfies TablesFromNames<typeof tableNames>;
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Provide Sensible Defaults
|
|
277
|
+
|
|
278
|
+
Always provide default values for optional configuration:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const prefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Utility Types Reference
|
|
285
|
+
|
|
286
|
+
The `@izumisy-tailor/omakase-modules/builder` package provides these utility types:
|
|
287
|
+
|
|
288
|
+
| Type | Description |
|
|
289
|
+
|------|-------------|
|
|
290
|
+
| `TablesFromNames<T>` | Derives a tables type from a `tableNames` array. `T` should be `typeof tableNames`. |
|
|
291
|
+
| `ModuleFactoryContext<C>` | Context passed to table builder functions. `C` is your module's config type. |
|
|
292
|
+
| `ModuleDependency<T>` | Type for declaring dependencies on other modules. `T` is the module's default export type. |
|
|
293
|
+
|
|
294
|
+
## Next Steps
|
|
295
|
+
|
|
296
|
+
- See [Using Modules](./using-modules.md) for how applications consume your module
|
|
@@ -0,0 +1,224 @@
|
|
|
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
|
+
> **Note**: The `loadModules` function registers all configured modules in a global registry, which is later used by `getModulesReference` to generate wrapper files.
|
|
43
|
+
|
|
44
|
+
## 2. Configure TypeScript Path Alias
|
|
45
|
+
|
|
46
|
+
You must configure a path alias in your `tsconfig.json` to point to the `modules.ts` file you created above. This alias is required for the generated wrapper files to correctly import your module configuration:
|
|
47
|
+
|
|
48
|
+
```jsonc
|
|
49
|
+
// tsconfig.json
|
|
50
|
+
{
|
|
51
|
+
"compilerOptions": {
|
|
52
|
+
// ... other options
|
|
53
|
+
"paths": {
|
|
54
|
+
"@omakase-modules/config": ["./modules"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The `@omakase-modules/config` alias should point to your `modules.ts` file (without the `.ts` extension). The wrapper files generated by `getModulesReference` use this alias to import the configured modules.
|
|
61
|
+
|
|
62
|
+
## 3. Reference Modules in tailor.config.ts
|
|
63
|
+
|
|
64
|
+
Use `getModulesReference` to include module files in your Tailor configuration:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// tailor.config.ts
|
|
68
|
+
import { defineConfig } from "@tailor-platform/sdk";
|
|
69
|
+
import { getModulesReference } from "@izumisy-tailor/omakase-modules/config/sdk";
|
|
70
|
+
import modules from "./modules";
|
|
71
|
+
|
|
72
|
+
const moduleReference = await getModulesReference(modules);
|
|
73
|
+
|
|
74
|
+
export default defineConfig({
|
|
75
|
+
name: "my-app",
|
|
76
|
+
db: {
|
|
77
|
+
main: {
|
|
78
|
+
files: ["./src/tailordb/*.ts", ...moduleReference.tailordb],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
resolver: {
|
|
82
|
+
"main-pipeline": {
|
|
83
|
+
files: ["./src/resolvers/*.ts", ...moduleReference.resolver],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
executor: {
|
|
87
|
+
files: ["./src/executors/**/*.ts", ...moduleReference.executor],
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`getModulesReference` generates wrapper files in `.tailor-sdk/.omakase` that properly inject module configurations and create named exports for each table. Make sure to add this directory to your `.gitignore`.
|
|
93
|
+
|
|
94
|
+
### Generated Wrapper Files
|
|
95
|
+
|
|
96
|
+
The wrapper generator creates files that:
|
|
97
|
+
1. Import the factory function from each module
|
|
98
|
+
2. Call it with the loaded modules from your `modules.ts`
|
|
99
|
+
3. Export the results (tables, resolvers, executors) for use by Tailor SDK
|
|
100
|
+
|
|
101
|
+
## 4. Handle Module Dependencies
|
|
102
|
+
|
|
103
|
+
When modules depend on other modules, you need to wire them together:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
// modules.ts
|
|
107
|
+
import { loadModules } from "@izumisy-tailor/omakase-modules";
|
|
108
|
+
import { db } from "@tailor-platform/sdk";
|
|
109
|
+
import ecommerceCoreModule from "omakase-module-commerce-core";
|
|
110
|
+
import orderModule from "omakase-module-order";
|
|
111
|
+
import inventoryModule from "omakase-module-inventory";
|
|
112
|
+
|
|
113
|
+
export default loadModules((loader) => {
|
|
114
|
+
// Add the base module first
|
|
115
|
+
const $commerce = loader.add(
|
|
116
|
+
ecommerceCoreModule.configure({
|
|
117
|
+
config: {
|
|
118
|
+
dataModel: {
|
|
119
|
+
product: {
|
|
120
|
+
docNumberPrefix: "PP-PROD",
|
|
121
|
+
customAttributes: {
|
|
122
|
+
customStatus: db.enum(["new", "used", "refurbished"]),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// Pass the commerce module as a dependency
|
|
131
|
+
const $order = loader.add(
|
|
132
|
+
orderModule.configure({
|
|
133
|
+
config: {
|
|
134
|
+
dependencies: {
|
|
135
|
+
commerce: $commerce,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// Inventory depends on both commerce and order
|
|
142
|
+
loader.add(
|
|
143
|
+
inventoryModule.configure({
|
|
144
|
+
config: {
|
|
145
|
+
dbNamespace: "main",
|
|
146
|
+
dependencies: {
|
|
147
|
+
commerce: $commerce,
|
|
148
|
+
order: $order,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
return loader;
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The `loader.add()` method returns the configured module, which can then be passed as a dependency to other modules. This ensures type-safe dependency wiring.
|
|
159
|
+
|
|
160
|
+
## Common Configuration Options
|
|
161
|
+
|
|
162
|
+
Most modules support these common configuration patterns:
|
|
163
|
+
|
|
164
|
+
### Custom Attributes
|
|
165
|
+
|
|
166
|
+
Add custom fields to module tables:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
config: {
|
|
170
|
+
dataModel: {
|
|
171
|
+
product: {
|
|
172
|
+
customAttributes: {
|
|
173
|
+
myCustomField: db.string(),
|
|
174
|
+
priority: db.int(),
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Document Number Prefixes
|
|
182
|
+
|
|
183
|
+
Customize document number prefixes:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
config: {
|
|
187
|
+
dataModel: {
|
|
188
|
+
order: {
|
|
189
|
+
docNumberPrefix: "ORD-2024",
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Module-Specific Options
|
|
196
|
+
|
|
197
|
+
Some modules have their own configuration options:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// Inventory module example
|
|
201
|
+
config: {
|
|
202
|
+
dbNamespace: "main", // Required: TailorDB namespace for this module
|
|
203
|
+
invantoryBootstrapBaseValue: 200, // Module-specific option
|
|
204
|
+
dependencies: { /* ... */ },
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Troubleshooting
|
|
209
|
+
|
|
210
|
+
### Module Not Found
|
|
211
|
+
|
|
212
|
+
If you see errors about modules not being found, ensure:
|
|
213
|
+
1. The module is installed as a dependency in your `package.json`
|
|
214
|
+
2. The module is added via `loader.add()` in your `modules.ts`
|
|
215
|
+
|
|
216
|
+
### Type Errors with Dependencies
|
|
217
|
+
|
|
218
|
+
If you see type errors when passing dependencies:
|
|
219
|
+
1. Ensure the dependency module is added before the dependent module
|
|
220
|
+
2. Use the return value from `loader.add()` as the dependency value
|
|
221
|
+
|
|
222
|
+
## Next Steps
|
|
223
|
+
|
|
224
|
+
- See [Creating Modules](./creating-modules.md) if you want to build your own reusable modules
|
package/package.json
CHANGED
|
@@ -1,34 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@izumisy-tailor/omakase-modules",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "Modularization mechanism for Tailor Platform application powered by Tailor SDK",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"
|
|
8
|
+
"src",
|
|
9
|
+
"docs"
|
|
9
10
|
],
|
|
10
11
|
"exports": {
|
|
11
|
-
".":
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
"./config/sdk": {
|
|
16
|
-
"default": "./dist/config/sdk/index.mjs",
|
|
17
|
-
"types": "./dist/config/sdk/index.d.mts"
|
|
18
|
-
},
|
|
19
|
-
"./builder": {
|
|
20
|
-
"default": "./dist/builder/index.mjs",
|
|
21
|
-
"types": "./dist/builder/index.d.mts"
|
|
22
|
-
},
|
|
23
|
-
"./config/loader": {
|
|
24
|
-
"default": "./dist/stub-loader/index.mjs",
|
|
25
|
-
"types": "./dist/stub-loader/index.d.mts"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "tsdown",
|
|
30
|
-
"dev": "tsdown --watch",
|
|
31
|
-
"type-check": "tsc"
|
|
12
|
+
".": "./src/config/index.ts",
|
|
13
|
+
"./config/sdk": "./src/config/sdk/index.ts",
|
|
14
|
+
"./builder": "./src/builder/index.ts"
|
|
32
15
|
},
|
|
33
16
|
"keywords": [
|
|
34
17
|
"tailor-platform",
|
|
@@ -38,13 +21,19 @@
|
|
|
38
21
|
],
|
|
39
22
|
"author": "Tailor Inc.",
|
|
40
23
|
"license": "MIT",
|
|
41
|
-
"packageManager": "pnpm@10.22.0",
|
|
42
24
|
"devDependencies": {
|
|
43
25
|
"@types/node": "^25.0.3",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
26
|
+
"typescript": "^5",
|
|
27
|
+
"vitest": "^4.0.16"
|
|
46
28
|
},
|
|
47
29
|
"peerDependencies": {
|
|
48
|
-
"@tailor-platform/sdk": "^0.
|
|
30
|
+
"@tailor-platform/sdk": "^0.20.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"dedent": "^1.7.1"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"type-check": "tsc",
|
|
37
|
+
"test": "vitest run"
|
|
49
38
|
}
|
|
50
|
-
}
|
|
39
|
+
}
|