@common-stack/server-core 7.2.1-alpha.31 → 7.2.1-alpha.32

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.
@@ -0,0 +1,491 @@
1
+ /**
2
+ * @file typed-moleculer-service.ts
3
+ * @description Provides type-safe base class for Moleculer services with ENFORCED
4
+ * compile-time verification AND automatic action generation from service methods.
5
+ */
6
+ import type { ServiceSchema } from 'moleculer';
7
+ import { type ExcludedServiceMethods } from './serviceGenerationUtils';
8
+ /**
9
+ * Exclude base service CRUD methods and lifecycle methods
10
+ * @deprecated Use ExcludedServiceMethods from serviceGenerationUtils instead
11
+ */
12
+ type ExcludedMethods = ExcludedServiceMethods;
13
+ /**
14
+ * Extract all method names from a service interface (excluding base methods)
15
+ */
16
+ export type ServiceMethods<T> = {
17
+ [K in keyof T]: T[K] extends Function ? (K extends ExcludedMethods ? never : K) : never;
18
+ }[keyof T];
19
+ /**
20
+ * Required actions type - forces all service methods to have actions
21
+ */
22
+ export type RequiredServiceActions<TService> = {
23
+ [K in ServiceMethods<TService>]: {
24
+ params?: Record<string, unknown>;
25
+ handler: (...args: unknown[]) => unknown;
26
+ };
27
+ };
28
+ /**
29
+ * Service schema with REQUIRED typed actions - TypeScript will error if any are missing
30
+ */
31
+ export interface EnforcedServiceSchema<TService> extends Omit<ServiceSchema, 'actions'> {
32
+ name: string;
33
+ actions: RequiredServiceActions<TService> & Record<string, unknown>;
34
+ }
35
+ /**
36
+ * ADVANCED AUTO-GENERATED configuration with full control
37
+ * Params are inferred from TypeScript function signatures with optional fine-grained control
38
+ */
39
+ export type AutoInferredActionConfig<TService> = {
40
+ /**
41
+ * Optional: Override param schemas for specific methods
42
+ * Use this when you need custom Moleculer validation beyond the default 'object' type
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * paramOverrides: {
47
+ * findAccountById: { id: 'string' }, // Override inferred 'object' with 'string'
48
+ * getUsers: { where: { type: 'object', optional: true } } // Add optional flag
49
+ * }
50
+ * ```
51
+ */
52
+ paramOverrides?: Partial<{
53
+ [K in ServiceMethods<TService>]: Record<string, unknown>;
54
+ }>;
55
+ /**
56
+ * Optional: Only include specific methods (whitelist approach)
57
+ * If specified, ONLY these methods will be auto-generated
58
+ * Takes precedence over exclude
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * include: ['findAccountById', 'createAccount', 'updateAccount']
63
+ * ```
64
+ */
65
+ include?: Array<ServiceMethods<TService>>;
66
+ /**
67
+ * Optional: Exclude specific methods from auto-generation (blacklist approach)
68
+ * Ignored if 'include' is specified
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * exclude: ['deleteAccount', 'internalMethod']
73
+ * ```
74
+ */
75
+ exclude?: Array<ServiceMethods<TService>>;
76
+ /**
77
+ * Optional: Map action names to different method names
78
+ * Use this when your Moleculer action name differs from the service method name
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * actionToMethodMap: {
83
+ * 'accounts.find': 'findAccountById',
84
+ * 'accounts.create': 'createAccount'
85
+ * }
86
+ * ```
87
+ */
88
+ actionToMethodMap?: Record<string, string>;
89
+ /**
90
+ * Optional: Add custom Moleculer action properties for specific methods
91
+ * Allows setting visibility, caching, rate limiting, etc.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * actionConfig: {
96
+ * findAccountById: {
97
+ * cache: true,
98
+ * visibility: 'public'
99
+ * },
100
+ * deleteAccount: {
101
+ * visibility: 'protected'
102
+ * }
103
+ * }
104
+ * ```
105
+ */
106
+ actionConfig?: Partial<{
107
+ [K in ServiceMethods<TService>]: {
108
+ cache?: boolean | object;
109
+ visibility?: 'public' | 'protected' | 'private';
110
+ [key: string]: unknown;
111
+ };
112
+ }>;
113
+ };
114
+ /**
115
+ * ADVANCED AUTO-GENERATED: Generate actions with full control over inclusion, exclusion, and overrides.
116
+ * Params are inferred from TypeScript function signatures with optional fine-grained control.
117
+ *
118
+ * @param service - The service instance to wrap
119
+ * @param config - Advanced configuration for fine-grained control
120
+ * @returns Actions object with handlers for selected service methods
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * // Basic: Auto-generate all methods
125
+ * const actions = generateAutoInferredServiceActions<IAccountService>(accountService);
126
+ *
127
+ * // Advanced: Include only specific methods
128
+ * const actions = generateAutoInferredServiceActions<IAccountService>(accountService, {
129
+ * include: ['findAccountById', 'createAccount', 'updateAccount']
130
+ * });
131
+ *
132
+ * // Advanced: Exclude specific methods
133
+ * const actions = generateAutoInferredServiceActions<IAccountService>(accountService, {
134
+ * exclude: ['deleteAccount', 'internalMethod']
135
+ * });
136
+ *
137
+ * // Advanced: Override param schemas for specific methods
138
+ * const actions = generateAutoInferredServiceActions<IAccountService>(accountService, {
139
+ * paramOverrides: {
140
+ * findAccountById: { id: 'string' },
141
+ * getUsers: { where: { type: 'object', optional: true } }
142
+ * }
143
+ * });
144
+ *
145
+ * // Advanced: Add custom action configuration
146
+ * const actions = generateAutoInferredServiceActions<IAccountService>(accountService, {
147
+ * actionConfig: {
148
+ * findAccountById: { cache: true, visibility: 'public' },
149
+ * deleteAccount: { visibility: 'protected' }
150
+ * }
151
+ * });
152
+ *
153
+ * // Advanced: Combine multiple options
154
+ * const actions = generateAutoInferredServiceActions<IAccountService>(accountService, {
155
+ * include: ['findAccountById', 'createAccount'],
156
+ * paramOverrides: {
157
+ * findAccountById: { id: 'string' }
158
+ * },
159
+ * actionConfig: {
160
+ * findAccountById: { cache: true }
161
+ * }
162
+ * });
163
+ * ```
164
+ */
165
+ export declare function generateAutoInferredServiceActions<TService>(service: TService, config?: AutoInferredActionConfig<TService>): Record<string, {
166
+ params?: Record<string, unknown>;
167
+ handler: (ctx: unknown) => unknown;
168
+ }>;
169
+ /**
170
+ * Generate both actions AND events from a service instance
171
+ * - Actions: Generated from regular service methods
172
+ * - Events: Generated from methods marked with @MoleculerEventHandler decorator
173
+ *
174
+ * @param service - The service instance to wrap
175
+ * @param config - Configuration for actions and events
176
+ * @returns Object with both actions and events
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * // Service with decorator
181
+ * class OrganizationService {
182
+ * // Regular method becomes action
183
+ * async createOrganization(org: Org): Promise<Org> { }
184
+ *
185
+ * // Decorated method becomes event handler
186
+ * @MoleculerEventHandler(UserBroadcasterAction.OnUserCreated)
187
+ * async onUserCreated(event: UserEvent): Promise<void> { }
188
+ * }
189
+ *
190
+ * // Generate both
191
+ * const { actions, events } = generateServiceActionsAndEvents(service);
192
+ * ```
193
+ */
194
+ export declare function generateServiceActionsAndEvents<TService>(service: TService, config?: AutoInferredActionConfig<TService>): {
195
+ actions: Record<string, {
196
+ params?: Record<string, unknown>;
197
+ handler: (ctx: unknown) => unknown;
198
+ [key: string]: unknown;
199
+ }>;
200
+ events: Record<string, {
201
+ handler: (ctx: unknown) => unknown;
202
+ group?: string;
203
+ }>;
204
+ };
205
+ export interface AutoActionConfig {
206
+ /**
207
+ * Custom parameter validation schema for specific actions
208
+ * Key is the action/method name, value is Moleculer params schema
209
+ */
210
+ params?: Record<string, Record<string, unknown>>;
211
+ /**
212
+ * Actions to exclude from auto-generation (use manual handlers instead)
213
+ */
214
+ exclude?: string[];
215
+ /**
216
+ * Action name mappings (if action name differs from method name)
217
+ * Key is the action name, value is the method name
218
+ */
219
+ actionToMethodMap?: Record<string, string>;
220
+ }
221
+ /**
222
+ * Type-safe configuration that REQUIRES params for ALL service methods
223
+ * TypeScript will show compile error if any method is missing from params
224
+ */
225
+ export type TypeSafeActionConfig<TService> = {
226
+ /**
227
+ * REQUIRED: Parameter validation schema for ALL service methods
228
+ * TypeScript will error if any method is missing
229
+ */
230
+ params: {
231
+ [K in ServiceMethods<TService>]: Record<string, unknown>;
232
+ };
233
+ /**
234
+ * Optional: Actions to exclude from auto-generation
235
+ */
236
+ exclude?: string[];
237
+ /**
238
+ * Optional: Action name mappings
239
+ */
240
+ actionToMethodMap?: Record<string, string>;
241
+ };
242
+ /**
243
+ * Automatically generate Moleculer actions from a service instance.
244
+ *
245
+ * This eliminates the need to write repetitive action handlers - just pass your service
246
+ * and it will create handlers that forward all calls automatically.
247
+ *
248
+ * @param service - The service instance to wrap
249
+ * @param config - Optional configuration for customizing actions
250
+ * @returns Actions object with handlers for all service methods
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const actions = generateServiceActions(accountService, {
255
+ * params: {
256
+ * findAccountById: { id: 'string' },
257
+ * createAccount: { account: 'object' }
258
+ * },
259
+ * exclude: ['get', 'getAll'] // Handle these manually
260
+ * });
261
+ * ```
262
+ */
263
+ export declare function generateServiceActions<TService extends Record<string, unknown>>(service: TService, config?: AutoActionConfig): Record<string, {
264
+ params?: Record<string, unknown>;
265
+ handler: (ctx: unknown) => unknown;
266
+ }>;
267
+ /**
268
+ * TYPE-SAFE version: Generate Moleculer actions with COMPILE-TIME verification.
269
+ * TypeScript will error if any service method is missing from params.
270
+ *
271
+ * @param service - The service instance to wrap
272
+ * @param config - Type-safe configuration requiring ALL methods to have params
273
+ * @returns Actions object with handlers for all service methods
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * const actions = generateTypeSafeServiceActions<IAccountService>(accountService, {
278
+ * params: {
279
+ * // TypeScript enforces ALL IAccountService methods are here!
280
+ * findAccountById: { id: 'string' },
281
+ * createAccount: { account: 'object' },
282
+ * // ... if you forget any method, TypeScript will error
283
+ * }
284
+ * });
285
+ * ```
286
+ */
287
+ export declare function generateTypeSafeServiceActions<TService>(service: TService, config: TypeSafeActionConfig<TService>): Record<string, {
288
+ params?: Record<string, unknown>;
289
+ handler: (ctx: unknown) => unknown;
290
+ }>;
291
+ /**
292
+ * Verify that all service methods have param validation defined.
293
+ * Throws an error if any methods are missing params.
294
+ *
295
+ * Use this in development to ensure you haven't forgotten any param schemas.
296
+ *
297
+ * @param service - The service instance
298
+ * @param config - The config used for generateServiceActions
299
+ * @throws Error if any methods are missing param validation
300
+ *
301
+ * @example
302
+ * ```typescript
303
+ * const config = { params: { ... }, exclude: [...] };
304
+ * verifyAllParamsDefined(accountService, config); // Throws if params missing
305
+ * const actions = generateServiceActions(accountService, config);
306
+ * ```
307
+ */
308
+ export declare function verifyAllParamsDefined<TService extends Record<string, unknown>>(service: TService, config?: AutoActionConfig): void;
309
+ /**
310
+ * Type-safe Moleculer Service base class with ENFORCED action verification.
311
+ *
312
+ * @deprecated Use generateServiceActionsAndEvents() or generateAutoInferredServiceActions() instead
313
+ * This class requires importing Moleculer Service which causes build issues.
314
+ *
315
+ * Usage with auto-generated actions:
316
+ * ```typescript
317
+ * export class AccountMoleculerService extends Service {
318
+ * constructor(broker: ServiceBroker, { container }: { container: Container }) {
319
+ * super(broker);
320
+ * const accountService = container.get<IAccountService>(SERVER_TYPES.IAccountService);
321
+ *
322
+ * // Automatically generate ALL actions from the service!
323
+ * const autoActions = generateAutoInferredServiceActions(accountService);
324
+ *
325
+ * this.parseServiceSchema({
326
+ * name: MoleculerServiceName.AccountUser,
327
+ * actions: autoActions,
328
+ * });
329
+ * }
330
+ * }
331
+ * ```
332
+ */
333
+ /**
334
+ * Placeholder for TypedMoleculerService for backward compatibility
335
+ * @deprecated Use generateServiceActionsAndEvents() instead
336
+ */
337
+ export type TypedMoleculerService<TService> = unknown;
338
+ /**
339
+ * Helper type for explicit verification - use in const to get better error messages
340
+ */
341
+ export type VerifyAllActionsImplemented<TService> = {
342
+ [K in ServiceMethods<TService>]: true;
343
+ };
344
+ /**
345
+ * Typed action handler with parameter and return type safety
346
+ */
347
+ export interface TypedActionHandler<TParams = unknown, TReturn = unknown> {
348
+ params?: Record<string, unknown>;
349
+ handler: (ctx: {
350
+ params: TParams;
351
+ }) => TReturn | Promise<TReturn>;
352
+ }
353
+ /**
354
+ * Helper to create a typed action handler
355
+ */
356
+ export declare function createTypedAction<TParams, TReturn>(action: TypedActionHandler<TParams, TReturn>): TypedActionHandler<TParams, TReturn>;
357
+ /**
358
+ * Service schema type with better action type hints
359
+ */
360
+ export interface TypedServiceSchema extends ServiceSchema {
361
+ actions?: Record<string, TypedActionHandler>;
362
+ }
363
+ /**
364
+ * Extend Moleculer namespace with action generation utilities
365
+ */
366
+ declare module './moleculerEventHandler' {
367
+ namespace Moleculer {
368
+ /**
369
+ * ADVANCED AUTO-GENERATED configuration with full control
370
+ */
371
+ type AutoInferredActionConfig<TService> = {
372
+ paramOverrides?: Partial<{
373
+ [K in ServiceMethods<TService>]: Record<string, unknown>;
374
+ }>;
375
+ include?: Array<ServiceMethods<TService>>;
376
+ exclude?: Array<ServiceMethods<TService>>;
377
+ actionToMethodMap?: Record<string, string>;
378
+ actionConfig?: Partial<{
379
+ [K in ServiceMethods<TService>]: {
380
+ cache?: boolean | object;
381
+ visibility?: 'public' | 'protected' | 'private';
382
+ [key: string]: unknown;
383
+ };
384
+ }>;
385
+ };
386
+ /**
387
+ * Generate actions with full control over inclusion, exclusion, and overrides.
388
+ * Params are inferred from TypeScript function signatures.
389
+ */
390
+ function generateAutoInferredActions<TService>(service: TService, config?: AutoInferredActionConfig<TService>): Record<string, {
391
+ params?: Record<string, unknown>;
392
+ handler: (ctx: unknown) => unknown;
393
+ }>;
394
+ /**
395
+ * Generate both actions AND events from a service instance
396
+ */
397
+ function generateActionsAndEvents<TService>(service: TService, config?: AutoInferredActionConfig<TService>): {
398
+ actions: Record<string, {
399
+ params?: Record<string, unknown>;
400
+ handler: (ctx: unknown) => unknown;
401
+ [key: string]: unknown;
402
+ }>;
403
+ events: Record<string, {
404
+ handler: (ctx: unknown) => unknown;
405
+ group?: string;
406
+ }>;
407
+ };
408
+ /**
409
+ * DEBUG UTILITY: Extract parameter information for all service methods
410
+ * Returns detailed information about parameters, schemas, and configurations
411
+ */
412
+ function debugServiceParams<TService>(service: TService, config?: AutoInferredActionConfig<TService>): Record<string, {
413
+ methodName: string;
414
+ paramNames: string[];
415
+ functionSignature: string;
416
+ inferredSchema: Record<string, unknown> | undefined;
417
+ overrideSchema: Record<string, unknown> | undefined;
418
+ isExcluded: boolean;
419
+ isEventHandler: boolean;
420
+ }>;
421
+ /**
422
+ * DEBUG UTILITY: Pretty print service parameter information to console
423
+ * Useful for understanding auto-generation and identifying methods needing overrides
424
+ */
425
+ function printServiceParams<TService>(service: TService, config?: AutoInferredActionConfig<TService>, options?: {
426
+ onlyMissingOverrides?: boolean;
427
+ onlyIncluded?: boolean;
428
+ showExcluded?: boolean;
429
+ }): void;
430
+ }
431
+ }
432
+ /**
433
+ * DEBUG UTILITY: Dumps parameter information for all service methods
434
+ *
435
+ * This function extracts and logs parameter names, types, and inferred schemas
436
+ * for debugging auto-generation issues. Use during development to understand
437
+ * what the auto-generation sees and optimize paramOverrides.
438
+ *
439
+ * @param service - The service instance to analyze
440
+ * @param config - Optional configuration to see what would be generated
441
+ * @returns Object with detailed parameter information for each method
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * // In development/debug mode
446
+ * const paramInfo = Moleculer.debugServiceParams(accountService);
447
+ * console.log(JSON.stringify(paramInfo, null, 2));
448
+ *
449
+ * // With config to see filtered results
450
+ * const paramInfo = Moleculer.debugServiceParams(accountService, {
451
+ * exclude: ['dispose', 'createUserToken']
452
+ * });
453
+ * ```
454
+ */
455
+ export declare function debugServiceParams<TService>(service: TService, config?: AutoInferredActionConfig<TService>): Record<string, {
456
+ methodName: string;
457
+ paramNames: string[];
458
+ functionSignature: string;
459
+ inferredSchema: Record<string, unknown> | undefined;
460
+ overrideSchema: Record<string, unknown> | undefined;
461
+ isExcluded: boolean;
462
+ isEventHandler: boolean;
463
+ }>;
464
+ /**
465
+ * DEBUG UTILITY: Pretty prints service parameter information to console
466
+ *
467
+ * Formats and logs the output of debugServiceParams() in a readable way.
468
+ * Shows which methods need paramOverrides and what types are inferred.
469
+ *
470
+ * @param service - The service instance to analyze
471
+ * @param config - Optional configuration
472
+ * @param options - Display options
473
+ *
474
+ * @example
475
+ * ```typescript
476
+ * // Print all methods
477
+ * Moleculer.printServiceParams(accountService);
478
+ *
479
+ * // Print only methods without overrides
480
+ * Moleculer.printServiceParams(accountService, config, { onlyMissingOverrides: true });
481
+ *
482
+ * // Print only included methods
483
+ * Moleculer.printServiceParams(accountService, config, { onlyIncluded: true });
484
+ * ```
485
+ */
486
+ export declare function printServiceParams<TService>(service: TService, config?: AutoInferredActionConfig<TService>, options?: {
487
+ onlyMissingOverrides?: boolean;
488
+ onlyIncluded?: boolean;
489
+ showExcluded?: boolean;
490
+ }): void;
491
+ export {};