@izumisy-tailor/omakase-modules 0.2.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 +0 -12
- package/docs/tutorials/creating-modules.md +110 -70
- package/docs/tutorials/using-modules.md +58 -8
- package/package.json +11 -16
- package/src/builder/helpers.ts +40 -0
- package/src/builder/index.ts +2 -0
- package/src/builder/register.ts +38 -22
- package/src/config/module-loader.ts +20 -12
- package/src/config/sdk/paths.ts +41 -12
- 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/docs/examples/data-models/core/inventory-module.md +0 -230
- package/docs/examples/data-models/core/order-module.md +0 -132
- package/docs/examples/data-models/scenarios/inventory-reservation-scenario.md +0 -73
- package/docs/examples/data-models/scenarios/multi-storefront-order-scenario.md +0 -99
- package/docs/examples/data-models/scenarios/order-payment-status-scenario.md +0 -92
- package/docs/examples/data-models/scenarios/procurement-order-scenario.md +0 -95
- package/src/config/module-registry.ts +0 -22
- package/src/stub-loader/index.ts +0 -3
- package/src/stub-loader/interface.ts +0 -40
package/README.md
CHANGED
|
@@ -45,15 +45,3 @@ pnpm add @izumisy-tailor/omakase-modules
|
|
|
45
45
|
### `@izumisy-tailor/omakase-modules/config/sdk`
|
|
46
46
|
|
|
47
47
|
- `getModulesReference(loadedModules)` - Generate file path references for `tailor.config.ts`
|
|
48
|
-
|
|
49
|
-
## Project Structure
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
examples/
|
|
53
|
-
commerce-core-module/ # E-commerce core module (Product, Customer, etc.)
|
|
54
|
-
order-module/ # Order management module
|
|
55
|
-
inventory-module/ # Inventory management module
|
|
56
|
-
basic-app/ # Application using the above modules
|
|
57
|
-
packages/
|
|
58
|
-
core/ # omakase-modules core package
|
|
59
|
-
```
|
|
@@ -11,11 +11,10 @@ my-module/
|
|
|
11
11
|
package.json
|
|
12
12
|
tsconfig.json
|
|
13
13
|
src/
|
|
14
|
-
module.ts # Module definition
|
|
14
|
+
module.ts # Module definition and table types export
|
|
15
15
|
types.ts # Configuration types
|
|
16
16
|
tailordb/
|
|
17
|
-
index.ts # TailorDB exports
|
|
18
|
-
context.ts # Type definitions for tables
|
|
17
|
+
index.ts # TailorDB exports with tableNames
|
|
19
18
|
my-table.ts # Table builders
|
|
20
19
|
resolvers/
|
|
21
20
|
my-resolver.ts
|
|
@@ -29,17 +28,20 @@ Create the module definition with `defineModule`:
|
|
|
29
28
|
|
|
30
29
|
```typescript
|
|
31
30
|
// src/module.ts
|
|
32
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
defineModule,
|
|
33
|
+
type TablesFromNames,
|
|
34
|
+
} from "@izumisy-tailor/omakase-modules/builder";
|
|
33
35
|
import type { ModuleConfig } from "./types";
|
|
34
|
-
import
|
|
36
|
+
import { tableNames } from "./tailordb";
|
|
35
37
|
import * as pkg from "../package.json";
|
|
36
38
|
|
|
37
|
-
export default defineModule<ModuleConfig,
|
|
39
|
+
export default defineModule<ModuleConfig, TablesFromNames<typeof tableNames>>({
|
|
38
40
|
packageName: pkg.name,
|
|
39
41
|
});
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
The `packageName` must match the `name` field in your `package.json`.
|
|
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.
|
|
43
45
|
|
|
44
46
|
## 2. Define Configuration Types
|
|
45
47
|
|
|
@@ -62,55 +64,48 @@ export type ModuleConfig = {
|
|
|
62
64
|
};
|
|
63
65
|
```
|
|
64
66
|
|
|
65
|
-
## 3.
|
|
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
|
|
67
|
+
## 3. Build Tables with Configuration
|
|
85
68
|
|
|
86
69
|
Use `withModuleConfiguration` to access configuration when building tables:
|
|
87
70
|
|
|
88
71
|
```typescript
|
|
89
72
|
// src/tailordb/index.ts
|
|
90
|
-
import {
|
|
91
|
-
|
|
73
|
+
import {
|
|
74
|
+
withModuleConfiguration,
|
|
75
|
+
type TablesFromNames,
|
|
76
|
+
} from "@izumisy-tailor/omakase-modules/builder";
|
|
92
77
|
import moduleDef from "../module";
|
|
93
78
|
import { buildProductTable } from "./product";
|
|
94
79
|
import { buildCategoryTable } from "./category";
|
|
95
80
|
|
|
96
|
-
|
|
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) => {
|
|
97
92
|
const category = buildCategoryTable(context);
|
|
98
93
|
const product = buildProductTable(context, { category });
|
|
99
94
|
|
|
100
|
-
return { product, category } satisfies
|
|
95
|
+
return { product, category } satisfies TablesFromNames<typeof tableNames>;
|
|
101
96
|
});
|
|
102
|
-
|
|
103
|
-
export const productTable = tables.product;
|
|
104
|
-
export const categoryTable = tables.category;
|
|
105
97
|
```
|
|
106
98
|
|
|
99
|
+
> **Important**: The `tableNames` export is required for the wrapper generator to create named exports for each table.
|
|
100
|
+
|
|
107
101
|
```typescript
|
|
108
102
|
// src/tailordb/product.ts
|
|
109
|
-
import {
|
|
110
|
-
import type
|
|
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";
|
|
111
106
|
|
|
112
107
|
export const buildProductTable = (
|
|
113
|
-
{ config }: ModuleFactoryContext
|
|
108
|
+
{ config }: ModuleFactoryContext<ModuleConfig>,
|
|
114
109
|
deps: { category: TailorDBType }
|
|
115
110
|
) => {
|
|
116
111
|
const customAttributes = config.dataModel?.product?.customAttributes || {};
|
|
@@ -130,7 +125,7 @@ export const buildProductTable = (
|
|
|
130
125
|
};
|
|
131
126
|
```
|
|
132
127
|
|
|
133
|
-
##
|
|
128
|
+
## 4. Declare Dependencies on Other Modules
|
|
134
129
|
|
|
135
130
|
If your module depends on other modules, use `ModuleDependency`:
|
|
136
131
|
|
|
@@ -149,26 +144,81 @@ export type ModuleConfig = {
|
|
|
149
144
|
|
|
150
145
|
This ensures type-safe dependency injection when users configure your module.
|
|
151
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
|
+
|
|
152
198
|
## File Export Requirements
|
|
153
199
|
|
|
154
200
|
Due to Tailor SDK API requirements, **TailorDB** and **Resolvers/Executors** have different export patterns:
|
|
155
201
|
|
|
156
|
-
**TailorDB**: Should use a single `index.ts` barrel export
|
|
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
|
|
157
205
|
|
|
158
206
|
```typescript
|
|
159
207
|
// src/tailordb/index.ts
|
|
160
|
-
const
|
|
208
|
+
export const tableNames = ["product", "category"] as const;
|
|
209
|
+
|
|
210
|
+
export default withModuleConfiguration(moduleDef, (context) => {
|
|
161
211
|
const category = buildCategoryTable(context);
|
|
162
212
|
const product = buildProductTable(context, { category });
|
|
163
213
|
|
|
164
214
|
// Type error if any required table is missing
|
|
165
|
-
return { product, category } satisfies
|
|
215
|
+
return { product, category } satisfies TablesFromNames<typeof tableNames>;
|
|
166
216
|
});
|
|
167
217
|
```
|
|
168
218
|
|
|
169
219
|
```
|
|
170
220
|
src/tailordb/
|
|
171
|
-
index.ts # Exports
|
|
221
|
+
index.ts # Exports tableNames and default factory
|
|
172
222
|
product.ts # Table builder (not directly exported)
|
|
173
223
|
category.ts # Table builder (not directly exported)
|
|
174
224
|
```
|
|
@@ -186,9 +236,9 @@ src/executors/
|
|
|
186
236
|
|
|
187
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.
|
|
188
238
|
|
|
189
|
-
##
|
|
239
|
+
## 5. Configure Package Exports
|
|
190
240
|
|
|
191
|
-
Set up your `package.json` to export the
|
|
241
|
+
Set up your `package.json` to export the module files.
|
|
192
242
|
|
|
193
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.
|
|
194
244
|
|
|
@@ -197,27 +247,17 @@ Set up your `package.json` to export the built files.
|
|
|
197
247
|
"name": "my-module",
|
|
198
248
|
"type": "module",
|
|
199
249
|
"exports": {
|
|
200
|
-
".":
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
}
|
|
250
|
+
".": "./src/module.ts",
|
|
251
|
+
"./backend/tailordb": "./src/tailordb/index.ts",
|
|
252
|
+
"./backend/resolvers/*": "./src/resolvers/*.ts",
|
|
253
|
+
"./backend/executors/*": "./src/executors/*.ts"
|
|
216
254
|
}
|
|
217
255
|
}
|
|
218
256
|
```
|
|
219
257
|
|
|
220
|
-
Note that TailorDB uses an `index.
|
|
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.
|
|
221
261
|
|
|
222
262
|
## Best Practices
|
|
223
263
|
|
|
@@ -227,10 +267,10 @@ Always use factory functions (like `buildProductTable`) instead of directly expo
|
|
|
227
267
|
|
|
228
268
|
### Type Your Tables
|
|
229
269
|
|
|
230
|
-
Use `satisfies` to ensure your returned tables match the expected type:
|
|
270
|
+
Use `satisfies` with `TablesFromNames` to ensure your returned tables match the expected type:
|
|
231
271
|
|
|
232
272
|
```typescript
|
|
233
|
-
return { product, category } satisfies
|
|
273
|
+
return { product, category } satisfies TablesFromNames<typeof tableNames>;
|
|
234
274
|
```
|
|
235
275
|
|
|
236
276
|
### Provide Sensible Defaults
|
|
@@ -241,15 +281,15 @@ Always provide default values for optional configuration:
|
|
|
241
281
|
const prefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
|
|
242
282
|
```
|
|
243
283
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
Export individual table references for use in other modules:
|
|
284
|
+
## Utility Types Reference
|
|
247
285
|
|
|
248
|
-
|
|
249
|
-
export const productTable = tables.product;
|
|
250
|
-
```
|
|
286
|
+
The `@izumisy-tailor/omakase-modules/builder` package provides these utility types:
|
|
251
287
|
|
|
252
|
-
|
|
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. |
|
|
253
293
|
|
|
254
294
|
## Next Steps
|
|
255
295
|
|
|
@@ -39,21 +39,25 @@ export default loadModules((loader) => {
|
|
|
39
39
|
|
|
40
40
|
Each module exposes a `configure()` method that accepts a type-safe configuration object. The available options are defined by the module author.
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
> **Note**: The `loadModules` function registers all configured modules in a global registry, which is later used by `getModulesReference` to generate wrapper files.
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
## 2. Configure TypeScript Path Alias
|
|
45
45
|
|
|
46
|
-
|
|
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
|
|
47
50
|
{
|
|
48
51
|
"compilerOptions": {
|
|
52
|
+
// ... other options
|
|
49
53
|
"paths": {
|
|
50
|
-
"@
|
|
54
|
+
"@omakase-modules/config": ["./modules"]
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
```
|
|
55
59
|
|
|
56
|
-
|
|
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.
|
|
57
61
|
|
|
58
62
|
## 3. Reference Modules in tailor.config.ts
|
|
59
63
|
|
|
@@ -65,7 +69,7 @@ import { defineConfig } from "@tailor-platform/sdk";
|
|
|
65
69
|
import { getModulesReference } from "@izumisy-tailor/omakase-modules/config/sdk";
|
|
66
70
|
import modules from "./modules";
|
|
67
71
|
|
|
68
|
-
const moduleReference = getModulesReference(modules);
|
|
72
|
+
const moduleReference = await getModulesReference(modules);
|
|
69
73
|
|
|
70
74
|
export default defineConfig({
|
|
71
75
|
name: "my-app",
|
|
@@ -85,6 +89,15 @@ export default defineConfig({
|
|
|
85
89
|
});
|
|
86
90
|
```
|
|
87
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
|
+
|
|
88
101
|
## 4. Handle Module Dependencies
|
|
89
102
|
|
|
90
103
|
When modules depend on other modules, you need to wire them together:
|
|
@@ -92,6 +105,7 @@ When modules depend on other modules, you need to wire them together:
|
|
|
92
105
|
```typescript
|
|
93
106
|
// modules.ts
|
|
94
107
|
import { loadModules } from "@izumisy-tailor/omakase-modules";
|
|
108
|
+
import { db } from "@tailor-platform/sdk";
|
|
95
109
|
import ecommerceCoreModule from "omakase-module-commerce-core";
|
|
96
110
|
import orderModule from "omakase-module-order";
|
|
97
111
|
import inventoryModule from "omakase-module-inventory";
|
|
@@ -100,7 +114,16 @@ export default loadModules((loader) => {
|
|
|
100
114
|
// Add the base module first
|
|
101
115
|
const $commerce = loader.add(
|
|
102
116
|
ecommerceCoreModule.configure({
|
|
103
|
-
config: {
|
|
117
|
+
config: {
|
|
118
|
+
dataModel: {
|
|
119
|
+
product: {
|
|
120
|
+
docNumberPrefix: "PP-PROD",
|
|
121
|
+
customAttributes: {
|
|
122
|
+
customStatus: db.enum(["new", "used", "refurbished"]),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
104
127
|
})
|
|
105
128
|
);
|
|
106
129
|
|
|
@@ -132,7 +155,7 @@ export default loadModules((loader) => {
|
|
|
132
155
|
});
|
|
133
156
|
```
|
|
134
157
|
|
|
135
|
-
The `loader.add()` method returns the configured module, which can then be passed as a dependency to other modules.
|
|
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.
|
|
136
159
|
|
|
137
160
|
## Common Configuration Options
|
|
138
161
|
|
|
@@ -169,6 +192,33 @@ config: {
|
|
|
169
192
|
}
|
|
170
193
|
```
|
|
171
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
|
+
|
|
172
222
|
## Next Steps
|
|
173
223
|
|
|
174
224
|
- See [Creating Modules](./creating-modules.md) if you want to build your own reusable modules
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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": [
|
|
@@ -9,18 +9,9 @@
|
|
|
9
9
|
"docs"
|
|
10
10
|
],
|
|
11
11
|
"exports": {
|
|
12
|
-
".":
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"./config/sdk": {
|
|
16
|
-
"default": "./src/config/sdk/index.ts"
|
|
17
|
-
},
|
|
18
|
-
"./builder": {
|
|
19
|
-
"default": "./src/builder/index.ts"
|
|
20
|
-
},
|
|
21
|
-
"./config/loader": {
|
|
22
|
-
"default": "./src/stub-loader/index.ts"
|
|
23
|
-
}
|
|
12
|
+
".": "./src/config/index.ts",
|
|
13
|
+
"./config/sdk": "./src/config/sdk/index.ts",
|
|
14
|
+
"./builder": "./src/builder/index.ts"
|
|
24
15
|
},
|
|
25
16
|
"keywords": [
|
|
26
17
|
"tailor-platform",
|
|
@@ -32,13 +23,17 @@
|
|
|
32
23
|
"license": "MIT",
|
|
33
24
|
"devDependencies": {
|
|
34
25
|
"@types/node": "^25.0.3",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
26
|
+
"typescript": "^5",
|
|
27
|
+
"vitest": "^4.0.16"
|
|
37
28
|
},
|
|
38
29
|
"peerDependencies": {
|
|
39
30
|
"@tailor-platform/sdk": "^0.20.0"
|
|
40
31
|
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"dedent": "^1.7.1"
|
|
34
|
+
},
|
|
41
35
|
"scripts": {
|
|
42
|
-
"type-check": "tsc"
|
|
36
|
+
"type-check": "tsc",
|
|
37
|
+
"test": "vitest run"
|
|
43
38
|
}
|
|
44
39
|
}
|
package/src/builder/helpers.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { TailorDBType } from "@tailor-platform/sdk";
|
|
2
|
+
|
|
1
3
|
type ModuleBuilderProps<C extends Record<string, unknown>> = {
|
|
2
4
|
config: C;
|
|
3
5
|
};
|
|
@@ -49,3 +51,41 @@ export type ModuleDependency<T extends DefinedModule<any, any>> =
|
|
|
49
51
|
readonly __tablesBrand?: Tables;
|
|
50
52
|
}
|
|
51
53
|
: never;
|
|
54
|
+
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Utility Types for Module Development
|
|
57
|
+
// ============================================================================
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Derives a tables type from a tableNames array.
|
|
61
|
+
* Use this to avoid manually defining a separate Tables type.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* export const tableNames = ["product", "category"] as const;
|
|
66
|
+
* type MyTables = TablesFromNames<typeof tableNames>;
|
|
67
|
+
* // Result: { product: TailorDBType; category: TailorDBType }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export type TablesFromNames<T extends readonly string[]> = {
|
|
71
|
+
[K in T[number]]: TailorDBType;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Context passed to table builder functions.
|
|
76
|
+
* Provides access to the module's configuration.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* export const buildProductTable = (
|
|
81
|
+
* { config }: ModuleFactoryContext<ModuleConfig>,
|
|
82
|
+
* deps: { category: TailorDBType }
|
|
83
|
+
* ) => {
|
|
84
|
+
* const prefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
|
|
85
|
+
* return db.type("Product", { ... });
|
|
86
|
+
* };
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export type ModuleFactoryContext<C extends Record<string, unknown>> = {
|
|
90
|
+
config: C;
|
|
91
|
+
};
|
package/src/builder/index.ts
CHANGED
package/src/builder/register.ts
CHANGED
|
@@ -1,34 +1,50 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LoadedModules } from "../config/module-loader";
|
|
2
2
|
import type { DefinedModule } from "./helpers";
|
|
3
3
|
|
|
4
|
-
type ModuleFactoryContext<C extends Record<string, unknown>> =
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
type ModuleFactoryContext<C extends Record<string, unknown>> = {
|
|
5
|
+
config: C;
|
|
6
|
+
};
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Define module exports that depend on configuration from loadModules.
|
|
10
|
+
*
|
|
11
|
+
* This function returns a factory function that takes LoadedModules as input
|
|
12
|
+
* and produces the configured exports. The wrapper files generated by
|
|
13
|
+
* getModulesReference will call this factory with the app's loadModules result.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // In module's tailordb/index.ts
|
|
18
|
+
* export default withModuleConfiguration(moduleDef, (context) => {
|
|
19
|
+
* const inventory = buildInventoryTable(context);
|
|
20
|
+
* return { inventory };
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // In module's executors that need dependency module tables:
|
|
24
|
+
* export default withModuleConfiguration(moduleDef, async (context, loadedModules) => {
|
|
25
|
+
* const { productVariant } = await loadedModules.getTables(commerceModuleTables);
|
|
26
|
+
* return createExecutor({ ... });
|
|
27
|
+
* });
|
|
10
28
|
*
|
|
11
|
-
*
|
|
29
|
+
* // The wrapper file will call it like:
|
|
30
|
+
* // import factory from "module/backend/tailordb";
|
|
31
|
+
* // import modules from "../../modules";
|
|
32
|
+
* // export default await factory(modules);
|
|
33
|
+
* ```
|
|
12
34
|
*/
|
|
13
|
-
export const withModuleConfiguration =
|
|
35
|
+
export const withModuleConfiguration = <
|
|
14
36
|
C extends Record<string, unknown>,
|
|
15
37
|
Tables extends Record<string, unknown>,
|
|
16
38
|
Result
|
|
17
39
|
>(
|
|
18
40
|
module: DefinedModule<C, Tables>,
|
|
19
|
-
factory: (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*/
|
|
29
|
-
const { default: configLoader } = await import(
|
|
30
|
-
"@izumisy-tailor/omakase-modules/config/loader"
|
|
31
|
-
);
|
|
32
|
-
const moduleState = await configLoader.loadConfig(module);
|
|
33
|
-
return await factory(moduleState);
|
|
41
|
+
factory: (
|
|
42
|
+
context: ModuleFactoryContext<C>,
|
|
43
|
+
loadedModules: LoadedModules
|
|
44
|
+
) => Result | Promise<Result>
|
|
45
|
+
): ((loadedModules: LoadedModules) => Promise<Result>) => {
|
|
46
|
+
return async (loadedModules: LoadedModules) => {
|
|
47
|
+
const moduleState = loadedModules.loadConfig<C>(module);
|
|
48
|
+
return await factory(moduleState, loadedModules);
|
|
49
|
+
};
|
|
34
50
|
};
|