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

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,36 @@ 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
+ }
465
+ yield event;
466
+ }
429
467
  } else {
430
- const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
431
468
  if (isStream && pluginInstance.runStream) {
432
469
  for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
433
- chunkCount++;
470
+ chunks.push(chunk);
434
471
  yield {
435
472
  type: "data",
436
473
  data: chunk
@@ -438,7 +475,7 @@ var CapabilityService = class _CapabilityService {
438
475
  }
439
476
  } else {
440
477
  const result = await pluginInstance.run(actionName, context, resolvedParams);
441
- chunkCount = 1;
478
+ chunks.push(result);
442
479
  yield {
443
480
  type: "data",
444
481
  data: result
@@ -447,25 +484,22 @@ var CapabilityService = class _CapabilityService {
447
484
  yield {
448
485
  type: "done",
449
486
  metadata: {
450
- chunks: chunkCount,
487
+ chunks: chunks.length,
451
488
  duration: Date.now() - startTime
452
489
  }
453
490
  };
454
491
  }
455
- this.logger.log({
456
- message: "Capability streamWithEvents completed",
457
- capabilityId: config.id,
458
- action: actionName,
459
- duration: Date.now() - startTime,
460
- chunks: chunkCount
492
+ const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
493
+ this.logger.log("Capability (streamWithEvents) executed successfully", {
494
+ ...loggerContext,
495
+ duration_ms: Date.now() - startTime,
496
+ output: stringifyForLog(aggregatedResult)
461
497
  });
462
498
  } 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
499
+ this.logger.error("Capability (streamWithEvents) execution failed", {
500
+ ...loggerContext,
501
+ duration_ms: Date.now() - startTime,
502
+ error: error instanceof Error ? error.message : String(error)
469
503
  });
470
504
  yield {
471
505
  type: "error",
@@ -479,13 +513,14 @@ var CapabilityService = class _CapabilityService {
479
513
  buildActionContext(override) {
480
514
  return {
481
515
  logger: this.logger,
482
- httpClient: this.httpClient,
516
+ platformHttpClient: this.platformHttpClient,
483
517
  userContext: override?.userContext ?? this.getUserContext()
484
518
  };
485
519
  }
486
520
  getUserContext() {
487
521
  const ctx = this.requestContextService.getContext();
488
522
  return {
523
+ appId: ctx?.appId ?? "",
489
524
  userId: ctx?.userId ?? "",
490
525
  tenantId: ctx?.tenantId ?? ""
491
526
  };
@@ -504,7 +539,7 @@ CapabilityService = _ts_decorate3([
504
539
  ], CapabilityService);
505
540
 
506
541
  // src/controllers/debug.controller.ts
507
- import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus } from "@nestjs/common";
542
+ import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus, Logger as Logger3 } from "@nestjs/common";
508
543
  function _ts_decorate4(decorators, target, key, desc) {
509
544
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
510
545
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -522,13 +557,14 @@ function _ts_param2(paramIndex, decorator) {
522
557
  };
523
558
  }
524
559
  __name(_ts_param2, "_ts_param");
525
- var DebugController = class {
560
+ var DebugController = class _DebugController {
526
561
  static {
527
562
  __name(this, "DebugController");
528
563
  }
529
564
  capabilityService;
530
565
  pluginLoaderService;
531
566
  templateEngineService;
567
+ logger = new Logger3(_DebugController.name);
532
568
  constructor(capabilityService, pluginLoaderService, templateEngineService) {
533
569
  this.capabilityService = capabilityService;
534
570
  this.pluginLoaderService = pluginLoaderService;
@@ -633,45 +669,61 @@ var DebugController = class {
633
669
  }
634
670
  async debugStream(capabilityId, body, res) {
635
671
  const params = body.params ?? {};
672
+ const startTime = Date.now();
636
673
  res.setHeader("Content-Type", "text/event-stream");
637
674
  res.setHeader("Cache-Control", "no-cache");
638
675
  res.setHeader("Connection", "keep-alive");
639
676
  try {
640
677
  const config = this.getCapabilityConfig(capabilityId, body.capability);
641
678
  const action = await this.getActionName(config.pluginKey, body.action);
679
+ const loggerContext = {
680
+ capability_id: config.id,
681
+ plugin_key: config.pluginKey,
682
+ action
683
+ };
684
+ this.logger.log(`Executing capability (stream), input: ${stringifyForLog(params)}`, loggerContext);
642
685
  const capability = this.capabilityService.loadWithConfig(config);
643
686
  const eventStream = capability.callStreamWithEvents(action, params);
687
+ let pendingChunk = null;
688
+ const allChunks = [];
644
689
  for await (const event of eventStream) {
645
690
  switch (event.type) {
646
691
  case "data": {
647
- const response = {
648
- status_code: ErrorCodes.SUCCESS,
649
- data: {
650
- type: "content",
651
- delta: {
652
- content: event.data
692
+ allChunks.push(event.data);
693
+ if (pendingChunk !== null) {
694
+ const response = {
695
+ status_code: ErrorCodes.SUCCESS,
696
+ data: {
697
+ type: "content",
698
+ delta: {
699
+ content: pendingChunk
700
+ }
653
701
  }
654
- }
655
- };
656
- res.write(`data: ${JSON.stringify(response)}
702
+ };
703
+ res.write(`data: ${JSON.stringify(response)}
657
704
 
658
705
  `);
706
+ }
707
+ pendingChunk = event.data;
659
708
  break;
660
709
  }
661
710
  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)}
711
+ if (pendingChunk !== null) {
712
+ const response = {
713
+ status_code: ErrorCodes.SUCCESS,
714
+ data: {
715
+ type: "content",
716
+ delta: {
717
+ content: pendingChunk
718
+ },
719
+ finished: true
720
+ }
721
+ };
722
+ res.write(`data: ${JSON.stringify(response)}
673
723
 
674
724
  `);
725
+ }
726
+ this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
675
727
  res.end();
676
728
  return;
677
729
  }
@@ -694,6 +746,21 @@ var DebugController = class {
694
746
  }
695
747
  }
696
748
  }
749
+ if (pendingChunk !== null) {
750
+ const response = {
751
+ status_code: ErrorCodes.SUCCESS,
752
+ data: {
753
+ type: "content",
754
+ delta: {
755
+ content: pendingChunk
756
+ },
757
+ finished: true
758
+ }
759
+ };
760
+ res.write(`data: ${JSON.stringify(response)}
761
+
762
+ `);
763
+ }
697
764
  res.end();
698
765
  } catch (error) {
699
766
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -755,7 +822,7 @@ DebugController = _ts_decorate4([
755
822
  ], DebugController);
756
823
 
757
824
  // 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";
825
+ 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
826
  function _ts_decorate5(decorators, target, key, desc) {
760
827
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
761
828
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -773,11 +840,12 @@ function _ts_param3(paramIndex, decorator) {
773
840
  };
774
841
  }
775
842
  __name(_ts_param3, "_ts_param");
776
- var WebhookController = class {
843
+ var WebhookController = class _WebhookController {
777
844
  static {
778
845
  __name(this, "WebhookController");
779
846
  }
780
847
  capabilityService;
848
+ logger = new Logger4(_WebhookController.name);
781
849
  constructor(capabilityService) {
782
850
  this.capabilityService = capabilityService;
783
851
  }
@@ -830,43 +898,58 @@ var WebhookController = class {
830
898
  }
831
899
  }
832
900
  async executeStream(capabilityId, body, res) {
901
+ const startTime = Date.now();
902
+ const loggerContext = {
903
+ capability_id: capabilityId,
904
+ action: body.action
905
+ };
833
906
  res.setHeader("Content-Type", "text/event-stream");
834
907
  res.setHeader("Cache-Control", "no-cache");
835
908
  res.setHeader("Connection", "keep-alive");
836
909
  try {
910
+ this.logger.log(`Executing capability (stream), input: ${stringifyForLog(body.params)}`, loggerContext);
837
911
  const capability = this.capabilityService.load(capabilityId);
838
912
  const eventStream = capability.callStreamWithEvents(body.action, body.params);
913
+ let pendingChunk = null;
914
+ const allChunks = [];
839
915
  for await (const event of eventStream) {
840
916
  switch (event.type) {
841
917
  case "data": {
842
- const response = {
843
- status_code: ErrorCodes.SUCCESS,
844
- data: {
845
- type: "content",
846
- delta: {
847
- content: event.data
918
+ allChunks.push(event.data);
919
+ if (pendingChunk !== null) {
920
+ const response = {
921
+ status_code: ErrorCodes.SUCCESS,
922
+ data: {
923
+ type: "content",
924
+ delta: {
925
+ content: pendingChunk
926
+ }
848
927
  }
849
- }
850
- };
851
- res.write(`data: ${JSON.stringify(response)}
928
+ };
929
+ res.write(`data: ${JSON.stringify(response)}
852
930
 
853
931
  `);
932
+ }
933
+ pendingChunk = event.data;
854
934
  break;
855
935
  }
856
936
  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)}
937
+ if (pendingChunk !== null) {
938
+ const response = {
939
+ status_code: ErrorCodes.SUCCESS,
940
+ data: {
941
+ type: "content",
942
+ delta: {
943
+ content: pendingChunk
944
+ },
945
+ finished: true
946
+ }
947
+ };
948
+ res.write(`data: ${JSON.stringify(response)}
868
949
 
869
950
  `);
951
+ }
952
+ this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
870
953
  res.end();
871
954
  return;
872
955
  }
@@ -889,6 +972,22 @@ var WebhookController = class {
889
972
  }
890
973
  }
891
974
  }
975
+ if (pendingChunk !== null) {
976
+ const response = {
977
+ status_code: ErrorCodes.SUCCESS,
978
+ data: {
979
+ type: "content",
980
+ delta: {
981
+ content: pendingChunk
982
+ },
983
+ finished: true
984
+ }
985
+ };
986
+ res.write(`data: ${JSON.stringify(response)}
987
+
988
+ `);
989
+ }
990
+ this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
892
991
  res.end();
893
992
  } catch (error) {
894
993
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -949,7 +1048,7 @@ WebhookController = _ts_decorate5([
949
1048
 
950
1049
  // src/capability.module.ts
951
1050
  import { Module } from "@nestjs/common";
952
- import { RequestContextService as RequestContextService2, PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT2 } from "@lark-apaas/nestjs-common";
1051
+ import { CommonModule, RequestContextService as RequestContextService2, PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT2 } from "@lark-apaas/nestjs-common";
953
1052
  function _ts_decorate6(decorators, target, key, desc) {
954
1053
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
955
1054
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -976,6 +1075,9 @@ var CapabilityModule = class _CapabilityModule {
976
1075
  static forRoot(options) {
977
1076
  return {
978
1077
  module: _CapabilityModule,
1078
+ imports: [
1079
+ CommonModule
1080
+ ],
979
1081
  controllers: getControllers(),
980
1082
  providers: [
981
1083
  {
@@ -1010,6 +1112,9 @@ var CapabilityModule = class _CapabilityModule {
1010
1112
  };
1011
1113
  CapabilityModule = _ts_decorate6([
1012
1114
  Module({
1115
+ imports: [
1116
+ CommonModule
1117
+ ],
1013
1118
  controllers: getControllers(),
1014
1119
  providers: [
1015
1120
  CapabilityService,