@izumisy-tailor/omakase-modules 0.2.0 → 0.4.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.
Files changed (47) hide show
  1. package/README.md +0 -28
  2. package/docs/generated/README.md +35 -0
  3. package/docs/generated/_media/creating-modules.md +471 -0
  4. package/docs/{tutorials → generated/_media}/using-modules.md +69 -20
  5. package/docs/generated/builder/README.md +25 -0
  6. package/docs/generated/builder/functions/defineModule.md +60 -0
  7. package/docs/generated/builder/functions/withModuleConfiguration.md +68 -0
  8. package/docs/generated/builder/type-aliases/AnyDefinedModule.md +57 -0
  9. package/docs/generated/builder/type-aliases/ConfiguredDependencies.md +44 -0
  10. package/docs/generated/builder/type-aliases/ConfiguredModule.md +60 -0
  11. package/docs/generated/builder/type-aliases/DefinedModule.md +93 -0
  12. package/docs/generated/builder/type-aliases/DependencyModules.md +29 -0
  13. package/docs/generated/builder/type-aliases/EmptyDependencies.md +34 -0
  14. package/docs/generated/builder/type-aliases/ModuleBuilder.md +124 -0
  15. package/docs/generated/builder/type-aliases/ModuleBuilderProps.md +42 -0
  16. package/docs/generated/builder/type-aliases/ModuleFactoryContext.md +40 -0
  17. package/docs/generated/builder/type-aliases/TablesFromNames.md +28 -0
  18. package/docs/generated/config/README.md +19 -0
  19. package/docs/generated/config/classes/ModuleLoader.md +128 -0
  20. package/docs/generated/config/functions/loadModules.md +79 -0
  21. package/docs/generated/config/sdk/README.md +16 -0
  22. package/docs/generated/config/sdk/functions/getModulesReference.md +81 -0
  23. package/docs/generated/config/sdk/functions/loadModuleForDev.md +53 -0
  24. package/docs/generated/config/sdk/type-aliases/GetModulesReferenceOptions.md +60 -0
  25. package/docs/generated/config/type-aliases/LoadedModules.md +162 -0
  26. package/docs/generated/modules.md +11 -0
  27. package/package.json +17 -18
  28. package/src/builder/helpers.ts +388 -28
  29. package/src/builder/index.ts +8 -1
  30. package/src/builder/register.ts +38 -25
  31. package/src/config/module-loader.ts +251 -21
  32. package/src/config/sdk/dev-context.ts +82 -0
  33. package/src/config/sdk/index.ts +2 -1
  34. package/src/config/sdk/paths.ts +124 -13
  35. package/src/config/sdk/wrapper/base.ts +185 -0
  36. package/src/config/sdk/wrapper/generator.ts +89 -0
  37. package/src/config/sdk/wrapper/strategies.ts +121 -0
  38. package/docs/examples/data-models/core/inventory-module.md +0 -230
  39. package/docs/examples/data-models/core/order-module.md +0 -132
  40. package/docs/examples/data-models/scenarios/inventory-reservation-scenario.md +0 -73
  41. package/docs/examples/data-models/scenarios/multi-storefront-order-scenario.md +0 -99
  42. package/docs/examples/data-models/scenarios/order-payment-status-scenario.md +0 -92
  43. package/docs/examples/data-models/scenarios/procurement-order-scenario.md +0 -95
  44. package/docs/tutorials/creating-modules.md +0 -256
  45. package/src/config/module-registry.ts +0 -22
  46. package/src/stub-loader/index.ts +0 -3
  47. package/src/stub-loader/interface.ts +0 -40
@@ -1,256 +0,0 @@
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
@@ -1,22 +0,0 @@
1
- import type { ConfiguredModule } from "../builder/helpers";
2
-
3
- const registry = new Map<string, ConfiguredModule<any>>();
4
-
5
- export const clearModuleRegistry = () => {
6
- registry.clear();
7
- };
8
-
9
- export const registerConfiguredModules = (
10
- modules: ReadonlyArray<ConfiguredModule<any>>
11
- ) => {
12
- modules.forEach((module) => {
13
- registry.set(module.packageName, module);
14
- });
15
- return modules;
16
- };
17
-
18
- export const getConfiguredModule = <C extends Record<string, unknown>>(
19
- packageName: string
20
- ): ConfiguredModule<C> | undefined => {
21
- return registry.get(packageName) as ConfiguredModule<C> | undefined;
22
- };
@@ -1,3 +0,0 @@
1
- import { moduleConfigLoader } from "./interface";
2
-
3
- export default moduleConfigLoader;
@@ -1,40 +0,0 @@
1
- import { DefinedModule } from "../builder";
2
-
3
- export type ModuleConfigLoaderReturn<C extends Record<string, unknown>> =
4
- Promise<{
5
- config: C;
6
- }>;
7
-
8
- const loadConfig = async <C extends Record<string, unknown>>(
9
- _: DefinedModule<C, any>
10
- ): ModuleConfigLoaderReturn<C> => {
11
- console.warn(
12
- `[warn] Empty module configuration loaded. Override "@izumisy-tailor/omakase-modules/config/loader" to "./modules.ts" in tsconfig.json paths in your app`
13
- );
14
-
15
- return {
16
- config: {} as C,
17
- };
18
- };
19
-
20
- /**
21
- * `moduleConfigLoader` is an interface for loading module configurations.
22
- *
23
- * By default, it throws an error indicating that the loader needs to be overridden in tsconfig.json.
24
- * Users should provide their "modules.ts" that calls `loadModules` which implements the actual loading logic.
25
- *
26
- * @example
27
- * ```
28
- * {
29
- * "compilerOptions": {
30
- * // ...
31
- * "paths": {
32
- * "@izumisy-tailor/omakase-modules/config/loader": ["./modules.ts"],
33
- * }
34
- * }
35
- * }
36
- * ```
37
- */
38
- export const moduleConfigLoader = {
39
- loadConfig,
40
- };