@faststore/api 1.12.42 → 1.12.44

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.
@@ -11,9 +11,18 @@ var crypto = _interopDefault(require('crypto'));
11
11
  var graphql = require('graphql');
12
12
  var language = require('graphql/language');
13
13
  var utils = require('@graphql-tools/utils');
14
+ var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
15
+ var resources = require('@opentelemetry/resources');
16
+ var exporterTraceOtlpGrpc = require('@opentelemetry/exporter-trace-otlp-grpc');
17
+ var sdkLogs = require('@opentelemetry/sdk-logs');
18
+ var exporterLogsOtlpGrpc = require('@opentelemetry/exporter-logs-otlp-grpc');
19
+ var core = require('@envelop/core');
20
+ var onResolve = require('@envelop/on-resolve');
21
+ var api = require('@opentelemetry/api');
22
+ var apiLogs = require('@opentelemetry/api-logs');
14
23
 
15
24
  var name = "@faststore/api";
16
- var version = "1.12.41";
25
+ var version = "1.12.43";
17
26
  var license = "MIT";
18
27
  var main = "dist/index.js";
19
28
  var typings = "dist/index.d.ts";
@@ -35,7 +44,12 @@ var scripts = {
35
44
  generate: "graphql-codegen --config codegen.yml"
36
45
  };
37
46
  var dependencies = {
47
+ "@envelop/on-resolve": "^2.0.6",
38
48
  "@graphql-tools/schema": "^8.2.0",
49
+ "@opentelemetry/exporter-logs-otlp-grpc": "^0.39.1",
50
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.39.1",
51
+ "@opentelemetry/sdk-logs": "^0.39.1",
52
+ "@opentelemetry/sdk-trace-base": "^1.13.0",
39
53
  "@rollup/plugin-graphql": "^1.0.0",
40
54
  dataloader: "^2.1.0",
41
55
  "fast-deep-equal": "^3.1.3",
@@ -43,7 +57,8 @@ var dependencies = {
43
57
  "p-limit": "^3.1.0"
44
58
  };
45
59
  var devDependencies = {
46
- "@faststore/shared": "^1.12.37",
60
+ "@envelop/core": "^2.6.0",
61
+ "@faststore/shared": "^1.12.43",
47
62
  "@graphql-codegen/cli": "2.2.0",
48
63
  "@graphql-codegen/typescript": "2.2.2",
49
64
  concurrently: "^6.2.1",
@@ -57,6 +72,7 @@ var devDependencies = {
57
72
  typescript: "^4.4.2"
58
73
  };
59
74
  var peerDependencies = {
75
+ "@envelop/core": "^1 || ^2",
60
76
  graphql: "^15.6.0"
61
77
  };
62
78
  var packageJson = {
@@ -2154,7 +2170,7 @@ const StoreSearchResult = {
2154
2170
  },
2155
2171
  products: async ({
2156
2172
  productSearchPromise
2157
- }) => {
2173
+ }, _, ctx) => {
2158
2174
  const productSearchResult = await productSearchPromise;
2159
2175
  const skus = productSearchResult.products.map(product => {
2160
2176
  const [maybeSku] = product.items;
@@ -2168,7 +2184,14 @@ const StoreSearchResult = {
2168
2184
  endCursor: productSearchResult.recordsFiltered.toString(),
2169
2185
  totalCount: productSearchResult.recordsFiltered
2170
2186
  },
2171
- edges: skus.map((sku, index) => ({
2187
+ edges: skus.filter(sku => {
2188
+ if (ctx.hideUnavailableItems) {
2189
+ return sku.sellers.some(item => inStock(item.commertialOffer));
2190
+ } else {
2191
+ return true;
2192
+ }
2193
+ }) // TODO: remove this filter when the IS returns correctly with hideUnavailableItems
2194
+ .map((sku, index) => ({
2172
2195
  node: sku,
2173
2196
  cursor: index.toString()
2174
2197
  }))
@@ -2490,6 +2513,7 @@ const getContextFactory = options => ctx => {
2490
2513
  };
2491
2514
  ctx.clients = getClients(options, ctx);
2492
2515
  ctx.loaders = getLoaders(options, ctx);
2516
+ ctx.hideUnavailableItems = options.hideUnavailableItems;
2493
2517
  return ctx;
2494
2518
  };
2495
2519
  const getResolvers = _ => Resolvers;
@@ -2640,6 +2664,268 @@ const directive = {
2640
2664
  })
2641
2665
  };
2642
2666
 
2667
+ var AttributeName;
2668
+
2669
+ (function (AttributeName) {
2670
+ AttributeName["EXECUTION_ERROR"] = "graphql.error";
2671
+ AttributeName["EXECUTION_RESULT"] = "graphql.result";
2672
+ AttributeName["RESOLVER_EXECUTION_ERROR"] = "graphql.resolver.error";
2673
+ AttributeName["RESOLVER_EXCEPTION"] = "graphql.resolver.exception";
2674
+ AttributeName["RESOLVER_FIELD_NAME"] = "graphql.resolver.fieldName";
2675
+ AttributeName["RESOLVER_TYPE_NAME"] = "graphql.resolver.typeName";
2676
+ AttributeName["RESOLVER_RESULT_TYPE"] = "graphql.resolver.resultType";
2677
+ AttributeName["RESOLVER_ARGS"] = "graphql.resolver.args";
2678
+ AttributeName["EXECUTION_OPERATION_NAME"] = "graphql.operation.name";
2679
+ AttributeName["EXECUTION_OPERATION_TYPE"] = "graphql.operation.type";
2680
+ AttributeName["EXECUTION_OPERATION_DOCUMENT"] = "graphql.document";
2681
+ AttributeName["EXECUTION_VARIABLES"] = "graphql.variables";
2682
+ })(AttributeName || (AttributeName = {}));
2683
+
2684
+ const tracingSpanSymbol = /*#__PURE__*/Symbol('OPEN_TELEMETRY_GRAPHQL');
2685
+
2686
+ function getResolverSpanKey(path) {
2687
+ const nodes = []; // If the first node (after reversed, it will be the last one) is an integer, that is, identifies a list,
2688
+ // we don't want to include it in the key. Note that this will only happen when analysing .prev paths in
2689
+ // a list of elements. We just want to remove the initial node that is a integer, not all of them.
2690
+ //
2691
+ // Nodes with keys 6bc73341b2a183fc::product::image::0::url would not be able to find
2692
+ // parents with key 6bc73341b2a183fc::product::image because of the "0" list index -
2693
+ // it would search for 6bc73341b2a183fc::product::image::0
2694
+
2695
+ let currentPath = nodes.length === 0 && Number.isInteger(path.key) ? path.prev : path;
2696
+
2697
+ while (currentPath) {
2698
+ nodes.push(currentPath.key);
2699
+ currentPath = currentPath.prev;
2700
+ }
2701
+
2702
+ return [...nodes].reverse().join('.');
2703
+ }
2704
+
2705
+ const getFaststoreTelemetryPlugin = (tracingProvider, loggerProvider, serviceName, experimentalSendLogs) => {
2706
+ return function useFaststoreTelemetry() {
2707
+ const tracer = tracingProvider.getTracer(serviceName);
2708
+ const logger = loggerProvider.getLogger(serviceName);
2709
+ const resolverContextsByRootSpans = {};
2710
+ return {
2711
+ onPluginInit({
2712
+ addPlugin
2713
+ }) {
2714
+ addPlugin( // eslint-disable-next-line
2715
+ onResolve.useOnResolve(({
2716
+ info,
2717
+ context
2718
+ }) => {
2719
+ if (context && typeof context === 'object' && context[tracingSpanSymbol]) {
2720
+ var _path$prev, _path$prev2;
2721
+
2722
+ tracer.getActiveSpanProcessor();
2723
+ const rootContextSpanId = context[tracingSpanSymbol].spanContext().spanId;
2724
+ const {
2725
+ fieldName,
2726
+ returnType,
2727
+ parentType,
2728
+ path
2729
+ } = info;
2730
+ const previousResolverSpanKey = path.prev && getResolverSpanKey(path.prev);
2731
+ let ctx = null;
2732
+
2733
+ if (previousResolverSpanKey && resolverContextsByRootSpans[rootContextSpanId][previousResolverSpanKey]) {
2734
+ ctx = resolverContextsByRootSpans[rootContextSpanId][previousResolverSpanKey];
2735
+ } else {
2736
+ var _resolverContextsByRo;
2737
+
2738
+ ctx = api.trace.setSpan(api.context.active(), context[tracingSpanSymbol]);
2739
+ resolverContextsByRootSpans[rootContextSpanId] = (_resolverContextsByRo = resolverContextsByRootSpans[rootContextSpanId]) != null ? _resolverContextsByRo : {};
2740
+ }
2741
+
2742
+ const resolverIndexInList = Number.isInteger((_path$prev = path.prev) == null ? void 0 : _path$prev.key) ? `[${(_path$prev2 = path.prev) == null ? void 0 : _path$prev2.key}]` : '';
2743
+ const resolverSpan = tracer.startSpan(`${parentType.toString()}.${fieldName}${resolverIndexInList}`, {
2744
+ attributes: {
2745
+ [AttributeName.RESOLVER_FIELD_NAME]: fieldName,
2746
+ [AttributeName.RESOLVER_TYPE_NAME]: parentType.toString(),
2747
+ [AttributeName.RESOLVER_RESULT_TYPE]: returnType.toString(),
2748
+ 'meta.span.path': getResolverSpanKey(path)
2749
+ }
2750
+ }, ctx);
2751
+ const resolverCtx = api.trace.setSpan(ctx, resolverSpan);
2752
+ resolverContextsByRootSpans[rootContextSpanId][getResolverSpanKey(path)] = resolverCtx;
2753
+ return ({
2754
+ result
2755
+ }) => {
2756
+ if (result instanceof Error) {
2757
+ resolverSpan.setAttributes({
2758
+ error: true,
2759
+ 'exception.category': AttributeName.RESOLVER_EXECUTION_ERROR,
2760
+ 'exception.message': result.message,
2761
+ 'exception.type': result.name
2762
+ });
2763
+ resolverSpan.recordException(result);
2764
+ }
2765
+
2766
+ resolverSpan.end();
2767
+ };
2768
+ } // eslint-disable-next-line @typescript-eslint/no-empty-function
2769
+
2770
+
2771
+ return () => {};
2772
+ }));
2773
+ },
2774
+
2775
+ onExecute({
2776
+ args,
2777
+ extendContext
2778
+ }) {
2779
+ var _args$document$defini, _args$operationName;
2780
+
2781
+ const operationType = (_args$document$defini = args.document.definitions.filter(def => def.kind === graphql.Kind.OPERATION_DEFINITION).map(def => def.operation)) == null ? void 0 : _args$document$defini[0]; // Span name according to Semantic Conventions
2782
+ // https://github.com/open-telemetry/semantic-conventions
2783
+
2784
+ let spanName = 'GraphQL Operation';
2785
+
2786
+ if (operationType && args.operationName) {
2787
+ spanName = `${operationType} ${args.operationName}`;
2788
+ } else if (operationType && !args.operationName) {
2789
+ spanName = operationType;
2790
+ }
2791
+
2792
+ const executionSpan = tracer.startSpan(spanName, {
2793
+ kind: api.SpanKind.SERVER,
2794
+ attributes: {
2795
+ [AttributeName.EXECUTION_OPERATION_NAME]: (_args$operationName = args.operationName) != null ? _args$operationName : undefined,
2796
+ [AttributeName.EXECUTION_OPERATION_TYPE]: operationType != null ? operationType : undefined,
2797
+ [AttributeName.EXECUTION_OPERATION_DOCUMENT]: graphql.print(args.document)
2798
+ }
2799
+ });
2800
+ const executeContext = api.context.active();
2801
+ const resultCbs = {
2802
+ onExecuteDone({
2803
+ result
2804
+ }) {
2805
+ var _args$operationName2, _args$variableValues;
2806
+
2807
+ if (core.isAsyncIterable(result)) {
2808
+ executionSpan.end(); // eslint-disable-next-line no-console
2809
+
2810
+ console.warn(`Plugin "newrelic" encountered a AsyncIterator which is not supported yet, so tracing data is not available for the operation.`);
2811
+ return;
2812
+ }
2813
+
2814
+ const logRecord = {
2815
+ context: executeContext,
2816
+ attributes: {
2817
+ 'service.name': 'faststore-api',
2818
+ 'service.version': '1.12.38',
2819
+ 'service.name_and_version': 'faststore-api@1.12.38',
2820
+ 'vtex.search_index': 'faststore_beta_api',
2821
+ [AttributeName.EXECUTION_OPERATION_NAME]: (_args$operationName2 = args.operationName) != null ? _args$operationName2 : undefined,
2822
+ [AttributeName.EXECUTION_OPERATION_DOCUMENT]: graphql.print(args.document),
2823
+ [AttributeName.EXECUTION_VARIABLES]: JSON.stringify((_args$variableValues = args.variableValues) != null ? _args$variableValues : {})
2824
+ }
2825
+ };
2826
+
2827
+ if (typeof result.data !== 'undefined' && !(result.errors && result.errors.length > 0)) {
2828
+ logRecord.severityNumber = apiLogs.SeverityNumber.INFO;
2829
+ logRecord.severityText = 'Info';
2830
+ logRecord.attributes[AttributeName.EXECUTION_RESULT] = JSON.stringify(result);
2831
+ }
2832
+
2833
+ if (result.errors && result.errors.length > 0) {
2834
+ logRecord.severityNumber = apiLogs.SeverityNumber.ERROR;
2835
+ logRecord.severityText = 'Error';
2836
+ logRecord.attributes[AttributeName.EXECUTION_ERROR] = JSON.stringify(result.errors);
2837
+ executionSpan.setAttributes({
2838
+ error: true,
2839
+ 'exception.category': AttributeName.EXECUTION_ERROR,
2840
+ 'exception.message': JSON.stringify(result.errors)
2841
+ });
2842
+ }
2843
+
2844
+ if (experimentalSendLogs) {
2845
+ logger.emit(logRecord);
2846
+ }
2847
+
2848
+ executionSpan.end();
2849
+ }
2850
+
2851
+ };
2852
+ extendContext({
2853
+ [tracingSpanSymbol]: executionSpan
2854
+ });
2855
+ return resultCbs;
2856
+ }
2857
+
2858
+ };
2859
+ };
2860
+ };
2861
+
2862
+ const FASTSTORE_API_VERSION = packageJson.version; // TODO: These urls are hardcoded for now, but they should be configurable via ENV variables
2863
+ // They are only acessible from within the VTEX network, so they are not a security risk
2864
+
2865
+ const TRACE_COLLECTOR_URL = 'opentelemetry-collector.vtex.systems';
2866
+ const TRACE_COLLECTOR_URL_DEV = 'opentelemetry-collector-beta.vtex.systems';
2867
+ const LOG_COLLECTOR_URL = 'opentelemetry-collector.vtex.systems';
2868
+ function getTelemetry(APIOptions, telemetryOptions) {
2869
+ var _telemetryOptions$exp;
2870
+
2871
+ const honeycombCollectorOptions = {
2872
+ url: (telemetryOptions == null ? void 0 : telemetryOptions.mode) === 'dev' ? TRACE_COLLECTOR_URL_DEV : TRACE_COLLECTOR_URL
2873
+ };
2874
+ const openSearchCollectorOptions = {
2875
+ url: LOG_COLLECTOR_URL
2876
+ }; // Create a new tracer provider
2877
+
2878
+ const tracerProvider = new sdkTraceBase.BasicTracerProvider({
2879
+ resource: new resources.Resource({
2880
+ 'service.name': 'faststore-api',
2881
+ 'service.version': FASTSTORE_API_VERSION,
2882
+ 'service.name_and_version': `faststore-api@${FASTSTORE_API_VERSION}`,
2883
+ platform: APIOptions.platform,
2884
+ [`${APIOptions.platform}.account`]: APIOptions.account,
2885
+ [`${APIOptions.platform}.environment`]: APIOptions.environment,
2886
+ // TODO: include the following properties in the logs
2887
+ // [`${APIOptions.platform}.options.hideUnavailableItems`]:
2888
+ // APIOptions.hideUnavailableItems,
2889
+ // [`${APIOptions.platform}.flags.enableOrderFormSync`]:
2890
+ // APIOptions.flags?.enableOrderFormSync,
2891
+ // channel: APIOptions.channel,
2892
+ locale: APIOptions.locale
2893
+ })
2894
+ });
2895
+ const loggerProvider = new sdkLogs.LoggerProvider(); // Create trace exporter
2896
+
2897
+ const honeycombExporter = new exporterTraceOtlpGrpc.OTLPTraceExporter(honeycombCollectorOptions); // Create log exporter
2898
+
2899
+ const openSearchExporter = new exporterLogsOtlpGrpc.OTLPLogsExporter(openSearchCollectorOptions); // Set up a span processor to export spans to Honeycomb
2900
+
2901
+ const honeyCombSpanProcessor = new sdkTraceBase.SimpleSpanProcessor(honeycombExporter); // Set up a log record processor to export spans to OpenSearch
2902
+
2903
+ const openSearchLogProcessor = new sdkLogs.SimpleLogRecordProcessor(openSearchExporter); // Register the span processor with the tracer provider
2904
+
2905
+ tracerProvider.addSpanProcessor(honeyCombSpanProcessor); // Register the log record processor with the log provider
2906
+
2907
+ loggerProvider.addLogRecordProcessor(openSearchLogProcessor);
2908
+
2909
+ if ((telemetryOptions == null ? void 0 : telemetryOptions.mode) === 'verbose' || (telemetryOptions == null ? void 0 : telemetryOptions.mode) === 'dev') {
2910
+ // Set up a console exporter for verbose mode
2911
+ const consoleExporter = new sdkTraceBase.ConsoleSpanExporter();
2912
+ const verboseTraceProcessor = new sdkTraceBase.SimpleSpanProcessor(consoleExporter); // Set up processors for verbose mode
2913
+
2914
+ const consoleLogExporter = new sdkLogs.ConsoleLogRecordExporter();
2915
+ const veboseLogRecordExporter = new sdkLogs.SimpleLogRecordProcessor(consoleLogExporter);
2916
+ tracerProvider.addSpanProcessor(verboseTraceProcessor);
2917
+ loggerProvider.addLogRecordProcessor(veboseLogRecordExporter);
2918
+ }
2919
+
2920
+ const useFaststoreTelemetry = getFaststoreTelemetryPlugin( // The @opentelemetry/sdk-trace-base was renamed from @opentelemetry/tracing but the
2921
+ // envelop plugin doesn't support this change yet. This causes the class type to be incompatible,
2922
+ // even if they are the same. https://github.com/n1ru4l/envelop/issues/1610
2923
+ tracerProvider, loggerProvider, 'faststore-api', (_telemetryOptions$exp = telemetryOptions == null ? void 0 : telemetryOptions.experimentalSendLogs) != null ? _telemetryOptions$exp : false);
2924
+ return {
2925
+ useFaststoreTelemetry
2926
+ };
2927
+ }
2928
+
2643
2929
  const platforms = {
2644
2930
  vtex: {
2645
2931
  getResolvers: getResolvers,
@@ -2663,6 +2949,7 @@ exports.NotFoundError = NotFoundError;
2663
2949
  exports.getContextFactory = getContextFactory$1;
2664
2950
  exports.getResolvers = getResolvers$1;
2665
2951
  exports.getSchema = getSchema;
2952
+ exports.getTelemetry = getTelemetry;
2666
2953
  exports.getTypeDefs = getTypeDefs;
2667
2954
  exports.isBadRequestError = isBadRequestError;
2668
2955
  exports.isFastStoreError = isFastStoreError;