@rainbow-o23/n1 1.0.58 → 1.0.60
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/index.cjs +130 -17
- package/index.js +129 -18
- package/lib/pipeline/index.d.ts +1 -0
- package/lib/pipeline/pipeline-execution-context.d.ts +42 -0
- package/lib/pipeline/pipeline-step.d.ts +3 -7
- package/lib/pipeline/pipeline.d.ts +4 -13
- package/package.json +1 -1
- package/src/lib/pipeline/index.ts +1 -0
- package/src/lib/pipeline/pipeline-execution-context.ts +166 -0
- package/src/lib/pipeline/pipeline-step.ts +3 -8
- package/src/lib/pipeline/pipeline.ts +22 -36
package/index.cjs
CHANGED
|
@@ -399,7 +399,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
399
399
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
400
400
|
PERFORMANCE OF THIS SOFTWARE.
|
|
401
401
|
***************************************************************************** */
|
|
402
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
402
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
403
403
|
|
|
404
404
|
|
|
405
405
|
function __decorate(decorators, target, key, desc) {
|
|
@@ -604,6 +604,115 @@ class AbstractPipelineExecution {
|
|
|
604
604
|
}
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
+
class PipelineExecutionContext {
|
|
608
|
+
_authorization;
|
|
609
|
+
_traceId;
|
|
610
|
+
_scopedTraceIds;
|
|
611
|
+
_others = {};
|
|
612
|
+
constructor(authorization, traceId, scopedTraceIds) {
|
|
613
|
+
this._authorization = authorization;
|
|
614
|
+
this._traceId = traceId || nanoid.nanoid(16);
|
|
615
|
+
this._scopedTraceIds = scopedTraceIds || {};
|
|
616
|
+
}
|
|
617
|
+
get authorization() {
|
|
618
|
+
return this._authorization;
|
|
619
|
+
}
|
|
620
|
+
get traceId() {
|
|
621
|
+
return this._traceId;
|
|
622
|
+
}
|
|
623
|
+
get scopedTraceIds() {
|
|
624
|
+
return Object.values(this._scopedTraceIds).reduce((acc, [name, value]) => {
|
|
625
|
+
if (value != null && value.trim().length !== 0) {
|
|
626
|
+
acc[name] = value;
|
|
627
|
+
}
|
|
628
|
+
return acc;
|
|
629
|
+
}, {});
|
|
630
|
+
}
|
|
631
|
+
findScopedTraceId(scopeKey) {
|
|
632
|
+
return this._scopedTraceIds[scopeKey];
|
|
633
|
+
}
|
|
634
|
+
setScopedTraceId(scopeKey, name, value) {
|
|
635
|
+
this._scopedTraceIds[scopeKey] = [name, value];
|
|
636
|
+
}
|
|
637
|
+
findOther(key) {
|
|
638
|
+
return this._others[key];
|
|
639
|
+
}
|
|
640
|
+
setOther(key, value) {
|
|
641
|
+
this._others[key] = value;
|
|
642
|
+
}
|
|
643
|
+
shallowClone(...omittedKeys) {
|
|
644
|
+
const cloned = new PipelineExecutionContext(this.authorization, this.traceId, this._scopedTraceIds);
|
|
645
|
+
Object.keys(this._others).forEach(key => {
|
|
646
|
+
if (omittedKeys.includes(key)) {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
cloned.setOther(key, this.findOther(key));
|
|
650
|
+
});
|
|
651
|
+
return cloned;
|
|
652
|
+
}
|
|
653
|
+
clone(...omittedKeys) {
|
|
654
|
+
const cloned = new PipelineExecutionContext(this.authorization, this.traceId);
|
|
655
|
+
Object.keys(this._others).forEach(key => {
|
|
656
|
+
if (omittedKeys.includes(key)) {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
cloned.setOther(key, this.findOther(key));
|
|
660
|
+
});
|
|
661
|
+
return cloned;
|
|
662
|
+
}
|
|
663
|
+
temporaryWith(temporaryContext) {
|
|
664
|
+
return new TemporaryExecutionContext(this, temporaryContext);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
class TemporaryExecutionContext extends PipelineExecutionContext {
|
|
668
|
+
_parent;
|
|
669
|
+
_temporaryContext;
|
|
670
|
+
_temporaryKeys;
|
|
671
|
+
constructor(parent, temporaryContext) {
|
|
672
|
+
super();
|
|
673
|
+
this._parent = parent;
|
|
674
|
+
this._temporaryContext = temporaryContext ?? {};
|
|
675
|
+
this._temporaryKeys = Object.keys(this._temporaryContext);
|
|
676
|
+
}
|
|
677
|
+
get parent() {
|
|
678
|
+
return this._parent;
|
|
679
|
+
}
|
|
680
|
+
get authorization() {
|
|
681
|
+
return this.parent.authorization;
|
|
682
|
+
}
|
|
683
|
+
get traceId() {
|
|
684
|
+
return this.parent.traceId;
|
|
685
|
+
}
|
|
686
|
+
get scopedTraceIds() {
|
|
687
|
+
return this.parent.scopedTraceIds;
|
|
688
|
+
}
|
|
689
|
+
findScopedTraceId(scopeKey) {
|
|
690
|
+
return this.parent.findScopedTraceId(scopeKey);
|
|
691
|
+
}
|
|
692
|
+
setScopedTraceId(scopeKey, name, value) {
|
|
693
|
+
this.parent.setScopedTraceId(scopeKey, name, value);
|
|
694
|
+
}
|
|
695
|
+
get temporaryContext() {
|
|
696
|
+
return this._temporaryContext;
|
|
697
|
+
}
|
|
698
|
+
findOther(key) {
|
|
699
|
+
if (this._temporaryKeys.includes(key)) {
|
|
700
|
+
return this.temporaryContext[key];
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
return super.findOther(key);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
setOther(key, value) {
|
|
707
|
+
if (this._temporaryKeys.includes(key)) {
|
|
708
|
+
this.temporaryContext[key] = value;
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
super.setOther(key, value);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
607
716
|
class PipelineStepDateHelper {
|
|
608
717
|
_dateTimeFormat;
|
|
609
718
|
constructor(config) {
|
|
@@ -704,24 +813,28 @@ class AbstractPipeline extends AbstractPipelineExecution {
|
|
|
704
813
|
const options = this.buildStepOptions();
|
|
705
814
|
return await Promise.all(this.getStepBuilders().map(async (builder) => await builder.create(options)));
|
|
706
815
|
}
|
|
816
|
+
defendPipelineRequest(request) {
|
|
817
|
+
if (request.$context == null) {
|
|
818
|
+
request.$context = new PipelineExecutionContext();
|
|
819
|
+
}
|
|
820
|
+
return request;
|
|
821
|
+
}
|
|
707
822
|
convertRequestToPipelineData(request) {
|
|
708
|
-
return {
|
|
823
|
+
return {
|
|
824
|
+
content: request.payload,
|
|
825
|
+
$context: request.$context
|
|
826
|
+
};
|
|
709
827
|
}
|
|
710
828
|
convertPipelineDataToResponse(result) {
|
|
711
|
-
return {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
if (traceId == null || traceId.trim().length === 0) {
|
|
716
|
-
return nanoid.nanoid(16);
|
|
717
|
-
}
|
|
718
|
-
else {
|
|
719
|
-
return traceId;
|
|
720
|
-
}
|
|
829
|
+
return {
|
|
830
|
+
payload: result.content,
|
|
831
|
+
$context: result.$context
|
|
832
|
+
};
|
|
721
833
|
}
|
|
722
834
|
async perform(request) {
|
|
723
|
-
|
|
724
|
-
const
|
|
835
|
+
request = this.defendPipelineRequest(request);
|
|
836
|
+
const $context = request.$context;
|
|
837
|
+
const traceId = $context.traceId;
|
|
725
838
|
const response = await this.measurePerformance(traceId, 'PIPELINE')
|
|
726
839
|
.execute(async () => {
|
|
727
840
|
this.traceRequest(traceId, request);
|
|
@@ -731,9 +844,7 @@ class AbstractPipeline extends AbstractPipelineExecution {
|
|
|
731
844
|
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
732
845
|
.execute(async () => {
|
|
733
846
|
this.traceStepIn(traceId, step, request);
|
|
734
|
-
const response = await step.perform({
|
|
735
|
-
...request, $context: { ...request.$context, authorization, traceId }
|
|
736
|
-
});
|
|
847
|
+
const response = await step.perform({ ...request, $context });
|
|
737
848
|
this.traceStepOut(traceId, step, response);
|
|
738
849
|
return this.returnOrContinueOrClear(request, response);
|
|
739
850
|
});
|
|
@@ -818,8 +929,10 @@ exports.LoggerUtils = LoggerUtils;
|
|
|
818
929
|
exports.PIPELINE_STEP_FILE_SYMBOL = PIPELINE_STEP_FILE_SYMBOL;
|
|
819
930
|
exports.PIPELINE_STEP_RETURN_NULL = PIPELINE_STEP_RETURN_NULL;
|
|
820
931
|
exports.PerformanceExecution = PerformanceExecution;
|
|
932
|
+
exports.PipelineExecutionContext = PipelineExecutionContext;
|
|
821
933
|
exports.PipelineRepository = PipelineRepository;
|
|
822
934
|
exports.PipelineStepDateHelper = PipelineStepDateHelper;
|
|
935
|
+
exports.TemporaryExecutionContext = TemporaryExecutionContext;
|
|
823
936
|
exports.UncatchableError = UncatchableError;
|
|
824
937
|
exports.createConfig = createConfig;
|
|
825
938
|
exports.createLogger = createLogger;
|
package/index.js
CHANGED
|
@@ -397,7 +397,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
397
397
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
398
398
|
PERFORMANCE OF THIS SOFTWARE.
|
|
399
399
|
***************************************************************************** */
|
|
400
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
400
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
401
401
|
|
|
402
402
|
|
|
403
403
|
function __decorate(decorators, target, key, desc) {
|
|
@@ -602,6 +602,115 @@ class AbstractPipelineExecution {
|
|
|
602
602
|
}
|
|
603
603
|
}
|
|
604
604
|
|
|
605
|
+
class PipelineExecutionContext {
|
|
606
|
+
_authorization;
|
|
607
|
+
_traceId;
|
|
608
|
+
_scopedTraceIds;
|
|
609
|
+
_others = {};
|
|
610
|
+
constructor(authorization, traceId, scopedTraceIds) {
|
|
611
|
+
this._authorization = authorization;
|
|
612
|
+
this._traceId = traceId || nanoid(16);
|
|
613
|
+
this._scopedTraceIds = scopedTraceIds || {};
|
|
614
|
+
}
|
|
615
|
+
get authorization() {
|
|
616
|
+
return this._authorization;
|
|
617
|
+
}
|
|
618
|
+
get traceId() {
|
|
619
|
+
return this._traceId;
|
|
620
|
+
}
|
|
621
|
+
get scopedTraceIds() {
|
|
622
|
+
return Object.values(this._scopedTraceIds).reduce((acc, [name, value]) => {
|
|
623
|
+
if (value != null && value.trim().length !== 0) {
|
|
624
|
+
acc[name] = value;
|
|
625
|
+
}
|
|
626
|
+
return acc;
|
|
627
|
+
}, {});
|
|
628
|
+
}
|
|
629
|
+
findScopedTraceId(scopeKey) {
|
|
630
|
+
return this._scopedTraceIds[scopeKey];
|
|
631
|
+
}
|
|
632
|
+
setScopedTraceId(scopeKey, name, value) {
|
|
633
|
+
this._scopedTraceIds[scopeKey] = [name, value];
|
|
634
|
+
}
|
|
635
|
+
findOther(key) {
|
|
636
|
+
return this._others[key];
|
|
637
|
+
}
|
|
638
|
+
setOther(key, value) {
|
|
639
|
+
this._others[key] = value;
|
|
640
|
+
}
|
|
641
|
+
shallowClone(...omittedKeys) {
|
|
642
|
+
const cloned = new PipelineExecutionContext(this.authorization, this.traceId, this._scopedTraceIds);
|
|
643
|
+
Object.keys(this._others).forEach(key => {
|
|
644
|
+
if (omittedKeys.includes(key)) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
cloned.setOther(key, this.findOther(key));
|
|
648
|
+
});
|
|
649
|
+
return cloned;
|
|
650
|
+
}
|
|
651
|
+
clone(...omittedKeys) {
|
|
652
|
+
const cloned = new PipelineExecutionContext(this.authorization, this.traceId);
|
|
653
|
+
Object.keys(this._others).forEach(key => {
|
|
654
|
+
if (omittedKeys.includes(key)) {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
cloned.setOther(key, this.findOther(key));
|
|
658
|
+
});
|
|
659
|
+
return cloned;
|
|
660
|
+
}
|
|
661
|
+
temporaryWith(temporaryContext) {
|
|
662
|
+
return new TemporaryExecutionContext(this, temporaryContext);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
class TemporaryExecutionContext extends PipelineExecutionContext {
|
|
666
|
+
_parent;
|
|
667
|
+
_temporaryContext;
|
|
668
|
+
_temporaryKeys;
|
|
669
|
+
constructor(parent, temporaryContext) {
|
|
670
|
+
super();
|
|
671
|
+
this._parent = parent;
|
|
672
|
+
this._temporaryContext = temporaryContext ?? {};
|
|
673
|
+
this._temporaryKeys = Object.keys(this._temporaryContext);
|
|
674
|
+
}
|
|
675
|
+
get parent() {
|
|
676
|
+
return this._parent;
|
|
677
|
+
}
|
|
678
|
+
get authorization() {
|
|
679
|
+
return this.parent.authorization;
|
|
680
|
+
}
|
|
681
|
+
get traceId() {
|
|
682
|
+
return this.parent.traceId;
|
|
683
|
+
}
|
|
684
|
+
get scopedTraceIds() {
|
|
685
|
+
return this.parent.scopedTraceIds;
|
|
686
|
+
}
|
|
687
|
+
findScopedTraceId(scopeKey) {
|
|
688
|
+
return this.parent.findScopedTraceId(scopeKey);
|
|
689
|
+
}
|
|
690
|
+
setScopedTraceId(scopeKey, name, value) {
|
|
691
|
+
this.parent.setScopedTraceId(scopeKey, name, value);
|
|
692
|
+
}
|
|
693
|
+
get temporaryContext() {
|
|
694
|
+
return this._temporaryContext;
|
|
695
|
+
}
|
|
696
|
+
findOther(key) {
|
|
697
|
+
if (this._temporaryKeys.includes(key)) {
|
|
698
|
+
return this.temporaryContext[key];
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
return super.findOther(key);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
setOther(key, value) {
|
|
705
|
+
if (this._temporaryKeys.includes(key)) {
|
|
706
|
+
this.temporaryContext[key] = value;
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
super.setOther(key, value);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
605
714
|
class PipelineStepDateHelper {
|
|
606
715
|
_dateTimeFormat;
|
|
607
716
|
constructor(config) {
|
|
@@ -702,24 +811,28 @@ class AbstractPipeline extends AbstractPipelineExecution {
|
|
|
702
811
|
const options = this.buildStepOptions();
|
|
703
812
|
return await Promise.all(this.getStepBuilders().map(async (builder) => await builder.create(options)));
|
|
704
813
|
}
|
|
814
|
+
defendPipelineRequest(request) {
|
|
815
|
+
if (request.$context == null) {
|
|
816
|
+
request.$context = new PipelineExecutionContext();
|
|
817
|
+
}
|
|
818
|
+
return request;
|
|
819
|
+
}
|
|
705
820
|
convertRequestToPipelineData(request) {
|
|
706
|
-
return {
|
|
821
|
+
return {
|
|
822
|
+
content: request.payload,
|
|
823
|
+
$context: request.$context
|
|
824
|
+
};
|
|
707
825
|
}
|
|
708
826
|
convertPipelineDataToResponse(result) {
|
|
709
|
-
return {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (traceId == null || traceId.trim().length === 0) {
|
|
714
|
-
return nanoid(16);
|
|
715
|
-
}
|
|
716
|
-
else {
|
|
717
|
-
return traceId;
|
|
718
|
-
}
|
|
827
|
+
return {
|
|
828
|
+
payload: result.content,
|
|
829
|
+
$context: result.$context
|
|
830
|
+
};
|
|
719
831
|
}
|
|
720
832
|
async perform(request) {
|
|
721
|
-
|
|
722
|
-
const
|
|
833
|
+
request = this.defendPipelineRequest(request);
|
|
834
|
+
const $context = request.$context;
|
|
835
|
+
const traceId = $context.traceId;
|
|
723
836
|
const response = await this.measurePerformance(traceId, 'PIPELINE')
|
|
724
837
|
.execute(async () => {
|
|
725
838
|
this.traceRequest(traceId, request);
|
|
@@ -729,9 +842,7 @@ class AbstractPipeline extends AbstractPipelineExecution {
|
|
|
729
842
|
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
730
843
|
.execute(async () => {
|
|
731
844
|
this.traceStepIn(traceId, step, request);
|
|
732
|
-
const response = await step.perform({
|
|
733
|
-
...request, $context: { ...request.$context, authorization, traceId }
|
|
734
|
-
});
|
|
845
|
+
const response = await step.perform({ ...request, $context });
|
|
735
846
|
this.traceStepOut(traceId, step, response);
|
|
736
847
|
return this.returnOrContinueOrClear(request, response);
|
|
737
848
|
});
|
|
@@ -795,4 +906,4 @@ class PipelineRepository {
|
|
|
795
906
|
}
|
|
796
907
|
}
|
|
797
908
|
|
|
798
|
-
export { AbstractPipeline, AbstractPipelineExecution, AbstractPipelineStep, AbstractStaticPipeline, CatchableError, Config, ConsoleLogger, DefaultPipelineBuilder, DefaultPipelineStepBuilder, ERR_DUPLICATED_ERROR_CODE, ERR_PIPELINE_NOT_FOUND, ERR_TRIM_NON_STRING, ERR_UNKNOWN, EnhancedLogger, ErrorCodes, ExposedUncatchableError, LoggerPerformanceSaver, LoggerUtils, PIPELINE_STEP_FILE_SYMBOL, PIPELINE_STEP_RETURN_NULL, PerformanceExecution, PipelineRepository, PipelineStepDateHelper, StepHelpersUtils, UncatchableError, createConfig, createLogger, createStepHelpers, registerToStepHelpers, saveLoggerPerformance };
|
|
909
|
+
export { AbstractPipeline, AbstractPipelineExecution, AbstractPipelineStep, AbstractStaticPipeline, CatchableError, Config, ConsoleLogger, DefaultPipelineBuilder, DefaultPipelineStepBuilder, ERR_DUPLICATED_ERROR_CODE, ERR_PIPELINE_NOT_FOUND, ERR_TRIM_NON_STRING, ERR_UNKNOWN, EnhancedLogger, ErrorCodes, ExposedUncatchableError, LoggerPerformanceSaver, LoggerUtils, PIPELINE_STEP_FILE_SYMBOL, PIPELINE_STEP_RETURN_NULL, PerformanceExecution, PipelineExecutionContext, PipelineRepository, PipelineStepDateHelper, StepHelpersUtils, TemporaryExecutionContext, UncatchableError, createConfig, createLogger, createStepHelpers, registerToStepHelpers, saveLoggerPerformance };
|
package/lib/pipeline/index.d.ts
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface PipelineRequestAuthorizationRole {
|
|
2
|
+
code?: string;
|
|
3
|
+
[key: string]: any | undefined;
|
|
4
|
+
}
|
|
5
|
+
export interface PipelineRequestAuthorization<A = any> {
|
|
6
|
+
readonly authorized: boolean;
|
|
7
|
+
readonly authentication?: A;
|
|
8
|
+
readonly roles: Array<PipelineRequestAuthorizationRole>;
|
|
9
|
+
readonly headers?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export declare class PipelineExecutionContext {
|
|
12
|
+
private readonly _authorization?;
|
|
13
|
+
private readonly _traceId;
|
|
14
|
+
private readonly _scopedTraceIds;
|
|
15
|
+
private readonly _others;
|
|
16
|
+
constructor(authorization?: PipelineRequestAuthorization, traceId?: string, scopedTraceIds?: Record<string, [string, string]>);
|
|
17
|
+
get authorization(): PipelineRequestAuthorization;
|
|
18
|
+
get traceId(): string;
|
|
19
|
+
get scopedTraceIds(): Record<string, string>;
|
|
20
|
+
findScopedTraceId(scopeKey: string): [string, string] | undefined;
|
|
21
|
+
setScopedTraceId(scopeKey: string, name: string, value: string): void;
|
|
22
|
+
findOther(key: string): any | undefined;
|
|
23
|
+
setOther(key: string, value: any): void;
|
|
24
|
+
shallowClone(...omittedKeys: Array<string>): PipelineExecutionContext;
|
|
25
|
+
clone(...omittedKeys: Array<string>): PipelineExecutionContext;
|
|
26
|
+
temporaryWith(temporaryContext: Record<string, any>): PipelineExecutionContext;
|
|
27
|
+
}
|
|
28
|
+
export declare class TemporaryExecutionContext extends PipelineExecutionContext {
|
|
29
|
+
private readonly _parent;
|
|
30
|
+
private readonly _temporaryContext;
|
|
31
|
+
private readonly _temporaryKeys;
|
|
32
|
+
constructor(parent: PipelineExecutionContext, temporaryContext: Record<string, any>);
|
|
33
|
+
protected get parent(): PipelineExecutionContext;
|
|
34
|
+
get authorization(): PipelineRequestAuthorization;
|
|
35
|
+
get traceId(): string;
|
|
36
|
+
get scopedTraceIds(): Record<string, string>;
|
|
37
|
+
findScopedTraceId(scopeKey: string): [string, string] | undefined;
|
|
38
|
+
setScopedTraceId(scopeKey: string, name: string, value: string): void;
|
|
39
|
+
get temporaryContext(): Record<string, any>;
|
|
40
|
+
findOther(key: string): any;
|
|
41
|
+
setOther(key: string, value: any): void;
|
|
42
|
+
}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { Config, Logger } from '../utils';
|
|
2
|
-
import { PipelineRequestAuthorization } from './pipeline';
|
|
3
2
|
import { AbstractPipelineExecution, PipelineExecutionOptions } from './pipeline-execution';
|
|
3
|
+
import { PipelineExecutionContext } from './pipeline-execution-context';
|
|
4
4
|
import { PipelineStepHelpers } from './step-helpers';
|
|
5
5
|
export type PipelineStepCode = string;
|
|
6
6
|
export type PipelineStepPayload = any;
|
|
7
|
-
export interface
|
|
8
|
-
|
|
9
|
-
traceId?: string;
|
|
10
|
-
}
|
|
11
|
-
export interface PipelineStepData<C = PipelineStepPayload, CTX = PipelineStepContext> {
|
|
12
|
-
$context?: CTX;
|
|
7
|
+
export interface PipelineStepData<C = PipelineStepPayload, CTX = PipelineExecutionContext> {
|
|
8
|
+
$context: CTX;
|
|
13
9
|
content: C;
|
|
14
10
|
}
|
|
15
11
|
export interface PipelineStep<In = any, Out = any> {
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import { Config, Logger } from '../utils';
|
|
2
2
|
import { AbstractPipelineExecution, PipelineExecutionOptions } from './pipeline-execution';
|
|
3
|
+
import { PipelineExecutionContext } from './pipeline-execution-context';
|
|
3
4
|
import { PipelineStep, PipelineStepBuilder, PipelineStepData, PipelineStepOptions, PipelineStepType } from './pipeline-step';
|
|
4
5
|
export type PipelineRequestPayload = any;
|
|
5
|
-
export interface PipelineRequestAuthorizationRole {
|
|
6
|
-
code?: string;
|
|
7
|
-
[key: string]: any | undefined;
|
|
8
|
-
}
|
|
9
|
-
export interface PipelineRequestAuthorization<A = any> {
|
|
10
|
-
readonly authorized: boolean;
|
|
11
|
-
readonly authentication?: A;
|
|
12
|
-
readonly roles: Array<PipelineRequestAuthorizationRole>;
|
|
13
|
-
readonly headers?: Record<string, string>;
|
|
14
|
-
}
|
|
15
6
|
export interface PipelineRequest<C = PipelineRequestPayload> {
|
|
16
7
|
payload: C;
|
|
17
|
-
|
|
18
|
-
traceId?: string;
|
|
8
|
+
$context?: PipelineExecutionContext;
|
|
19
9
|
}
|
|
20
10
|
export type PipelineResponsePayload = any;
|
|
21
11
|
export interface PipelineResponse<C = PipelineResponsePayload> {
|
|
22
12
|
payload: C;
|
|
13
|
+
$context: PipelineExecutionContext;
|
|
23
14
|
}
|
|
24
15
|
export type PipelineCode = string;
|
|
25
16
|
export interface Pipeline<In = any, Out = any> {
|
|
@@ -39,9 +30,9 @@ export declare abstract class AbstractPipeline<In = any, Out = any> extends Abst
|
|
|
39
30
|
protected abstract getStepBuilders(): Array<PipelineStepBuilder>;
|
|
40
31
|
protected buildStepOptions(): Pick<PipelineStepOptions, 'config' | 'logger'>;
|
|
41
32
|
createSteps(): Promise<Array<PipelineStep>>;
|
|
33
|
+
protected defendPipelineRequest(request: PipelineRequest<In>): Required<PipelineRequest<In>>;
|
|
42
34
|
convertRequestToPipelineData<I, FirstStepIn>(request: PipelineRequest<I>): PipelineStepData<FirstStepIn>;
|
|
43
35
|
convertPipelineDataToResponse<LastStepOut, O>(result: PipelineStepData<LastStepOut>): PipelineResponse<O>;
|
|
44
|
-
protected createTraceId(request: PipelineRequest<In>): string;
|
|
45
36
|
perform(request: PipelineRequest<In>): Promise<PipelineResponse<Out>>;
|
|
46
37
|
}
|
|
47
38
|
export declare abstract class AbstractStaticPipeline<In = any, Out = any> extends AbstractPipeline<In, Out> {
|
package/package.json
CHANGED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import {nanoid} from 'nanoid';
|
|
2
|
+
|
|
3
|
+
export interface PipelineRequestAuthorizationRole {
|
|
4
|
+
code?: string;
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
[key: string]: any | undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export interface PipelineRequestAuthorization<A = any> {
|
|
11
|
+
readonly authorized: boolean;
|
|
12
|
+
/** undefined when authorized is false */
|
|
13
|
+
readonly authentication?: A;
|
|
14
|
+
/** empty array when authorized is false */
|
|
15
|
+
readonly roles: Array<PipelineRequestAuthorizationRole>;
|
|
16
|
+
/** headers should be added to response */
|
|
17
|
+
readonly headers?: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class PipelineExecutionContext {
|
|
21
|
+
private readonly _authorization?: PipelineRequestAuthorization;
|
|
22
|
+
private readonly _traceId: string;
|
|
23
|
+
/*
|
|
24
|
+
* typically, when calling a remote service, and which is from some microservices group,
|
|
25
|
+
* there might be some trace ids brought in.
|
|
26
|
+
* therefore, these trace ids should be collected and put into pipeline context.
|
|
27
|
+
* the key is tracing group, and value is trace id of this tracing group.
|
|
28
|
+
* Record<scope key, [name, value]>
|
|
29
|
+
*/
|
|
30
|
+
private readonly _scopedTraceIds: Record<string, [string, string]>;
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
private readonly _others: Record<string, any> = {};
|
|
33
|
+
|
|
34
|
+
constructor(authorization?: PipelineRequestAuthorization, traceId?: string, scopedTraceIds?: Record<string, [string, string]>) {
|
|
35
|
+
this._authorization = authorization;
|
|
36
|
+
this._traceId = traceId || nanoid(16);
|
|
37
|
+
this._scopedTraceIds = scopedTraceIds || {};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get authorization(): PipelineRequestAuthorization {
|
|
41
|
+
return this._authorization;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get traceId(): string {
|
|
45
|
+
return this._traceId;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get scopedTraceIds(): Record<string, string> {
|
|
49
|
+
return Object.values(this._scopedTraceIds).reduce((acc, [name, value]) => {
|
|
50
|
+
if (value != null && value.trim().length !== 0) {
|
|
51
|
+
acc[name] = value;
|
|
52
|
+
}
|
|
53
|
+
return acc;
|
|
54
|
+
}, {});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
findScopedTraceId(scopeKey: string): [string, string] | undefined {
|
|
58
|
+
return this._scopedTraceIds[scopeKey];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setScopedTraceId(scopeKey: string, name: string, value: string): void {
|
|
62
|
+
this._scopedTraceIds[scopeKey] = [name, value];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
findOther(key: string): any | undefined {
|
|
67
|
+
return this._others[key];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
+
setOther(key: string, value: any): void {
|
|
72
|
+
this._others[key] = value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
shallowClone(...omittedKeys: Array<string>): PipelineExecutionContext {
|
|
76
|
+
const cloned = new PipelineExecutionContext(this.authorization, this.traceId, this._scopedTraceIds);
|
|
77
|
+
Object.keys(this._others).forEach(key => {
|
|
78
|
+
if (omittedKeys.includes(key)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
cloned.setOther(key, this.findOther(key));
|
|
82
|
+
});
|
|
83
|
+
return cloned;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
clone(...omittedKeys: Array<string>): PipelineExecutionContext {
|
|
87
|
+
const cloned = new PipelineExecutionContext(this.authorization, this.traceId);
|
|
88
|
+
Object.keys(this._others).forEach(key => {
|
|
89
|
+
if (omittedKeys.includes(key)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
cloned.setOther(key, this.findOther(key));
|
|
93
|
+
});
|
|
94
|
+
return cloned;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
|
+
temporaryWith(temporaryContext: Record<string, any>): PipelineExecutionContext {
|
|
99
|
+
return new TemporaryExecutionContext(this, temporaryContext);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* everything same as parent context, except things in given temporary context
|
|
105
|
+
*/
|
|
106
|
+
export class TemporaryExecutionContext extends PipelineExecutionContext {
|
|
107
|
+
private readonly _parent: PipelineExecutionContext;
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
|
+
private readonly _temporaryContext: Record<string, any>;
|
|
110
|
+
private readonly _temporaryKeys: Array<string>;
|
|
111
|
+
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
113
|
+
constructor(parent: PipelineExecutionContext, temporaryContext: Record<string, any>) {
|
|
114
|
+
super();
|
|
115
|
+
this._parent = parent;
|
|
116
|
+
this._temporaryContext = temporaryContext ?? {};
|
|
117
|
+
this._temporaryKeys = Object.keys(this._temporaryContext);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
protected get parent(): PipelineExecutionContext {
|
|
121
|
+
return this._parent;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get authorization(): PipelineRequestAuthorization {
|
|
125
|
+
return this.parent.authorization;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
get traceId(): string {
|
|
129
|
+
return this.parent.traceId;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get scopedTraceIds(): Record<string, string> {
|
|
133
|
+
return this.parent.scopedTraceIds;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
findScopedTraceId(scopeKey: string): [string, string] | undefined {
|
|
137
|
+
return this.parent.findScopedTraceId(scopeKey);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
setScopedTraceId(scopeKey: string, name: string, value: string) {
|
|
141
|
+
this.parent.setScopedTraceId(scopeKey, name, value);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
145
|
+
get temporaryContext(): Record<string, any> {
|
|
146
|
+
return this._temporaryContext;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
150
|
+
findOther(key: string): any {
|
|
151
|
+
if (this._temporaryKeys.includes(key)) {
|
|
152
|
+
return this.temporaryContext[key];
|
|
153
|
+
} else {
|
|
154
|
+
return super.findOther(key);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
159
|
+
setOther(key: string, value: any) {
|
|
160
|
+
if (this._temporaryKeys.includes(key)) {
|
|
161
|
+
this.temporaryContext[key] = value;
|
|
162
|
+
} else {
|
|
163
|
+
super.setOther(key, value);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Config, Logger} from '../utils';
|
|
2
|
-
import {PipelineRequestAuthorization} from './pipeline';
|
|
3
2
|
import {AbstractPipelineExecution, PipelineExecutionOptions} from './pipeline-execution';
|
|
3
|
+
import {PipelineExecutionContext} from './pipeline-execution-context';
|
|
4
4
|
import {createStepHelpers, PipelineStepHelpers} from './step-helpers';
|
|
5
5
|
|
|
6
6
|
export type PipelineStepCode = string;
|
|
@@ -8,14 +8,9 @@ export type PipelineStepCode = string;
|
|
|
8
8
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
9
|
export type PipelineStepPayload = any;
|
|
10
10
|
|
|
11
|
-
export interface
|
|
12
|
-
authorization?: PipelineRequestAuthorization;
|
|
13
|
-
traceId?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface PipelineStepData<C = PipelineStepPayload, CTX = PipelineStepContext> {
|
|
11
|
+
export interface PipelineStepData<C = PipelineStepPayload, CTX = PipelineExecutionContext> {
|
|
17
12
|
/** this is runtime context */
|
|
18
|
-
$context
|
|
13
|
+
$context: CTX;
|
|
19
14
|
content: C;
|
|
20
15
|
}
|
|
21
16
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {nanoid} from 'nanoid';
|
|
2
1
|
import {Config, Logger} from '../utils';
|
|
3
2
|
import {AbstractPipelineExecution, PipelineExecutionOptions} from './pipeline-execution';
|
|
3
|
+
import {PipelineExecutionContext} from './pipeline-execution-context';
|
|
4
4
|
import {
|
|
5
5
|
DefaultPipelineStepBuilder,
|
|
6
6
|
PipelineStep,
|
|
@@ -13,27 +13,9 @@ import {
|
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
14
|
export type PipelineRequestPayload = any;
|
|
15
15
|
|
|
16
|
-
export interface PipelineRequestAuthorizationRole {
|
|
17
|
-
code?: string;
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
-
[key: string]: any | undefined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
export interface PipelineRequestAuthorization<A = any> {
|
|
24
|
-
readonly authorized: boolean;
|
|
25
|
-
/** undefined when authorized is false */
|
|
26
|
-
readonly authentication?: A;
|
|
27
|
-
/** empty array when authorized is false */
|
|
28
|
-
readonly roles: Array<PipelineRequestAuthorizationRole>;
|
|
29
|
-
/** headers should be added to response */
|
|
30
|
-
readonly headers?: Record<string, string>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
16
|
export interface PipelineRequest<C = PipelineRequestPayload> {
|
|
34
17
|
payload: C;
|
|
35
|
-
|
|
36
|
-
traceId?: string;
|
|
18
|
+
$context?: PipelineExecutionContext;
|
|
37
19
|
}
|
|
38
20
|
|
|
39
21
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -41,6 +23,7 @@ export type PipelineResponsePayload = any;
|
|
|
41
23
|
|
|
42
24
|
export interface PipelineResponse<C = PipelineResponsePayload> {
|
|
43
25
|
payload: C;
|
|
26
|
+
$context: PipelineExecutionContext;
|
|
44
27
|
}
|
|
45
28
|
|
|
46
29
|
export type PipelineCode = string;
|
|
@@ -94,21 +77,25 @@ export abstract class AbstractPipeline<In = any, Out = any> extends AbstractPipe
|
|
|
94
77
|
return await Promise.all(this.getStepBuilders().map(async builder => await builder.create(options)));
|
|
95
78
|
}
|
|
96
79
|
|
|
97
|
-
|
|
98
|
-
|
|
80
|
+
protected defendPipelineRequest(request: PipelineRequest<In>): Required<PipelineRequest<In>> {
|
|
81
|
+
if (request.$context == null) {
|
|
82
|
+
request.$context = new PipelineExecutionContext();
|
|
83
|
+
}
|
|
84
|
+
return request as Required<PipelineRequest<In>>;
|
|
99
85
|
}
|
|
100
86
|
|
|
101
|
-
public
|
|
102
|
-
return {
|
|
87
|
+
public convertRequestToPipelineData<I, FirstStepIn>(request: PipelineRequest<I>): PipelineStepData<FirstStepIn> {
|
|
88
|
+
return {
|
|
89
|
+
content: request.payload as unknown as FirstStepIn,
|
|
90
|
+
$context: request.$context
|
|
91
|
+
};
|
|
103
92
|
}
|
|
104
93
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
return traceId;
|
|
111
|
-
}
|
|
94
|
+
public convertPipelineDataToResponse<LastStepOut, O>(result: PipelineStepData<LastStepOut>): PipelineResponse<O> {
|
|
95
|
+
return {
|
|
96
|
+
payload: result.content as unknown as O,
|
|
97
|
+
$context: result.$context
|
|
98
|
+
};
|
|
112
99
|
}
|
|
113
100
|
|
|
114
101
|
/**
|
|
@@ -118,8 +105,9 @@ export abstract class AbstractPipeline<In = any, Out = any> extends AbstractPipe
|
|
|
118
105
|
* - use last step's result as response.
|
|
119
106
|
*/
|
|
120
107
|
public async perform(request: PipelineRequest<In>): Promise<PipelineResponse<Out>> {
|
|
121
|
-
|
|
122
|
-
const
|
|
108
|
+
request = this.defendPipelineRequest(request);
|
|
109
|
+
const $context = request.$context;
|
|
110
|
+
const traceId = $context.traceId;
|
|
123
111
|
const response = await this.measurePerformance(traceId, 'PIPELINE')
|
|
124
112
|
.execute(async () => {
|
|
125
113
|
this.traceRequest(traceId, request);
|
|
@@ -129,9 +117,7 @@ export abstract class AbstractPipeline<In = any, Out = any> extends AbstractPipe
|
|
|
129
117
|
return await this.measurePerformance(traceId, 'STEP', step.constructor.name)
|
|
130
118
|
.execute(async () => {
|
|
131
119
|
this.traceStepIn(traceId, step, request);
|
|
132
|
-
const response = await step.perform({
|
|
133
|
-
...request, $context: {...request.$context, authorization, traceId}
|
|
134
|
-
});
|
|
120
|
+
const response = await step.perform({...request, $context});
|
|
135
121
|
this.traceStepOut(traceId, step, response);
|
|
136
122
|
// if no response returned, keep using request for next
|
|
137
123
|
return this.returnOrContinueOrClear(request, response);
|