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