@izumisy-tailor/omakase-modules 0.3.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 -16
- package/docs/generated/README.md +35 -0
- package/docs/{tutorials → generated/_media}/creating-modules.md +192 -17
- package/docs/{tutorials → generated/_media}/using-modules.md +17 -18
- 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 +8 -4
- package/src/builder/helpers.ts +347 -27
- package/src/builder/index.ts +6 -1
- package/src/builder/register.ts +3 -6
- package/src/config/module-loader.ts +234 -12
- package/src/config/sdk/dev-context.ts +82 -0
- package/src/config/sdk/index.ts +2 -1
- package/src/config/sdk/paths.ts +85 -3
- package/src/config/sdk/wrapper/base.ts +58 -14
- package/src/config/sdk/wrapper/generator.ts +40 -3
- package/src/config/sdk/wrapper/strategies.ts +32 -13
package/src/builder/helpers.ts
CHANGED
|
@@ -1,56 +1,376 @@
|
|
|
1
1
|
import type { TailorDBType } from "@tailor-platform/sdk";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Represents a module with no dependencies.
|
|
5
|
+
*
|
|
6
|
+
* This is a branded type used internally to distinguish modules
|
|
7
|
+
* that have no dependencies from those that do. When defining a module
|
|
8
|
+
* without dependencies, you don't need to use this type directly.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Modules without dependencies don't need to specify this type
|
|
13
|
+
* export default defineModule<MyConfig, MyTables>({
|
|
14
|
+
* packageName: "my-module",
|
|
15
|
+
* }).build();
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export type EmptyDependencies = { readonly __empty?: never };
|
|
6
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Properties required when configuring a module via `configure()`.
|
|
22
|
+
*
|
|
23
|
+
* The shape of this type varies based on whether the module has dependencies:
|
|
24
|
+
* - **Without dependencies**: `{ config: C }`
|
|
25
|
+
* - **With dependencies**: `{ config: C; dependencies: ConfiguredDependencies<Deps> }`
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Module without dependencies
|
|
30
|
+
* myModule.configure({
|
|
31
|
+
* config: { dbNamespace: "main-db" },
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Module with dependencies
|
|
35
|
+
* inventoryModule.configure({
|
|
36
|
+
* config: { dbNamespace: "main-db" },
|
|
37
|
+
* dependencies: {
|
|
38
|
+
* commerce: $commerceModule,
|
|
39
|
+
* order: $orderModule,
|
|
40
|
+
* },
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export type ModuleBuilderProps<
|
|
45
|
+
/**
|
|
46
|
+
* The configuration type for the module
|
|
47
|
+
*/
|
|
48
|
+
C extends Record<string, unknown>,
|
|
49
|
+
/**
|
|
50
|
+
* The dependency modules record type
|
|
51
|
+
*/
|
|
52
|
+
Deps extends DependencyModules
|
|
53
|
+
> = Deps extends EmptyDependencies
|
|
54
|
+
? { config: C }
|
|
55
|
+
: { config: C; dependencies: ConfiguredDependencies<Deps> };
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A module that has been configured with specific settings.
|
|
59
|
+
*
|
|
60
|
+
* This type represents the result of calling `configure()` on a {@link DefinedModule}.
|
|
61
|
+
* Configured modules can be passed as dependencies to other modules or used
|
|
62
|
+
* directly in your application's Tailor configuration.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Create a configured module
|
|
67
|
+
* const $commerceModule = commerceModule.configure({
|
|
68
|
+
* config: { dbNamespace: "main-db" },
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Use as a dependency in another module
|
|
72
|
+
* const $inventoryModule = inventoryModule.configure({
|
|
73
|
+
* config: { dbNamespace: "main-db" },
|
|
74
|
+
* dependencies: {
|
|
75
|
+
* commerce: $commerceModule,
|
|
76
|
+
* },
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
7
80
|
export type ConfiguredModule<
|
|
81
|
+
/**
|
|
82
|
+
* The configuration type that was used to configure the module
|
|
83
|
+
*/
|
|
8
84
|
C extends Record<string, unknown> = Record<string, unknown>
|
|
9
85
|
> = {
|
|
10
86
|
packageName: string;
|
|
11
|
-
moduleProps:
|
|
87
|
+
moduleProps: { config: C };
|
|
88
|
+
/**
|
|
89
|
+
* @internal Brand for config type identification in dependency checking.
|
|
90
|
+
*/
|
|
91
|
+
readonly __configBrand?: C;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A record of module dependencies or an empty dependency set.
|
|
96
|
+
*
|
|
97
|
+
* This type represents the dependencies that a module can declare.
|
|
98
|
+
* It is either a record mapping dependency names to {@link AnyDefinedModule},
|
|
99
|
+
* or {@link EmptyDependencies} for modules without dependencies.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // Used internally when defining module dependencies
|
|
104
|
+
* defineModule<MyConfig, MyTables>({
|
|
105
|
+
* packageName: "my-module",
|
|
106
|
+
* }).withDependencies({
|
|
107
|
+
* commerce: commerceModule, // Record<string, AnyDefinedModule>
|
|
108
|
+
* order: orderModule,
|
|
109
|
+
* }).build();
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export type DependencyModules =
|
|
113
|
+
| Record<string, AnyDefinedModule>
|
|
114
|
+
| EmptyDependencies;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* A loosely-typed representation of any defined module.
|
|
118
|
+
*
|
|
119
|
+
* This type is used in dependency records where the exact type parameters
|
|
120
|
+
* of the module are not important. It provides the minimal interface needed
|
|
121
|
+
* to work with modules as dependencies.
|
|
122
|
+
*
|
|
123
|
+
* For strongly-typed module definitions, use {@link DefinedModule} instead.
|
|
124
|
+
*
|
|
125
|
+
* @see {@link DefinedModule} for the fully-typed module definition.
|
|
126
|
+
*/
|
|
127
|
+
export type AnyDefinedModule = {
|
|
128
|
+
packageName: string;
|
|
129
|
+
dependencies: Record<string, any>;
|
|
130
|
+
configure: (props: any) => ConfiguredModule<any>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @internal Brand for tables type identification in helper utilities.
|
|
134
|
+
*/
|
|
135
|
+
readonly __tablesBrand?: any;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @internal Brand for config type identification in dependency checking.
|
|
139
|
+
*/
|
|
140
|
+
readonly __configBrand?: any;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Transforms a record of {@link DefinedModule}s into a record of {@link ConfiguredModule}s.
|
|
145
|
+
*
|
|
146
|
+
* This utility type is used to derive the expected shape of the `dependencies`
|
|
147
|
+
* property when configuring a module that has dependencies. It preserves
|
|
148
|
+
* the exact configuration type for each dependency module.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* // When a module is defined with dependencies:
|
|
153
|
+
* defineModule<MyConfig, MyTables>({
|
|
154
|
+
* packageName: "my-module",
|
|
155
|
+
* }).withDependencies({
|
|
156
|
+
* commerce: commerceModule,
|
|
157
|
+
* order: orderModule,
|
|
158
|
+
* }).build();
|
|
159
|
+
*
|
|
160
|
+
* // The configure() method will expect:
|
|
161
|
+
* myModule.configure({
|
|
162
|
+
* config: { ... },
|
|
163
|
+
* dependencies: {
|
|
164
|
+
* commerce: ConfiguredModule<CommerceConfig>,
|
|
165
|
+
* order: ConfiguredModule<OrderConfig>,
|
|
166
|
+
* },
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export type ConfiguredDependencies<
|
|
171
|
+
/**
|
|
172
|
+
* The dependency modules record to transform
|
|
173
|
+
*/
|
|
174
|
+
Deps extends DependencyModules
|
|
175
|
+
> = {
|
|
176
|
+
[K in keyof Deps as K extends "__empty" ? never : K]: Deps[K] extends {
|
|
177
|
+
readonly __configBrand?: infer C;
|
|
178
|
+
}
|
|
179
|
+
? C extends Record<string, unknown>
|
|
180
|
+
? ConfiguredModule<C>
|
|
181
|
+
: never
|
|
182
|
+
: never;
|
|
12
183
|
};
|
|
13
184
|
|
|
185
|
+
/**
|
|
186
|
+
* A fully defined, reusable module that can be configured and composed.
|
|
187
|
+
*
|
|
188
|
+
* This is the primary type for modules created with {@link defineModule}.
|
|
189
|
+
* A `DefinedModule` encapsulates:
|
|
190
|
+
* - The module's package name for identification
|
|
191
|
+
* - Its dependencies on other modules
|
|
192
|
+
* - A `configure()` method to create a {@link ConfiguredModule}
|
|
193
|
+
* - Optional development configuration for local testing
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* // Define a module
|
|
198
|
+
* const inventoryModule = defineModule<InventoryConfig, InventoryTables>({
|
|
199
|
+
* packageName: "inventory-module",
|
|
200
|
+
* })
|
|
201
|
+
* .withDependencies({ commerce: commerceModule })
|
|
202
|
+
* .withDevConfig({ dbNamespace: "dev" })
|
|
203
|
+
* .build();
|
|
204
|
+
*
|
|
205
|
+
* // Configure the module for use
|
|
206
|
+
* const $inventory = inventoryModule.configure({
|
|
207
|
+
* config: { dbNamespace: "production" },
|
|
208
|
+
* dependencies: {
|
|
209
|
+
* commerce: $commerceModule,
|
|
210
|
+
* },
|
|
211
|
+
* });
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
14
214
|
export type DefinedModule<
|
|
215
|
+
/**
|
|
216
|
+
* The configuration schema for the module
|
|
217
|
+
*/
|
|
15
218
|
C extends Record<string, unknown>,
|
|
16
|
-
|
|
219
|
+
/**
|
|
220
|
+
* The TailorDB table definitions exported by the module
|
|
221
|
+
*/
|
|
222
|
+
Tables extends Record<string, unknown> = Record<string, unknown>,
|
|
223
|
+
/**
|
|
224
|
+
* The dependency modules this module requires
|
|
225
|
+
*/
|
|
226
|
+
Deps extends DependencyModules = EmptyDependencies
|
|
17
227
|
> = {
|
|
18
228
|
packageName: string;
|
|
19
|
-
|
|
229
|
+
dependencies: Deps;
|
|
230
|
+
configure: (props: ModuleBuilderProps<C, Deps>) => ConfiguredModule<C>;
|
|
231
|
+
/**
|
|
232
|
+
* Default configuration for module development.
|
|
233
|
+
* Used by loadModuleForDev when no config is provided.
|
|
234
|
+
*/
|
|
235
|
+
devConfig?: C;
|
|
20
236
|
/**
|
|
21
237
|
* @internal Type-only hook so that table shapes flow through helper utilities.
|
|
22
238
|
*/
|
|
23
239
|
readonly __tablesBrand?: Tables;
|
|
240
|
+
/**
|
|
241
|
+
* @internal Brand for config type identification in dependency checking.
|
|
242
|
+
*/
|
|
243
|
+
readonly __configBrand?: C;
|
|
24
244
|
};
|
|
25
245
|
|
|
26
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Intermediate builder type returned by defineModule.
|
|
248
|
+
* Use .withDependencies() to add dependencies, then call .build() to finalize.
|
|
249
|
+
* Modules without dependencies can call .build() directly.
|
|
250
|
+
*/
|
|
251
|
+
export type ModuleBuilder<
|
|
27
252
|
C extends Record<string, unknown>,
|
|
28
|
-
Tables extends Record<string, unknown
|
|
29
|
-
|
|
253
|
+
Tables extends Record<string, unknown>,
|
|
254
|
+
Deps extends DependencyModules = EmptyDependencies
|
|
255
|
+
> = {
|
|
30
256
|
/**
|
|
31
|
-
*
|
|
257
|
+
* Adds dependencies to the module definition.
|
|
258
|
+
* The Deps type is automatically inferred from the record.
|
|
32
259
|
*
|
|
33
|
-
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* export default defineModule<ModuleConfig, Tables>({
|
|
263
|
+
* packageName: "my-module",
|
|
264
|
+
* }).withDependencies({
|
|
265
|
+
* commerce: commerceModule,
|
|
266
|
+
* order: orderModule,
|
|
267
|
+
* }).build();
|
|
268
|
+
* ```
|
|
34
269
|
*/
|
|
270
|
+
withDependencies: <const NewDeps extends DependencyModules>(
|
|
271
|
+
deps: NewDeps
|
|
272
|
+
) => ModuleBuilder<C, Tables, NewDeps>;
|
|
273
|
+
/**
|
|
274
|
+
* Sets the default configuration for module development.
|
|
275
|
+
* This config is used by loadModuleForDev when no config is provided.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```typescript
|
|
279
|
+
* export default defineModule<ModuleConfig, Tables>({
|
|
280
|
+
* packageName: "my-module",
|
|
281
|
+
* }).withDevConfig({
|
|
282
|
+
* dbNamespace: "main-db",
|
|
283
|
+
* }).build();
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
withDevConfig: (config: C) => ModuleBuilder<C, Tables, Deps>;
|
|
287
|
+
/**
|
|
288
|
+
* Finalizes the module definition and returns the DefinedModule.
|
|
289
|
+
* This must be called at the end of the builder chain to get the actual module.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* // Without dependencies
|
|
294
|
+
* export default defineModule<ModuleConfig, Tables>({
|
|
295
|
+
* packageName: "my-module",
|
|
296
|
+
* }).build();
|
|
297
|
+
*
|
|
298
|
+
* // With dependencies and dev config
|
|
299
|
+
* export default defineModule<ModuleConfig, Tables>({
|
|
300
|
+
* packageName: "my-module",
|
|
301
|
+
* })
|
|
302
|
+
* .withDependencies({ commerce: commerceModule })
|
|
303
|
+
* .withDevConfig({ dbNamespace: "dev" })
|
|
304
|
+
* .build();
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
build: () => DefinedModule<C, Tables, Deps>;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Defines a reusable module with optional dependencies on other modules.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* // Module without dependencies
|
|
316
|
+
* export default defineModule<ModuleConfig, Tables>({
|
|
317
|
+
* packageName: "my-module",
|
|
318
|
+
* }).build();
|
|
319
|
+
*
|
|
320
|
+
* // Module with dependencies - Deps type is automatically inferred
|
|
321
|
+
* import commerceModule from "omakase-module-commerce-core";
|
|
322
|
+
* import orderModule from "omakase-module-order";
|
|
323
|
+
*
|
|
324
|
+
* export default defineModule<ModuleConfig, Tables>({
|
|
325
|
+
* packageName: "my-module",
|
|
326
|
+
* }).withDependencies({
|
|
327
|
+
* commerce: commerceModule,
|
|
328
|
+
* order: orderModule,
|
|
329
|
+
* }).build();
|
|
330
|
+
*
|
|
331
|
+
* // When configuring a module with dependencies, pass them as a record:
|
|
332
|
+
* inventoryModule.configure({
|
|
333
|
+
* config: { dbNamespace: "main-db" },
|
|
334
|
+
* dependencies: {
|
|
335
|
+
* commerce: $commerceModule,
|
|
336
|
+
* order: $orderModule,
|
|
337
|
+
* },
|
|
338
|
+
* });
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
export const defineModule = <
|
|
342
|
+
C extends Record<string, unknown>,
|
|
343
|
+
Tables extends Record<string, unknown> = Record<string, unknown>
|
|
344
|
+
>(baseProps: {
|
|
35
345
|
packageName: string;
|
|
36
|
-
}):
|
|
37
|
-
|
|
346
|
+
}): ModuleBuilder<C, Tables> => {
|
|
347
|
+
const createModule = <Deps extends DependencyModules>(
|
|
348
|
+
deps: Deps,
|
|
349
|
+
devConfig?: C
|
|
350
|
+
): DefinedModule<C, Tables, Deps> => ({
|
|
38
351
|
packageName: baseProps.packageName,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
};
|
|
352
|
+
dependencies: deps,
|
|
353
|
+
devConfig,
|
|
354
|
+
configure: (props) => ({
|
|
355
|
+
packageName: baseProps.packageName,
|
|
356
|
+
moduleProps: { config: props.config },
|
|
357
|
+
}),
|
|
358
|
+
});
|
|
47
359
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
360
|
+
const createBuilder = <Deps extends DependencyModules>(
|
|
361
|
+
deps: Deps,
|
|
362
|
+
devConfig?: C
|
|
363
|
+
): ModuleBuilder<C, Tables, Deps> => ({
|
|
364
|
+
withDependencies: <const NewDeps extends DependencyModules>(
|
|
365
|
+
newDeps: NewDeps
|
|
366
|
+
): ModuleBuilder<C, Tables, NewDeps> => createBuilder(newDeps, devConfig),
|
|
367
|
+
withDevConfig: (config: C): ModuleBuilder<C, Tables, Deps> =>
|
|
368
|
+
createBuilder(deps, config),
|
|
369
|
+
build: (): DefinedModule<C, Tables, Deps> => createModule(deps, devConfig),
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return createBuilder({} as EmptyDependencies);
|
|
373
|
+
};
|
|
54
374
|
|
|
55
375
|
// ============================================================================
|
|
56
376
|
// Utility Types for Module Development
|
package/src/builder/index.ts
CHANGED
|
@@ -2,8 +2,13 @@ export {
|
|
|
2
2
|
defineModule,
|
|
3
3
|
type ConfiguredModule,
|
|
4
4
|
type DefinedModule,
|
|
5
|
-
type ModuleDependency,
|
|
6
5
|
type TablesFromNames,
|
|
7
6
|
type ModuleFactoryContext,
|
|
7
|
+
type DependencyModules,
|
|
8
|
+
type EmptyDependencies,
|
|
9
|
+
type ModuleBuilder,
|
|
10
|
+
type AnyDefinedModule,
|
|
11
|
+
type ModuleBuilderProps,
|
|
12
|
+
type ConfiguredDependencies,
|
|
8
13
|
} from "./helpers";
|
|
9
14
|
export { withModuleConfiguration } from "./register";
|
package/src/builder/register.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { LoadedModules } from "../config/module-loader";
|
|
2
|
-
import type { DefinedModule } from "./helpers";
|
|
3
|
-
|
|
4
|
-
type ModuleFactoryContext<C extends Record<string, unknown>> = {
|
|
5
|
-
config: C;
|
|
6
|
-
};
|
|
2
|
+
import type { DefinedModule, ModuleFactoryContext } from "./helpers";
|
|
7
3
|
|
|
8
4
|
/**
|
|
9
5
|
* Define module exports that depend on configuration from loadModules.
|
|
@@ -35,9 +31,10 @@ type ModuleFactoryContext<C extends Record<string, unknown>> = {
|
|
|
35
31
|
export const withModuleConfiguration = <
|
|
36
32
|
C extends Record<string, unknown>,
|
|
37
33
|
Tables extends Record<string, unknown>,
|
|
34
|
+
Deps extends Record<string, any>,
|
|
38
35
|
Result
|
|
39
36
|
>(
|
|
40
|
-
module: DefinedModule<C, Tables>,
|
|
37
|
+
module: DefinedModule<C, Tables, Deps>,
|
|
41
38
|
factory: (
|
|
42
39
|
context: ModuleFactoryContext<C>,
|
|
43
40
|
loadedModules: LoadedModules
|