@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.
- package/README.md +0 -28
- package/docs/generated/README.md +35 -0
- package/docs/generated/_media/creating-modules.md +471 -0
- package/docs/{tutorials → generated/_media}/using-modules.md +69 -20
- package/docs/generated/builder/README.md +25 -0
- package/docs/generated/builder/functions/defineModule.md +60 -0
- package/docs/generated/builder/functions/withModuleConfiguration.md +68 -0
- package/docs/generated/builder/type-aliases/AnyDefinedModule.md +57 -0
- package/docs/generated/builder/type-aliases/ConfiguredDependencies.md +44 -0
- package/docs/generated/builder/type-aliases/ConfiguredModule.md +60 -0
- package/docs/generated/builder/type-aliases/DefinedModule.md +93 -0
- package/docs/generated/builder/type-aliases/DependencyModules.md +29 -0
- package/docs/generated/builder/type-aliases/EmptyDependencies.md +34 -0
- package/docs/generated/builder/type-aliases/ModuleBuilder.md +124 -0
- package/docs/generated/builder/type-aliases/ModuleBuilderProps.md +42 -0
- package/docs/generated/builder/type-aliases/ModuleFactoryContext.md +40 -0
- package/docs/generated/builder/type-aliases/TablesFromNames.md +28 -0
- package/docs/generated/config/README.md +19 -0
- package/docs/generated/config/classes/ModuleLoader.md +128 -0
- package/docs/generated/config/functions/loadModules.md +79 -0
- package/docs/generated/config/sdk/README.md +16 -0
- package/docs/generated/config/sdk/functions/getModulesReference.md +81 -0
- package/docs/generated/config/sdk/functions/loadModuleForDev.md +53 -0
- package/docs/generated/config/sdk/type-aliases/GetModulesReferenceOptions.md +60 -0
- package/docs/generated/config/type-aliases/LoadedModules.md +162 -0
- package/docs/generated/modules.md +11 -0
- package/package.json +17 -18
- package/src/builder/helpers.ts +388 -28
- package/src/builder/index.ts +8 -1
- package/src/builder/register.ts +38 -25
- package/src/config/module-loader.ts +251 -21
- package/src/config/sdk/dev-context.ts +82 -0
- package/src/config/sdk/index.ts +2 -1
- package/src/config/sdk/paths.ts +124 -13
- package/src/config/sdk/wrapper/base.ts +185 -0
- package/src/config/sdk/wrapper/generator.ts +89 -0
- package/src/config/sdk/wrapper/strategies.ts +121 -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/docs/tutorials/creating-modules.md +0 -256
- package/src/config/module-registry.ts +0 -22
- package/src/stub-loader/index.ts +0 -3
- package/src/stub-loader/interface.ts +0 -40
|
@@ -1,21 +1,93 @@
|
|
|
1
|
-
import { ConfiguredModule } from "../builder/helpers";
|
|
2
|
-
import {
|
|
3
|
-
clearModuleRegistry,
|
|
4
|
-
getConfiguredModule,
|
|
5
|
-
registerConfiguredModules,
|
|
6
|
-
} from "./module-registry";
|
|
1
|
+
import type { ConfiguredModule } from "../builder/helpers";
|
|
7
2
|
|
|
8
3
|
/**
|
|
9
|
-
* Module loader
|
|
10
|
-
*
|
|
4
|
+
* Module loader for registering and configuring modules.
|
|
5
|
+
*
|
|
6
|
+
* The `ModuleLoader` is used within the {@link loadModules} function to register
|
|
7
|
+
* configured modules. Modules can depend on each other, and the loader ensures
|
|
8
|
+
* proper dependency management.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { loadModules } from "@izumisy-tailor/omakase-modules";
|
|
13
|
+
* import commerceModule from "omakase-module-commerce-core";
|
|
14
|
+
* import orderModule from "omakase-module-order";
|
|
15
|
+
* import inventoryModule from "omakase-module-inventory";
|
|
16
|
+
*
|
|
17
|
+
* export default loadModules((loader) => {
|
|
18
|
+
* // Add a module without dependencies
|
|
19
|
+
* const $commerce = loader.add(
|
|
20
|
+
* commerceModule.configure({
|
|
21
|
+
* config: {
|
|
22
|
+
* dataModel: {
|
|
23
|
+
* product: { docNumberPrefix: "PROD" },
|
|
24
|
+
* },
|
|
25
|
+
* },
|
|
26
|
+
* })
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* // Add a module that depends on commerce
|
|
30
|
+
* const $order = loader.add(
|
|
31
|
+
* orderModule.configure({
|
|
32
|
+
* config: { dataModel: {} },
|
|
33
|
+
* dependencies: { commerce: $commerce },
|
|
34
|
+
* })
|
|
35
|
+
* );
|
|
36
|
+
*
|
|
37
|
+
* // Add a module that depends on both commerce and order
|
|
38
|
+
* loader.add(
|
|
39
|
+
* inventoryModule.configure({
|
|
40
|
+
* config: { dbNamespace: "main-db" },
|
|
41
|
+
* dependencies: { commerce: $commerce, order: $order },
|
|
42
|
+
* })
|
|
43
|
+
* );
|
|
44
|
+
*
|
|
45
|
+
* return loader;
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
11
48
|
*/
|
|
12
49
|
export class ModuleLoader {
|
|
13
50
|
private modules: Array<ConfiguredModule<any>> = [];
|
|
14
51
|
|
|
15
52
|
/**
|
|
16
|
-
* Add a module to the loader
|
|
17
|
-
*
|
|
18
|
-
*
|
|
53
|
+
* Add a configured module to the loader.
|
|
54
|
+
*
|
|
55
|
+
* Returns the added module so it can be used as a dependency for other modules.
|
|
56
|
+
* This enables type-safe dependency wiring between modules.
|
|
57
|
+
*
|
|
58
|
+
* @param module - A configured module created by calling `moduleDefinition.configure()`
|
|
59
|
+
* @returns The same configured module, to be used as a dependency for other modules
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* loadModules((loader) => {
|
|
64
|
+
* // Capture the returned value to use as a dependency
|
|
65
|
+
* const $commerce = loader.add(
|
|
66
|
+
* commerceModule.configure({
|
|
67
|
+
* config: {
|
|
68
|
+
* dataModel: {
|
|
69
|
+
* product: {
|
|
70
|
+
* docNumberPrefix: "PP-PROD",
|
|
71
|
+
* customAttributes: {
|
|
72
|
+
* customStatus: db.enum(["new", "used", "refurbished"]),
|
|
73
|
+
* },
|
|
74
|
+
* },
|
|
75
|
+
* },
|
|
76
|
+
* },
|
|
77
|
+
* })
|
|
78
|
+
* );
|
|
79
|
+
*
|
|
80
|
+
* // Use the captured module as a dependency
|
|
81
|
+
* loader.add(
|
|
82
|
+
* orderModule.configure({
|
|
83
|
+
* config: { dataModel: {} },
|
|
84
|
+
* dependencies: { commerce: $commerce },
|
|
85
|
+
* })
|
|
86
|
+
* );
|
|
87
|
+
*
|
|
88
|
+
* return loader;
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
19
91
|
*/
|
|
20
92
|
add<C extends Record<string, unknown>>(
|
|
21
93
|
module: ConfiguredModule<C>
|
|
@@ -33,29 +105,180 @@ export class ModuleLoader {
|
|
|
33
105
|
}
|
|
34
106
|
}
|
|
35
107
|
|
|
108
|
+
/**
|
|
109
|
+
* The result of loading modules, providing access to module configurations and tables.
|
|
110
|
+
*
|
|
111
|
+
* This type is returned by {@link loadModules} and passed to module factory functions.
|
|
112
|
+
* It provides utilities for:
|
|
113
|
+
* - Accessing configured module instances
|
|
114
|
+
* - Loading module configurations
|
|
115
|
+
* - Retrieving tables from dependency modules
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* // In tailor.config.ts - using getModulesReference with LoadedModules
|
|
120
|
+
* import { getModulesReference } from "@izumisy-tailor/omakase-modules/config/sdk";
|
|
121
|
+
* import modules from "./modules";
|
|
122
|
+
*
|
|
123
|
+
* const moduleReference = await getModulesReference(modules);
|
|
124
|
+
*
|
|
125
|
+
* export default defineConfig({
|
|
126
|
+
* db: {
|
|
127
|
+
* "main-db": {
|
|
128
|
+
* files: ["./src/tailordb/*.ts", ...moduleReference.tailordb],
|
|
129
|
+
* },
|
|
130
|
+
* },
|
|
131
|
+
* // ...
|
|
132
|
+
* });
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
36
135
|
export type LoadedModules = {
|
|
37
136
|
loadedModules: Record<string, ConfiguredModule<any>>;
|
|
137
|
+
/**
|
|
138
|
+
* Load the configuration for a specific module.
|
|
139
|
+
*
|
|
140
|
+
* Use this in module factory functions to access the user-provided configuration.
|
|
141
|
+
* Throws an error if the module has not been registered via `loadModules`.
|
|
142
|
+
*
|
|
143
|
+
* @param module - An object with `packageName` (typically the module definition)
|
|
144
|
+
* @returns An object containing the module's configuration
|
|
145
|
+
* @throws Error if the module has not been configured
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* // In a module's tailordb/index.ts
|
|
150
|
+
* import moduleDef from "../module";
|
|
151
|
+
*
|
|
152
|
+
* export default withModuleConfiguration(moduleDef, (context, loadedModules) => {
|
|
153
|
+
* // Access this module's configuration
|
|
154
|
+
* const { config } = loadedModules.loadConfig<ModuleConfig>(moduleDef);
|
|
155
|
+
* const prefix = config.dataModel?.product?.docNumberPrefix ?? "PROD";
|
|
156
|
+
*
|
|
157
|
+
* return { product: buildProductTable(context) };
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
38
161
|
loadConfig: <C extends Record<string, unknown>>(module: {
|
|
39
162
|
packageName: string;
|
|
40
163
|
}) => {
|
|
41
164
|
config: C;
|
|
42
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Get the tables from a dependency module by calling its factory function.
|
|
168
|
+
*
|
|
169
|
+
* Use this when a module needs to reference tables from another module,
|
|
170
|
+
* such as creating foreign key relationships or using shared types.
|
|
171
|
+
*
|
|
172
|
+
* @param factory - The factory function exported by the dependency module's `tailordb/index.ts`
|
|
173
|
+
* @returns A promise resolving to the tables created by the factory
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* // In inventory-module's tailordb/index.ts
|
|
178
|
+
* import commerceModuleTables from "omakase-module-commerce-core/backend/tailordb";
|
|
179
|
+
* import orderModuleTables from "omakase-module-order/backend/tailordb";
|
|
180
|
+
*
|
|
181
|
+
* export default withModuleConfiguration(
|
|
182
|
+
* moduleDef,
|
|
183
|
+
* async (context, loadedModules) => {
|
|
184
|
+
* // Get tables from commerce module to reference product/productVariant
|
|
185
|
+
* const { product, productVariant } = await loadedModules.getTables(
|
|
186
|
+
* commerceModuleTables
|
|
187
|
+
* );
|
|
188
|
+
*
|
|
189
|
+
* // Get tables from order module to reference order
|
|
190
|
+
* const { order } = await loadedModules.getTables(orderModuleTables);
|
|
191
|
+
*
|
|
192
|
+
* // Use dependency tables when building this module's tables
|
|
193
|
+
* const inventory = buildInventoryTable(context, { product, productVariant });
|
|
194
|
+
* const inventoryTransaction = buildInventoryTransactionTable(context, {
|
|
195
|
+
* inventory,
|
|
196
|
+
* order,
|
|
197
|
+
* });
|
|
198
|
+
*
|
|
199
|
+
* return { inventory, inventoryTransaction };
|
|
200
|
+
* }
|
|
201
|
+
* );
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
getTables: <T>(
|
|
205
|
+
factory: (loadedModules: LoadedModules) => Promise<T>
|
|
206
|
+
) => Promise<T>;
|
|
207
|
+
/**
|
|
208
|
+
* Indicates this is a dev context created by loadModuleForDev.
|
|
209
|
+
* When true, wrapper generation uses local src paths instead of node_modules.
|
|
210
|
+
* @internal
|
|
211
|
+
*/
|
|
212
|
+
__devContext?: {
|
|
213
|
+
/** The package name of the module being developed */
|
|
214
|
+
moduleName: string;
|
|
215
|
+
};
|
|
43
216
|
};
|
|
44
217
|
|
|
45
218
|
/**
|
|
46
|
-
* Load modules
|
|
47
|
-
*
|
|
48
|
-
*
|
|
219
|
+
* Load and configure modules for your Tailor application.
|
|
220
|
+
*
|
|
221
|
+
* This is the main entry point for setting up omakase modules. Use this function
|
|
222
|
+
* to register all modules your application needs, configure them with your settings,
|
|
223
|
+
* and wire up dependencies between modules.
|
|
224
|
+
*
|
|
225
|
+
* @param configurator - A function that receives a {@link ModuleLoader} and returns it after adding modules
|
|
226
|
+
* @returns A {@link LoadedModules} object containing all registered modules and utilities
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```typescript
|
|
230
|
+
* // modules.ts - Define your module configuration
|
|
231
|
+
* import { loadModules } from "@izumisy-tailor/omakase-modules";
|
|
232
|
+
* import { db } from "@tailor-platform/sdk";
|
|
233
|
+
* import commerceModule from "omakase-module-commerce-core";
|
|
234
|
+
* import orderModule from "omakase-module-order";
|
|
235
|
+
* import inventoryModule from "omakase-module-inventory";
|
|
236
|
+
*
|
|
237
|
+
* export default loadModules((loader) => {
|
|
238
|
+
* // Configure and add the commerce module
|
|
239
|
+
* const $commerce = loader.add(
|
|
240
|
+
* commerceModule.configure({
|
|
241
|
+
* config: {
|
|
242
|
+
* dataModel: {
|
|
243
|
+
* product: {
|
|
244
|
+
* docNumberPrefix: "PP-PROD",
|
|
245
|
+
* customAttributes: {
|
|
246
|
+
* customStatus: db.enum(["new", "used", "refurbished"]),
|
|
247
|
+
* },
|
|
248
|
+
* },
|
|
249
|
+
* },
|
|
250
|
+
* },
|
|
251
|
+
* })
|
|
252
|
+
* );
|
|
253
|
+
*
|
|
254
|
+
* // Configure order module with commerce as a dependency
|
|
255
|
+
* const $order = loader.add(
|
|
256
|
+
* orderModule.configure({
|
|
257
|
+
* config: { dataModel: {} },
|
|
258
|
+
* dependencies: { commerce: $commerce },
|
|
259
|
+
* })
|
|
260
|
+
* );
|
|
261
|
+
*
|
|
262
|
+
* // Configure inventory module with both dependencies
|
|
263
|
+
* loader.add(
|
|
264
|
+
* inventoryModule.configure({
|
|
265
|
+
* config: {
|
|
266
|
+
* dbNamespace: "main-db",
|
|
267
|
+
* invantoryBootstrapBaseValue: 300,
|
|
268
|
+
* },
|
|
269
|
+
* dependencies: { commerce: $commerce, order: $order },
|
|
270
|
+
* })
|
|
271
|
+
* );
|
|
272
|
+
*
|
|
273
|
+
* return loader;
|
|
274
|
+
* });
|
|
275
|
+
* ```
|
|
49
276
|
*/
|
|
50
277
|
export const loadModules = (
|
|
51
278
|
configurator: (loader: ModuleLoader) => ModuleLoader
|
|
52
279
|
): LoadedModules => {
|
|
53
|
-
clearModuleRegistry();
|
|
54
|
-
|
|
55
280
|
const emptyLoader = new ModuleLoader();
|
|
56
|
-
const modules =
|
|
57
|
-
configurator(emptyLoader)._getModules()
|
|
58
|
-
);
|
|
281
|
+
const modules = configurator(emptyLoader)._getModules();
|
|
59
282
|
|
|
60
283
|
const loadedModules = modules.reduce<Record<string, ConfiguredModule<any>>>(
|
|
61
284
|
(acc, module) => {
|
|
@@ -65,12 +288,12 @@ export const loadModules = (
|
|
|
65
288
|
{}
|
|
66
289
|
);
|
|
67
290
|
|
|
68
|
-
|
|
291
|
+
const loadedModulesResult: LoadedModules = {
|
|
69
292
|
loadedModules,
|
|
70
293
|
loadConfig: <C extends Record<string, unknown>>(module: {
|
|
71
294
|
packageName: string;
|
|
72
295
|
}) => {
|
|
73
|
-
const loadedModule =
|
|
296
|
+
const loadedModule = loadedModules[module.packageName];
|
|
74
297
|
if (!loadedModule) {
|
|
75
298
|
throw new Error(
|
|
76
299
|
`Module "${module.packageName}" has not been configured. Ensure it is added via loadModules.`
|
|
@@ -81,5 +304,12 @@ export const loadModules = (
|
|
|
81
304
|
config: loadedModule.moduleProps.config as C,
|
|
82
305
|
};
|
|
83
306
|
},
|
|
307
|
+
getTables: async <T>(
|
|
308
|
+
factory: (loadedModules: LoadedModules) => Promise<T>
|
|
309
|
+
): Promise<T> => {
|
|
310
|
+
return factory(loadedModulesResult);
|
|
311
|
+
},
|
|
84
312
|
};
|
|
313
|
+
|
|
314
|
+
return loadedModulesResult;
|
|
85
315
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { loadModules, type LoadedModules } from "../module-loader";
|
|
2
|
+
import type { DefinedModule, DependencyModules } from "../../builder/helpers";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a LoadedModules context for individual module development.
|
|
6
|
+
*
|
|
7
|
+
* This allows using `getModulesReference` in a module's own `tailor.config.ts`,
|
|
8
|
+
* enabling the kysely-type generator to work during module development.
|
|
9
|
+
*
|
|
10
|
+
* Dependencies declared in the module's `defineModule` are automatically
|
|
11
|
+
* registered with default (empty) configurations.
|
|
12
|
+
*
|
|
13
|
+
* @param module The module being developed
|
|
14
|
+
* @param config Optional development configuration. If omitted, uses module.devConfig.
|
|
15
|
+
* @returns A LoadedModules object that can be passed to getModulesReference
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // tailor.config.ts
|
|
20
|
+
* import { loadModuleForDev, getModulesReference } from "@izumisy-tailor/omakase-modules/config/sdk";
|
|
21
|
+
* import inventoryModule from "./src/module";
|
|
22
|
+
*
|
|
23
|
+
* const modules = loadModuleForDev(inventoryModule);
|
|
24
|
+
* const moduleReference = await getModulesReference(modules);
|
|
25
|
+
*
|
|
26
|
+
* export default defineConfig({ ... });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const loadModuleForDev = <
|
|
30
|
+
C extends Record<string, unknown>,
|
|
31
|
+
Tables extends Record<string, unknown>,
|
|
32
|
+
Deps extends DependencyModules
|
|
33
|
+
>(
|
|
34
|
+
module: DefinedModule<C, Tables, Deps>,
|
|
35
|
+
config?: C
|
|
36
|
+
): LoadedModules => {
|
|
37
|
+
// Use provided config, fall back to module's devConfig, or use empty object as default
|
|
38
|
+
const resolvedConfig = config ?? module.devConfig ?? ({} as C);
|
|
39
|
+
|
|
40
|
+
const modules = loadModules((loader) => {
|
|
41
|
+
// Recursively register all dependency modules with default config
|
|
42
|
+
const registerDependencies = (deps: DependencyModules) => {
|
|
43
|
+
for (const dep of Object.values(deps)) {
|
|
44
|
+
if (!dep) continue; // Skip empty dependency marker
|
|
45
|
+
// First register transitive dependencies
|
|
46
|
+
if (dep.dependencies && Object.keys(dep.dependencies).length > 0) {
|
|
47
|
+
registerDependencies(dep.dependencies);
|
|
48
|
+
}
|
|
49
|
+
// Then register this dependency with empty config
|
|
50
|
+
// For dev context, we use type assertion since dependencies are auto-resolved
|
|
51
|
+
loader.add(
|
|
52
|
+
(
|
|
53
|
+
dep.configure as (props: { config: Record<string, unknown> }) => any
|
|
54
|
+
)({ config: {} })
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Register all dependencies first
|
|
60
|
+
if (module.dependencies && Object.keys(module.dependencies).length > 0) {
|
|
61
|
+
registerDependencies(module.dependencies);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Register the main module being developed
|
|
65
|
+
// For dev context, we don't need to pass dependencies
|
|
66
|
+
loader.add(
|
|
67
|
+
(module.configure as (props: { config: C }) => any)({
|
|
68
|
+
config: resolvedConfig,
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return loader;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Mark this as a dev context with the module name being developed
|
|
76
|
+
return {
|
|
77
|
+
...modules,
|
|
78
|
+
__devContext: {
|
|
79
|
+
moduleName: module.packageName,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
};
|
package/src/config/sdk/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { getModulesReference } from "./paths";
|
|
1
|
+
export { getModulesReference, type GetModulesReferenceOptions } from "./paths";
|
|
2
|
+
export { loadModuleForDev } from "./dev-context";
|
package/src/config/sdk/paths.ts
CHANGED
|
@@ -1,20 +1,131 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { LoadedModules } from "../module-loader";
|
|
2
|
+
import type { LoadedModules } from "../module-loader";
|
|
3
|
+
import { generateWrapperFiles, OMAKASE_WRAPPER_DIR } from "./wrapper/generator";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Options for configuring {@link getModulesReference} behavior.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const moduleReference = await getModulesReference(modules, {
|
|
11
|
+
* basePath: "/custom/path",
|
|
12
|
+
* silent: true, // Suppress console output
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export type GetModulesReferenceOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* Base path for the application.
|
|
19
|
+
*
|
|
20
|
+
* This determines where wrapper files are generated and where module
|
|
21
|
+
* paths are resolved from. Defaults to `process.cwd()`.
|
|
22
|
+
*
|
|
23
|
+
* @default process.cwd()
|
|
24
|
+
*/
|
|
25
|
+
basePath?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to suppress log output.
|
|
28
|
+
*
|
|
29
|
+
* When `true`, no console output will be printed during module loading.
|
|
30
|
+
* Useful for testing or when you want cleaner build output.
|
|
31
|
+
*
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
silent?: boolean;
|
|
35
|
+
};
|
|
6
36
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Get file path patterns for modules to use in Tailor configuration.
|
|
39
|
+
*
|
|
40
|
+
* This function processes your loaded modules and returns glob patterns
|
|
41
|
+
* that can be spread into your `defineConfig`. It handles all the necessary
|
|
42
|
+
* setup to make module TailorDB types, resolvers, and executors available
|
|
43
|
+
* to Tailor's configuration system.
|
|
44
|
+
*
|
|
45
|
+
* @param loadedModules - The result of calling `loadModules()`
|
|
46
|
+
* @param options - Optional configuration for path resolution and logging
|
|
47
|
+
* @returns An object containing glob patterns for `tailordb`, `resolver`, and `executor` files
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // tailor.config.ts
|
|
52
|
+
* import { defineConfig, defineGenerators } from "@tailor-platform/sdk";
|
|
53
|
+
* import { getModulesReference } from "@izumisy-tailor/omakase-modules/config/sdk";
|
|
54
|
+
* import modules from "./modules";
|
|
55
|
+
*
|
|
56
|
+
* // Get module path patterns
|
|
57
|
+
* const moduleReference = await getModulesReference(modules);
|
|
58
|
+
*
|
|
59
|
+
* export default defineConfig({
|
|
60
|
+
* name: "my-app",
|
|
61
|
+
*
|
|
62
|
+
* // Spread module paths alongside your local files
|
|
63
|
+
* db: {
|
|
64
|
+
* "main-db": {
|
|
65
|
+
* files: ["./src/tailordb/*.ts", ...moduleReference.tailordb],
|
|
66
|
+
* },
|
|
67
|
+
* },
|
|
68
|
+
*
|
|
69
|
+
* resolver: {
|
|
70
|
+
* "main-pipeline": {
|
|
71
|
+
* files: ["./src/resolvers/*.ts", ...moduleReference.resolver],
|
|
72
|
+
* },
|
|
73
|
+
* },
|
|
74
|
+
*
|
|
75
|
+
* executor: {
|
|
76
|
+
* files: ["./src/executors/*.ts", ...moduleReference.executor],
|
|
77
|
+
* },
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // With custom options
|
|
84
|
+
* const moduleReference = await getModulesReference(modules, {
|
|
85
|
+
* basePath: import.meta.dirname, // Use ESM module directory
|
|
86
|
+
* silent: true, // No console output
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* The returned object contains three arrays:
|
|
92
|
+
* - `tailordb` - Paths to TailorDB type definitions from modules
|
|
93
|
+
* - `resolver` - Paths to GraphQL resolver definitions from modules
|
|
94
|
+
* - `executor` - Paths to event executor definitions from modules
|
|
95
|
+
*
|
|
96
|
+
* If a module has no files of a certain type, that array will be empty.
|
|
97
|
+
*/
|
|
98
|
+
export const getModulesReference = async (
|
|
99
|
+
loadedModules: LoadedModules,
|
|
100
|
+
options: GetModulesReferenceOptions = {}
|
|
101
|
+
) => {
|
|
102
|
+
const { basePath = process.cwd(), silent = false } = options;
|
|
11
103
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
104
|
+
// Log loaded modules information
|
|
105
|
+
const modulePackageNames = Object.keys(loadedModules.loadedModules);
|
|
106
|
+
if (!silent) {
|
|
107
|
+
console.log(`[omakase] Loaded ${modulePackageNames.length} module(s):\n`);
|
|
108
|
+
for (const name of modulePackageNames) {
|
|
109
|
+
console.log(` * ${name}`);
|
|
110
|
+
}
|
|
111
|
+
console.log("");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Generate wrapper files and return paths to them
|
|
115
|
+
const wrapperPaths = await generateWrapperFiles(loadedModules, basePath);
|
|
15
116
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
117
|
+
return {
|
|
118
|
+
tailordb:
|
|
119
|
+
wrapperPaths.tailordb.length > 0
|
|
120
|
+
? [path.join(OMAKASE_WRAPPER_DIR, "*", "tailordb", "*.ts")]
|
|
121
|
+
: [],
|
|
122
|
+
resolver:
|
|
123
|
+
wrapperPaths.resolver.length > 0
|
|
124
|
+
? [path.join(OMAKASE_WRAPPER_DIR, "*", "resolvers", "*.ts")]
|
|
125
|
+
: [],
|
|
126
|
+
executor:
|
|
127
|
+
wrapperPaths.executor.length > 0
|
|
128
|
+
? [path.join(OMAKASE_WRAPPER_DIR, "*", "executors", "*.ts")]
|
|
129
|
+
: [],
|
|
19
130
|
};
|
|
20
131
|
};
|