@envelop/core 2.2.0 → 2.4.0-alpha-3936561.0

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.js CHANGED
@@ -299,6 +299,49 @@ function errorAsyncIterator(source, onError) {
299
299
  };
300
300
  return stream;
301
301
  }
302
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
303
+ function getInMemoryLRUCache({ max = 1000, onDelete = () => { }, } = {}) {
304
+ let storage = {};
305
+ let keys = [];
306
+ return {
307
+ get(key) {
308
+ return storage[key];
309
+ },
310
+ set(key, value) {
311
+ queueMicrotask(() => {
312
+ if (storage[key] != null) {
313
+ if (keys.indexOf(key)) {
314
+ keys.splice(keys.indexOf(key), 1);
315
+ }
316
+ }
317
+ keys.push(key);
318
+ storage[key] = value;
319
+ while (keys.length > max) {
320
+ const key = keys.shift();
321
+ if (key != null) {
322
+ onDelete(key, storage[key]);
323
+ delete storage[key];
324
+ }
325
+ }
326
+ });
327
+ },
328
+ delete(key) {
329
+ queueMicrotask(() => {
330
+ if (storage[key] != null) {
331
+ keys.splice(keys.indexOf(key), 1);
332
+ onDelete(key, storage[key]);
333
+ delete storage[key];
334
+ }
335
+ });
336
+ },
337
+ clear() {
338
+ queueMicrotask(() => {
339
+ storage = {};
340
+ keys = [];
341
+ });
342
+ },
343
+ };
344
+ }
302
345
 
303
346
  function createEnvelopOrchestrator(plugins) {
304
347
  let schema = null;
@@ -486,8 +529,9 @@ function createEnvelopOrchestrator(plugins) {
486
529
  const customContextFactory = beforeCallbacks.context.length
487
530
  ? initialContext => async (orchestratorCtx) => {
488
531
  const afterCalls = [];
532
+ // In order to have access to the "last working" context object we keep this outside of the try block:
533
+ let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
489
534
  try {
490
- let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
491
535
  let isBreakingContextBuilding = false;
492
536
  for (const onContext of beforeCallbacks.context) {
493
537
  const afterHookResult = await onContext({
@@ -520,6 +564,7 @@ function createEnvelopOrchestrator(plugins) {
520
564
  let error = err;
521
565
  for (const errorCb of contextErrorHandlers) {
522
566
  errorCb({
567
+ context,
523
568
  error,
524
569
  setError: err => {
525
570
  error = err;
@@ -1227,9 +1272,15 @@ const useMaskedErrors = (opts) => {
1227
1272
 
1228
1273
  const OnNonIntrospectionFieldReachedValidationRule = (onNonIntrospectionField) => ctx => {
1229
1274
  const rootQueryType = ctx.getSchema().getQueryType();
1275
+ const rootMutationType = ctx.getSchema().getMutationType();
1276
+ const rootSubscriptionType = ctx.getSchema().getSubscriptionType();
1230
1277
  return {
1231
1278
  Field(field) {
1232
- if (ctx.getParentType() === rootQueryType && !field.name.value.startsWith('__')) {
1279
+ const parentType = ctx.getParentType();
1280
+ const isQuery = parentType === rootQueryType;
1281
+ const isMutation = parentType === rootMutationType;
1282
+ const isSubscription = parentType === rootSubscriptionType;
1283
+ if ((isQuery && !field.name.value.startsWith('__')) || isMutation || isSubscription) {
1233
1284
  onNonIntrospectionField();
1234
1285
  return graphql.BREAK;
1235
1286
  }
@@ -1281,6 +1332,7 @@ exports.envelopIsIntrospectionSymbol = envelopIsIntrospectionSymbol;
1281
1332
  exports.errorAsyncIterator = errorAsyncIterator;
1282
1333
  exports.finalAsyncIterator = finalAsyncIterator;
1283
1334
  exports.formatError = formatError;
1335
+ exports.getInMemoryLRUCache = getInMemoryLRUCache;
1284
1336
  exports.handleStreamOrSingleExecutionResult = handleStreamOrSingleExecutionResult;
1285
1337
  exports.isAsyncIterable = isAsyncIterable;
1286
1338
  exports.isIntrospectionDocument = isIntrospectionDocument;
package/index.mjs CHANGED
@@ -295,6 +295,49 @@ function errorAsyncIterator(source, onError) {
295
295
  };
296
296
  return stream;
297
297
  }
298
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
299
+ function getInMemoryLRUCache({ max = 1000, onDelete = () => { }, } = {}) {
300
+ let storage = {};
301
+ let keys = [];
302
+ return {
303
+ get(key) {
304
+ return storage[key];
305
+ },
306
+ set(key, value) {
307
+ queueMicrotask(() => {
308
+ if (storage[key] != null) {
309
+ if (keys.indexOf(key)) {
310
+ keys.splice(keys.indexOf(key), 1);
311
+ }
312
+ }
313
+ keys.push(key);
314
+ storage[key] = value;
315
+ while (keys.length > max) {
316
+ const key = keys.shift();
317
+ if (key != null) {
318
+ onDelete(key, storage[key]);
319
+ delete storage[key];
320
+ }
321
+ }
322
+ });
323
+ },
324
+ delete(key) {
325
+ queueMicrotask(() => {
326
+ if (storage[key] != null) {
327
+ keys.splice(keys.indexOf(key), 1);
328
+ onDelete(key, storage[key]);
329
+ delete storage[key];
330
+ }
331
+ });
332
+ },
333
+ clear() {
334
+ queueMicrotask(() => {
335
+ storage = {};
336
+ keys = [];
337
+ });
338
+ },
339
+ };
340
+ }
298
341
 
299
342
  function createEnvelopOrchestrator(plugins) {
300
343
  let schema = null;
@@ -482,8 +525,9 @@ function createEnvelopOrchestrator(plugins) {
482
525
  const customContextFactory = beforeCallbacks.context.length
483
526
  ? initialContext => async (orchestratorCtx) => {
484
527
  const afterCalls = [];
528
+ // In order to have access to the "last working" context object we keep this outside of the try block:
529
+ let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
485
530
  try {
486
- let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
487
531
  let isBreakingContextBuilding = false;
488
532
  for (const onContext of beforeCallbacks.context) {
489
533
  const afterHookResult = await onContext({
@@ -516,6 +560,7 @@ function createEnvelopOrchestrator(plugins) {
516
560
  let error = err;
517
561
  for (const errorCb of contextErrorHandlers) {
518
562
  errorCb({
563
+ context,
519
564
  error,
520
565
  setError: err => {
521
566
  error = err;
@@ -1223,9 +1268,15 @@ const useMaskedErrors = (opts) => {
1223
1268
 
1224
1269
  const OnNonIntrospectionFieldReachedValidationRule = (onNonIntrospectionField) => ctx => {
1225
1270
  const rootQueryType = ctx.getSchema().getQueryType();
1271
+ const rootMutationType = ctx.getSchema().getMutationType();
1272
+ const rootSubscriptionType = ctx.getSchema().getSubscriptionType();
1226
1273
  return {
1227
1274
  Field(field) {
1228
- if (ctx.getParentType() === rootQueryType && !field.name.value.startsWith('__')) {
1275
+ const parentType = ctx.getParentType();
1276
+ const isQuery = parentType === rootQueryType;
1277
+ const isMutation = parentType === rootMutationType;
1278
+ const isSubscription = parentType === rootSubscriptionType;
1279
+ if ((isQuery && !field.name.value.startsWith('__')) || isMutation || isSubscription) {
1229
1280
  onNonIntrospectionField();
1230
1281
  return BREAK;
1231
1282
  }
@@ -1261,4 +1312,4 @@ const useImmediateIntrospection = () => {
1261
1312
  };
1262
1313
  };
1263
1314
 
1264
- export { DEFAULT_ERROR_MESSAGE, EnvelopError, enableIf, envelop, envelopIsIntrospectionSymbol, errorAsyncIterator, finalAsyncIterator, formatError, handleStreamOrSingleExecutionResult, isAsyncIterable, isIntrospectionDocument, isIntrospectionOperation, isIntrospectionOperationString, isOperationDefinition, isPluginEnabled, makeExecute, makeSubscribe, mapAsyncIterator, useAsyncSchema, useEnvelop, useErrorHandler, useExtendContext, useImmediateIntrospection, useLazyLoadedSchema, useLogger, useMaskedErrors, usePayloadFormatter, useSchema, useTiming };
1315
+ export { DEFAULT_ERROR_MESSAGE, EnvelopError, enableIf, envelop, envelopIsIntrospectionSymbol, errorAsyncIterator, finalAsyncIterator, formatError, getInMemoryLRUCache, handleStreamOrSingleExecutionResult, isAsyncIterable, isIntrospectionDocument, isIntrospectionOperation, isIntrospectionOperationString, isOperationDefinition, isPluginEnabled, makeExecute, makeSubscribe, mapAsyncIterator, useAsyncSchema, useEnvelop, useErrorHandler, useExtendContext, useImmediateIntrospection, useLazyLoadedSchema, useLogger, useMaskedErrors, usePayloadFormatter, useSchema, useTiming };
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@envelop/core",
3
- "version": "2.2.0",
3
+ "version": "2.4.0-alpha-3936561.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
7
7
  },
8
8
  "dependencies": {
9
- "@envelop/types": "2.1.0"
9
+ "@envelop/types": "2.2.0"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
package/utils.d.ts CHANGED
@@ -31,3 +31,12 @@ export declare function isAsyncIterable<TType>(maybeAsyncIterable: unknown): may
31
31
  export declare function handleStreamOrSingleExecutionResult<ContextType = DefaultContext>(payload: OnExecuteDoneEventPayload<ContextType>, fn: OnExecuteDoneHookResultOnNextHook<ContextType>): void | OnExecuteDoneHookResult<ContextType>;
32
32
  export declare function finalAsyncIterator<TInput>(source: AsyncIterable<TInput>, onFinal: () => void): AsyncGenerator<TInput>;
33
33
  export declare function errorAsyncIterator<TInput>(source: AsyncIterable<TInput>, onError: (err: unknown) => void): AsyncGenerator<TInput>;
34
+ export declare function getInMemoryLRUCache<V>({ max, onDelete, }?: {
35
+ max?: number;
36
+ onDelete?: (key: string, value: V) => void;
37
+ }): {
38
+ get(key: string): V | undefined;
39
+ set(key: string, value: V): void;
40
+ delete(key: string): void;
41
+ clear(): void;
42
+ };