@memberjunction/server 6.1.1 → 6.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/config.d.ts +6 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -4
- package/dist/config.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +49 -2
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +95 -16
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/realtimeConfigUnits.d.ts +21 -0
- package/dist/realtimeConfigUnits.d.ts.map +1 -0
- package/dist/realtimeConfigUnits.js +24 -0
- package/dist/realtimeConfigUnits.js.map +1 -0
- package/package.json +92 -92
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +30 -2
- package/src/__tests__/realtime-env-override.test.ts +34 -0
- package/src/config.ts +5 -4
- package/src/generic/RunViewResolver.ts +95 -15
- package/src/realtimeConfigUnits.ts +24 -0
|
@@ -768,8 +768,16 @@ export class RunViewResolver extends ResolverBase {
|
|
|
768
768
|
await this.CheckAPIKeyScopeAuthorization('view:run', input.ViewName, userPayload);
|
|
769
769
|
const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
|
|
770
770
|
const rawData = await super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
|
|
771
|
-
if (rawData === null)
|
|
772
|
-
return
|
|
771
|
+
if (rawData === null) {
|
|
772
|
+
return {
|
|
773
|
+
Results: [],
|
|
774
|
+
Success: false,
|
|
775
|
+
ErrorMessage: `Failed to execute view: ${input.ViewName}`,
|
|
776
|
+
RowCount: 0,
|
|
777
|
+
TotalRowCount: 0,
|
|
778
|
+
ExecutionTime: 0,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
773
781
|
|
|
774
782
|
const viewInfo = super.safeFirstArrayElement<MJUserViewEntityExtended>(await super.findBy<MJUserViewEntityExtended>(provider, "MJ: User Views", { Name: input.ViewName }, userPayload.userRecord));
|
|
775
783
|
const entity = provider.EntityByID(viewInfo.EntityID);
|
|
@@ -786,8 +794,16 @@ export class RunViewResolver extends ResolverBase {
|
|
|
786
794
|
};
|
|
787
795
|
} catch (err) {
|
|
788
796
|
rethrowFieldSecurityDenial(err);
|
|
789
|
-
|
|
790
|
-
|
|
797
|
+
LogError(err);
|
|
798
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
799
|
+
return {
|
|
800
|
+
Results: [],
|
|
801
|
+
Success: false,
|
|
802
|
+
ErrorMessage: errorMessage,
|
|
803
|
+
RowCount: 0,
|
|
804
|
+
TotalRowCount: 0,
|
|
805
|
+
ExecutionTime: 0,
|
|
806
|
+
};
|
|
791
807
|
}
|
|
792
808
|
}
|
|
793
809
|
|
|
@@ -801,8 +817,16 @@ export class RunViewResolver extends ResolverBase {
|
|
|
801
817
|
await this.CheckAPIKeyScopeAuthorization('view:run', input.ViewID, userPayload);
|
|
802
818
|
const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
|
|
803
819
|
const rawData = await super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
|
|
804
|
-
if (rawData === null)
|
|
805
|
-
return
|
|
820
|
+
if (rawData === null) {
|
|
821
|
+
return {
|
|
822
|
+
Results: [],
|
|
823
|
+
Success: false,
|
|
824
|
+
ErrorMessage: `Failed to execute view with ID: ${input.ViewID}`,
|
|
825
|
+
RowCount: 0,
|
|
826
|
+
TotalRowCount: 0,
|
|
827
|
+
ExecutionTime: 0,
|
|
828
|
+
};
|
|
829
|
+
}
|
|
806
830
|
|
|
807
831
|
const viewInfo = super.safeFirstArrayElement<MJUserViewEntityExtended>(await super.findBy<MJUserViewEntityExtended>(provider, "MJ: User Views", { ID: input.ViewID }, userPayload.userRecord));
|
|
808
832
|
const entity = provider.EntityByID(viewInfo.EntityID);
|
|
@@ -819,8 +843,16 @@ export class RunViewResolver extends ResolverBase {
|
|
|
819
843
|
};
|
|
820
844
|
} catch (err) {
|
|
821
845
|
rethrowFieldSecurityDenial(err);
|
|
822
|
-
|
|
823
|
-
|
|
846
|
+
LogError(err);
|
|
847
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
848
|
+
return {
|
|
849
|
+
Results: [],
|
|
850
|
+
Success: false,
|
|
851
|
+
ErrorMessage: errorMessage,
|
|
852
|
+
RowCount: 0,
|
|
853
|
+
TotalRowCount: 0,
|
|
854
|
+
ExecutionTime: 0,
|
|
855
|
+
};
|
|
824
856
|
}
|
|
825
857
|
}
|
|
826
858
|
|
|
@@ -834,7 +866,16 @@ export class RunViewResolver extends ResolverBase {
|
|
|
834
866
|
await this.CheckAPIKeyScopeAuthorization('view:run', input.EntityName, userPayload);
|
|
835
867
|
const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
|
|
836
868
|
const rawData = await super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
|
|
837
|
-
if (rawData === null)
|
|
869
|
+
if (rawData === null) {
|
|
870
|
+
return {
|
|
871
|
+
Results: [],
|
|
872
|
+
Success: false,
|
|
873
|
+
ErrorMessage: `Failed to execute dynamic view for ${input.EntityName}`,
|
|
874
|
+
RowCount: 0,
|
|
875
|
+
TotalRowCount: 0,
|
|
876
|
+
ExecutionTime: 0,
|
|
877
|
+
};
|
|
878
|
+
}
|
|
838
879
|
|
|
839
880
|
const entity = provider.EntityByName(input.EntityName);
|
|
840
881
|
const returnData = this.processRawData(rawData.Results, entity.ID, entity);
|
|
@@ -850,8 +891,16 @@ export class RunViewResolver extends ResolverBase {
|
|
|
850
891
|
};
|
|
851
892
|
} catch (err) {
|
|
852
893
|
rethrowFieldSecurityDenial(err);
|
|
853
|
-
|
|
854
|
-
|
|
894
|
+
LogError(err);
|
|
895
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
896
|
+
return {
|
|
897
|
+
Results: [],
|
|
898
|
+
Success: false,
|
|
899
|
+
ErrorMessage: errorMessage,
|
|
900
|
+
RowCount: 0,
|
|
901
|
+
TotalRowCount: 0,
|
|
902
|
+
ExecutionTime: 0,
|
|
903
|
+
};
|
|
855
904
|
}
|
|
856
905
|
}
|
|
857
906
|
|
|
@@ -867,7 +916,14 @@ export class RunViewResolver extends ResolverBase {
|
|
|
867
916
|
// Note: RunViewsGeneric returns the core RunViewResult type, not the GraphQL type
|
|
868
917
|
const rawData = await super.RunViewsGeneric(input, provider, userPayload);
|
|
869
918
|
if (!rawData) {
|
|
870
|
-
return
|
|
919
|
+
return input.map(() => ({
|
|
920
|
+
Results: [],
|
|
921
|
+
Success: false,
|
|
922
|
+
ErrorMessage: 'Failed to execute views',
|
|
923
|
+
RowCount: 0,
|
|
924
|
+
TotalRowCount: 0,
|
|
925
|
+
ExecutionTime: 0,
|
|
926
|
+
}));
|
|
871
927
|
}
|
|
872
928
|
|
|
873
929
|
let results: RunViewGenericResult[] = [];
|
|
@@ -884,6 +940,7 @@ export class RunViewResolver extends ResolverBase {
|
|
|
884
940
|
TotalRowCount: data?.TotalRowCount,
|
|
885
941
|
ExecutionTime: data?.ExecutionTime,
|
|
886
942
|
Success: data?.Success,
|
|
943
|
+
ErrorMessage: data?.ErrorMessage,
|
|
887
944
|
AggregateResults: this.processAggregateResults(data?.AggregateResults),
|
|
888
945
|
AggregateExecutionTime: data?.AggregateExecutionTime,
|
|
889
946
|
});
|
|
@@ -893,7 +950,15 @@ export class RunViewResolver extends ResolverBase {
|
|
|
893
950
|
} catch (err) {
|
|
894
951
|
rethrowFieldSecurityDenial(err);
|
|
895
952
|
LogError(err);
|
|
896
|
-
|
|
953
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
954
|
+
return input.map(() => ({
|
|
955
|
+
Results: [],
|
|
956
|
+
Success: false,
|
|
957
|
+
ErrorMessage: errorMessage,
|
|
958
|
+
RowCount: 0,
|
|
959
|
+
TotalRowCount: 0,
|
|
960
|
+
ExecutionTime: 0,
|
|
961
|
+
}));
|
|
897
962
|
}
|
|
898
963
|
}
|
|
899
964
|
|
|
@@ -1060,7 +1125,14 @@ export class RunViewResolver extends ResolverBase {
|
|
|
1060
1125
|
const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
|
|
1061
1126
|
const rawData = await super.RunViewsGeneric(input, provider, userPayload);
|
|
1062
1127
|
if (!rawData) {
|
|
1063
|
-
return
|
|
1128
|
+
return input.map(() => ({
|
|
1129
|
+
Results: [],
|
|
1130
|
+
Success: false,
|
|
1131
|
+
ErrorMessage: 'Failed to execute views',
|
|
1132
|
+
RowCount: 0,
|
|
1133
|
+
TotalRowCount: 0,
|
|
1134
|
+
ExecutionTime: 0,
|
|
1135
|
+
}));
|
|
1064
1136
|
}
|
|
1065
1137
|
|
|
1066
1138
|
let results: RunViewGenericResult[] = [];
|
|
@@ -1089,7 +1161,15 @@ export class RunViewResolver extends ResolverBase {
|
|
|
1089
1161
|
} catch (err) {
|
|
1090
1162
|
rethrowFieldSecurityDenial(err);
|
|
1091
1163
|
LogError(err);
|
|
1092
|
-
|
|
1164
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
1165
|
+
return input.map(() => ({
|
|
1166
|
+
Results: [],
|
|
1167
|
+
Success: false,
|
|
1168
|
+
ErrorMessage: errorMessage,
|
|
1169
|
+
RowCount: 0,
|
|
1170
|
+
TotalRowCount: 0,
|
|
1171
|
+
ExecutionTime: 0,
|
|
1172
|
+
}));
|
|
1093
1173
|
}
|
|
1094
1174
|
}
|
|
1095
1175
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { parseBooleanEnv } from '@memberjunction/config';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the shipped default for `realtime.enabled` from the MJ_REALTIME_ENABLED env var.
|
|
5
|
+
*
|
|
6
|
+
* ## Why this is a function and not an inline expression
|
|
7
|
+
*
|
|
8
|
+
* Like telemetry, `DEFAULT_SERVER_CONFIG` — the base of the merge in `loadConfig()` — supplies
|
|
9
|
+
* `realtime.enabled`. Extracting it here keeps it unit-testable without pulling in config.ts's full
|
|
10
|
+
* dependency graph.
|
|
11
|
+
*
|
|
12
|
+
* ## Semantics
|
|
13
|
+
*
|
|
14
|
+
* Realtime is **on by default**. An unset or blank variable leaves it on; anything
|
|
15
|
+
* {@link parseBooleanEnv} reads as false (`'false'`, `'0'`, `'no'`, `'off'`) turns it off.
|
|
16
|
+
* Blank is deliberately treated as unset rather than as false, so an empty variable exported by a
|
|
17
|
+
* deployment script cannot silently disable realtime.
|
|
18
|
+
*
|
|
19
|
+
* @param rawEnvValue - the raw `process.env.MJ_REALTIME_ENABLED` value
|
|
20
|
+
* @returns whether realtime broker should be enabled by default
|
|
21
|
+
*/
|
|
22
|
+
export function RealtimeEnabledDefault(rawEnvValue: string | undefined | null): boolean {
|
|
23
|
+
return rawEnvValue?.trim() ? parseBooleanEnv(rawEnvValue) : true;
|
|
24
|
+
}
|