@lark-apaas/nestjs-capability 0.0.1-alpha.6 → 0.0.1-alpha.8

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/dist/index.js CHANGED
@@ -179,6 +179,28 @@ import { Injectable as Injectable3, Logger as Logger2, Inject } from "@nestjs/co
179
179
  import { RequestContextService, PLATFORM_HTTP_CLIENT } from "@lark-apaas/nestjs-common";
180
180
  import * as fs from "fs";
181
181
  import * as path from "path";
182
+
183
+ // src/utils/log-utils.ts
184
+ var DEFAULT_MAX_LENGTH = 1e3;
185
+ function truncateString(str, maxLength) {
186
+ if (str.length <= maxLength) {
187
+ return str;
188
+ }
189
+ return str.slice(0, maxLength) + `... [truncated, total ${str.length} chars]`;
190
+ }
191
+ __name(truncateString, "truncateString");
192
+ function stringifyForLog(value, maxLength = DEFAULT_MAX_LENGTH) {
193
+ try {
194
+ const str = JSON.stringify(value, null, 2);
195
+ return truncateString(str, maxLength);
196
+ } catch {
197
+ const str = String(value);
198
+ return truncateString(str, maxLength);
199
+ }
200
+ }
201
+ __name(stringifyForLog, "stringifyForLog");
202
+
203
+ // src/services/capability.service.ts
182
204
  function _ts_decorate3(decorators, target, key, desc) {
183
205
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
184
206
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -219,15 +241,15 @@ var CapabilityService = class _CapabilityService {
219
241
  __name(this, "CapabilityService");
220
242
  }
221
243
  requestContextService;
222
- httpClient;
244
+ platformHttpClient;
223
245
  pluginLoaderService;
224
246
  templateEngineService;
225
247
  logger = new Logger2(_CapabilityService.name);
226
248
  capabilities = /* @__PURE__ */ new Map();
227
249
  capabilitiesDir;
228
- constructor(requestContextService, httpClient, pluginLoaderService, templateEngineService) {
250
+ constructor(requestContextService, platformHttpClient, pluginLoaderService, templateEngineService) {
229
251
  this.requestContextService = requestContextService;
230
- this.httpClient = httpClient;
252
+ this.platformHttpClient = platformHttpClient;
231
253
  this.pluginLoaderService = pluginLoaderService;
232
254
  this.templateEngineService = templateEngineService;
233
255
  this.capabilitiesDir = path.join(process.cwd(), "server/capabilities");
@@ -315,20 +337,23 @@ var CapabilityService = class _CapabilityService {
315
337
  */
316
338
  async executeCall(config, actionName, input, contextOverride) {
317
339
  const startTime = Date.now();
340
+ const loggerContext = {
341
+ capability_id: config.id,
342
+ plugin_key: config.pluginKey,
343
+ action: actionName
344
+ };
318
345
  try {
319
346
  const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
320
347
  if (!pluginInstance.hasAction(actionName)) {
321
348
  throw new ActionNotFoundError(config.pluginKey, actionName);
322
349
  }
323
- const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
350
+ const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
324
351
  const context = this.buildActionContext(contextOverride);
325
352
  const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
326
- this.logger.log({
327
- message: "Executing capability",
328
- capabilityId: config.id,
329
- action: actionName,
330
- pluginKey: config.pluginKey,
331
- isStream
353
+ this.logger.log("Executing capability (call)", {
354
+ ...loggerContext,
355
+ is_stream: isStream,
356
+ input: stringifyForLog(input)
332
357
  });
333
358
  let result;
334
359
  if (isStream && pluginInstance.runStream) {
@@ -340,20 +365,17 @@ var CapabilityService = class _CapabilityService {
340
365
  } else {
341
366
  result = await pluginInstance.run(actionName, context, resolvedParams);
342
367
  }
343
- this.logger.log({
344
- message: "Capability executed successfully",
345
- capabilityId: config.id,
346
- action: actionName,
347
- duration: Date.now() - startTime
368
+ this.logger.log("Capability (call) executed successfully", {
369
+ ...loggerContext,
370
+ duration_ms: Date.now() - startTime,
371
+ output: stringifyForLog(result)
348
372
  });
349
373
  return result;
350
374
  } catch (error) {
351
- this.logger.error({
352
- message: "Capability execution failed",
353
- capabilityId: config.id,
354
- action: actionName,
355
- error: error instanceof Error ? error.message : String(error),
356
- duration: Date.now() - startTime
375
+ this.logger.error("Capability (call) execution failed", {
376
+ ...loggerContext,
377
+ duration_ms: Date.now() - startTime,
378
+ error: error instanceof Error ? error.message : String(error)
357
379
  });
358
380
  throw error;
359
381
  }
@@ -365,40 +387,46 @@ var CapabilityService = class _CapabilityService {
365
387
  */
366
388
  async *executeCallStream(config, actionName, input, contextOverride) {
367
389
  const startTime = Date.now();
390
+ const loggerContext = {
391
+ capability_id: config.id,
392
+ plugin_key: config.pluginKey,
393
+ action: actionName
394
+ };
395
+ const chunks = [];
368
396
  try {
369
397
  const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
370
398
  if (!pluginInstance.hasAction(actionName)) {
371
399
  throw new ActionNotFoundError(config.pluginKey, actionName);
372
400
  }
373
- const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
401
+ const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
374
402
  const context = this.buildActionContext(contextOverride);
375
403
  const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
376
- this.logger.log({
377
- message: "Executing capability (stream)",
378
- capabilityId: config.id,
379
- action: actionName,
380
- pluginKey: config.pluginKey,
381
- isStream
404
+ this.logger.log("Executing capability (stream)", {
405
+ ...loggerContext,
406
+ is_stream: isStream,
407
+ input: stringifyForLog(input)
382
408
  });
383
409
  if (isStream && pluginInstance.runStream) {
384
- yield* pluginInstance.runStream(actionName, context, resolvedParams);
410
+ for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
411
+ chunks.push(chunk);
412
+ yield chunk;
413
+ }
385
414
  } else {
386
415
  const result = await pluginInstance.run(actionName, context, resolvedParams);
416
+ chunks.push(result);
387
417
  yield result;
388
418
  }
389
- this.logger.log({
390
- message: "Capability stream completed",
391
- capabilityId: config.id,
392
- action: actionName,
393
- duration: Date.now() - startTime
419
+ const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
420
+ this.logger.log("Capability (stream) executed successfully", {
421
+ ...loggerContext,
422
+ duration_ms: Date.now() - startTime,
423
+ output: stringifyForLog(aggregatedResult)
394
424
  });
395
425
  } catch (error) {
396
- this.logger.error({
397
- message: "Capability stream execution failed",
398
- capabilityId: config.id,
399
- action: actionName,
400
- error: error instanceof Error ? error.message : String(error),
401
- duration: Date.now() - startTime
426
+ this.logger.error("Capability (stream) execution failed", {
427
+ ...loggerContext,
428
+ duration_ms: Date.now() - startTime,
429
+ error: error instanceof Error ? error.message : String(error)
402
430
  });
403
431
  throw error;
404
432
  }
@@ -410,27 +438,47 @@ var CapabilityService = class _CapabilityService {
410
438
  */
411
439
  async *executeCallStreamWithEvents(config, actionName, input, contextOverride) {
412
440
  const startTime = Date.now();
413
- let chunkCount = 0;
441
+ const loggerContext = {
442
+ capability_id: config.id,
443
+ plugin_key: config.pluginKey,
444
+ action: actionName
445
+ };
446
+ const chunks = [];
414
447
  try {
415
448
  const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
416
449
  if (!pluginInstance.hasAction(actionName)) {
417
450
  throw new ActionNotFoundError(config.pluginKey, actionName);
418
451
  }
419
- const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
452
+ const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
420
453
  const context = this.buildActionContext(contextOverride);
421
- this.logger.log({
422
- message: "Executing capability (streamWithEvents)",
423
- capabilityId: config.id,
424
- action: actionName,
425
- pluginKey: config.pluginKey
454
+ const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
455
+ this.logger.log("Executing capability (streamWithEvents)", {
456
+ ...loggerContext,
457
+ is_stream: isStream,
458
+ input: stringifyForLog(input)
426
459
  });
427
460
  if (pluginInstance.runStreamWithEvents) {
428
- yield* pluginInstance.runStreamWithEvents(actionName, context, resolvedParams);
461
+ for await (const event of pluginInstance.runStreamWithEvents(actionName, context, resolvedParams)) {
462
+ if (event.type === "data") {
463
+ chunks.push(event.data);
464
+ yield event;
465
+ } else if (event.type === "done") {
466
+ const aggregatedResult2 = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
467
+ yield {
468
+ type: "done",
469
+ metadata: {
470
+ ...event.metadata,
471
+ aggregated: aggregatedResult2
472
+ }
473
+ };
474
+ } else {
475
+ yield event;
476
+ }
477
+ }
429
478
  } else {
430
- const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
431
479
  if (isStream && pluginInstance.runStream) {
432
480
  for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
433
- chunkCount++;
481
+ chunks.push(chunk);
434
482
  yield {
435
483
  type: "data",
436
484
  data: chunk
@@ -438,34 +486,33 @@ var CapabilityService = class _CapabilityService {
438
486
  }
439
487
  } else {
440
488
  const result = await pluginInstance.run(actionName, context, resolvedParams);
441
- chunkCount = 1;
489
+ chunks.push(result);
442
490
  yield {
443
491
  type: "data",
444
492
  data: result
445
493
  };
446
494
  }
495
+ const aggregatedResult2 = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
447
496
  yield {
448
497
  type: "done",
449
498
  metadata: {
450
- chunks: chunkCount,
451
- duration: Date.now() - startTime
499
+ chunks: chunks.length,
500
+ duration: Date.now() - startTime,
501
+ aggregated: aggregatedResult2
452
502
  }
453
503
  };
454
504
  }
455
- this.logger.log({
456
- message: "Capability streamWithEvents completed",
457
- capabilityId: config.id,
458
- action: actionName,
459
- duration: Date.now() - startTime,
460
- chunks: chunkCount
505
+ const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
506
+ this.logger.log("Capability (streamWithEvents) executed successfully", {
507
+ ...loggerContext,
508
+ duration_ms: Date.now() - startTime,
509
+ output: stringifyForLog(aggregatedResult)
461
510
  });
462
511
  } catch (error) {
463
- this.logger.error({
464
- message: "Capability streamWithEvents execution failed",
465
- capabilityId: config.id,
466
- action: actionName,
467
- error: error instanceof Error ? error.message : String(error),
468
- duration: Date.now() - startTime
512
+ this.logger.error("Capability (streamWithEvents) execution failed", {
513
+ ...loggerContext,
514
+ duration_ms: Date.now() - startTime,
515
+ error: error instanceof Error ? error.message : String(error)
469
516
  });
470
517
  yield {
471
518
  type: "error",
@@ -479,13 +526,15 @@ var CapabilityService = class _CapabilityService {
479
526
  buildActionContext(override) {
480
527
  return {
481
528
  logger: this.logger,
482
- httpClient: this.httpClient,
483
- userContext: override?.userContext ?? this.getUserContext()
529
+ platformHttpClient: this.platformHttpClient,
530
+ userContext: override?.userContext ?? this.getUserContext(),
531
+ isDebug: override?.isDebug ?? false
484
532
  };
485
533
  }
486
534
  getUserContext() {
487
535
  const ctx = this.requestContextService.getContext();
488
536
  return {
537
+ appId: ctx?.appId ?? "",
489
538
  userId: ctx?.userId ?? "",
490
539
  tenantId: ctx?.tenantId ?? ""
491
540
  };
@@ -504,7 +553,7 @@ CapabilityService = _ts_decorate3([
504
553
  ], CapabilityService);
505
554
 
506
555
  // src/controllers/debug.controller.ts
507
- import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus } from "@nestjs/common";
556
+ import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus, Logger as Logger3 } from "@nestjs/common";
508
557
  function _ts_decorate4(decorators, target, key, desc) {
509
558
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
510
559
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -522,13 +571,14 @@ function _ts_param2(paramIndex, decorator) {
522
571
  };
523
572
  }
524
573
  __name(_ts_param2, "_ts_param");
525
- var DebugController = class {
574
+ var DebugController = class _DebugController {
526
575
  static {
527
576
  __name(this, "DebugController");
528
577
  }
529
578
  capabilityService;
530
579
  pluginLoaderService;
531
580
  templateEngineService;
581
+ logger = new Logger3(_DebugController.name);
532
582
  constructor(capabilityService, pluginLoaderService, templateEngineService) {
533
583
  this.capabilityService = capabilityService;
534
584
  this.pluginLoaderService = pluginLoaderService;
@@ -592,7 +642,9 @@ var DebugController = class {
592
642
  const action = await this.getActionName(config.pluginKey, body.action);
593
643
  const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
594
644
  try {
595
- const result = await this.capabilityService.loadWithConfig(config).call(action, params);
645
+ const result = await this.capabilityService.loadWithConfig(config).call(action, params, {
646
+ isDebug: true
647
+ });
596
648
  return {
597
649
  status_code: ErrorCodes.SUCCESS,
598
650
  data: {
@@ -639,39 +691,61 @@ var DebugController = class {
639
691
  try {
640
692
  const config = this.getCapabilityConfig(capabilityId, body.capability);
641
693
  const action = await this.getActionName(config.pluginKey, body.action);
694
+ const loggerContext = {
695
+ capability_id: config.id,
696
+ plugin_key: config.pluginKey,
697
+ action
698
+ };
699
+ this.logger.log(`Executing capability (stream)`, {
700
+ ...loggerContext,
701
+ input: stringifyForLog(params)
702
+ });
642
703
  const capability = this.capabilityService.loadWithConfig(config);
643
- const eventStream = capability.callStreamWithEvents(action, params);
704
+ const eventStream = capability.callStreamWithEvents(action, params, {
705
+ isDebug: true
706
+ });
707
+ let pendingChunk = null;
644
708
  for await (const event of eventStream) {
645
709
  switch (event.type) {
646
710
  case "data": {
647
- const response = {
648
- status_code: ErrorCodes.SUCCESS,
649
- data: {
650
- type: "content",
651
- delta: {
652
- content: event.data
711
+ if (pendingChunk !== null) {
712
+ const response = {
713
+ status_code: ErrorCodes.SUCCESS,
714
+ data: {
715
+ type: "content",
716
+ delta: {
717
+ content: pendingChunk
718
+ }
653
719
  }
654
- }
655
- };
656
- res.write(`data: ${JSON.stringify(response)}
720
+ };
721
+ res.write(`data: ${JSON.stringify(response)}
657
722
 
658
723
  `);
724
+ }
725
+ pendingChunk = event.data;
659
726
  break;
660
727
  }
661
728
  case "done": {
662
- const response = {
663
- status_code: ErrorCodes.SUCCESS,
664
- data: {
665
- type: "content",
666
- delta: {
667
- content: null
668
- },
669
- finished: true
670
- }
671
- };
672
- res.write(`data: ${JSON.stringify(response)}
729
+ if (pendingChunk !== null) {
730
+ const response = {
731
+ status_code: ErrorCodes.SUCCESS,
732
+ data: {
733
+ type: "content",
734
+ delta: {
735
+ content: pendingChunk
736
+ },
737
+ finished: true
738
+ }
739
+ };
740
+ res.write(`data: ${JSON.stringify(response)}
673
741
 
674
742
  `);
743
+ }
744
+ this.logger.log(`Capability (stream) executed successfully`, {
745
+ ...loggerContext,
746
+ duration_ms: event.metadata.duration,
747
+ output: stringifyForLog(event.metadata.aggregated)
748
+ });
675
749
  res.end();
676
750
  return;
677
751
  }
@@ -694,6 +768,21 @@ var DebugController = class {
694
768
  }
695
769
  }
696
770
  }
771
+ if (pendingChunk !== null) {
772
+ const response = {
773
+ status_code: ErrorCodes.SUCCESS,
774
+ data: {
775
+ type: "content",
776
+ delta: {
777
+ content: pendingChunk
778
+ },
779
+ finished: true
780
+ }
781
+ };
782
+ res.write(`data: ${JSON.stringify(response)}
783
+
784
+ `);
785
+ }
697
786
  res.end();
698
787
  } catch (error) {
699
788
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -755,7 +844,7 @@ DebugController = _ts_decorate4([
755
844
  ], DebugController);
756
845
 
757
846
  // src/controllers/webhook.controller.ts
758
- import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2, HttpException as HttpException2, HttpStatus as HttpStatus2 } from "@nestjs/common";
847
+ import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2, HttpException as HttpException2, HttpStatus as HttpStatus2, Logger as Logger4 } from "@nestjs/common";
759
848
  function _ts_decorate5(decorators, target, key, desc) {
760
849
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
761
850
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -773,11 +862,12 @@ function _ts_param3(paramIndex, decorator) {
773
862
  };
774
863
  }
775
864
  __name(_ts_param3, "_ts_param");
776
- var WebhookController = class {
865
+ var WebhookController = class _WebhookController {
777
866
  static {
778
867
  __name(this, "WebhookController");
779
868
  }
780
869
  capabilityService;
870
+ logger = new Logger4(_WebhookController.name);
781
871
  constructor(capabilityService) {
782
872
  this.capabilityService = capabilityService;
783
873
  }
@@ -830,43 +920,62 @@ var WebhookController = class {
830
920
  }
831
921
  }
832
922
  async executeStream(capabilityId, body, res) {
923
+ const loggerContext = {
924
+ capability_id: capabilityId,
925
+ action: body.action
926
+ };
833
927
  res.setHeader("Content-Type", "text/event-stream");
834
928
  res.setHeader("Cache-Control", "no-cache");
835
929
  res.setHeader("Connection", "keep-alive");
836
930
  try {
931
+ this.logger.log(`Executing capability (stream)`, {
932
+ ...loggerContext,
933
+ input: stringifyForLog(body.params)
934
+ });
837
935
  const capability = this.capabilityService.load(capabilityId);
838
936
  const eventStream = capability.callStreamWithEvents(body.action, body.params);
937
+ let pendingChunk = null;
839
938
  for await (const event of eventStream) {
840
939
  switch (event.type) {
841
940
  case "data": {
842
- const response = {
843
- status_code: ErrorCodes.SUCCESS,
844
- data: {
845
- type: "content",
846
- delta: {
847
- content: event.data
941
+ if (pendingChunk !== null) {
942
+ const response = {
943
+ status_code: ErrorCodes.SUCCESS,
944
+ data: {
945
+ type: "content",
946
+ delta: {
947
+ content: pendingChunk
948
+ }
848
949
  }
849
- }
850
- };
851
- res.write(`data: ${JSON.stringify(response)}
950
+ };
951
+ res.write(`data: ${JSON.stringify(response)}
852
952
 
853
953
  `);
954
+ }
955
+ pendingChunk = event.data;
854
956
  break;
855
957
  }
856
958
  case "done": {
857
- const response = {
858
- status_code: ErrorCodes.SUCCESS,
859
- data: {
860
- type: "content",
861
- delta: {
862
- content: null
863
- },
864
- finished: true
865
- }
866
- };
867
- res.write(`data: ${JSON.stringify(response)}
959
+ if (pendingChunk !== null) {
960
+ const response = {
961
+ status_code: ErrorCodes.SUCCESS,
962
+ data: {
963
+ type: "content",
964
+ delta: {
965
+ content: pendingChunk
966
+ },
967
+ finished: true
968
+ }
969
+ };
970
+ res.write(`data: ${JSON.stringify(response)}
868
971
 
869
972
  `);
973
+ }
974
+ this.logger.log(`Capability (stream) executed successfully`, {
975
+ ...loggerContext,
976
+ duration_ms: event.metadata.duration,
977
+ output: stringifyForLog(event.metadata.aggregated)
978
+ });
870
979
  res.end();
871
980
  return;
872
981
  }
@@ -889,6 +998,21 @@ var WebhookController = class {
889
998
  }
890
999
  }
891
1000
  }
1001
+ if (pendingChunk !== null) {
1002
+ const response = {
1003
+ status_code: ErrorCodes.SUCCESS,
1004
+ data: {
1005
+ type: "content",
1006
+ delta: {
1007
+ content: pendingChunk
1008
+ },
1009
+ finished: true
1010
+ }
1011
+ };
1012
+ res.write(`data: ${JSON.stringify(response)}
1013
+
1014
+ `);
1015
+ }
892
1016
  res.end();
893
1017
  } catch (error) {
894
1018
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -949,7 +1073,7 @@ WebhookController = _ts_decorate5([
949
1073
 
950
1074
  // src/capability.module.ts
951
1075
  import { Module } from "@nestjs/common";
952
- import { RequestContextService as RequestContextService2, PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT2 } from "@lark-apaas/nestjs-common";
1076
+ import { CommonModule, RequestContextService as RequestContextService2, PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT2 } from "@lark-apaas/nestjs-common";
953
1077
  function _ts_decorate6(decorators, target, key, desc) {
954
1078
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
955
1079
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -976,6 +1100,9 @@ var CapabilityModule = class _CapabilityModule {
976
1100
  static forRoot(options) {
977
1101
  return {
978
1102
  module: _CapabilityModule,
1103
+ imports: [
1104
+ CommonModule
1105
+ ],
979
1106
  controllers: getControllers(),
980
1107
  providers: [
981
1108
  {
@@ -1010,6 +1137,9 @@ var CapabilityModule = class _CapabilityModule {
1010
1137
  };
1011
1138
  CapabilityModule = _ts_decorate6([
1012
1139
  Module({
1140
+ imports: [
1141
+ CommonModule
1142
+ ],
1013
1143
  controllers: getControllers(),
1014
1144
  providers: [
1015
1145
  CapabilityService,