Socket
Socket
Sign inDemoInstall

graphql

Package Overview
Dependencies
Maintainers
7
Versions
259
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql - npm Package Compare versions

Comparing version 17.0.0-alpha.1.canary.pr.3659.cef660554446d49cec9a0958afb9690dd0b19193 to 17.0.0-alpha.1.canary.pr.3673.53c289997f206acd10388d6a574341c68cc1a30e

utilities/Anonymizer.d.ts

12

execution/collectFields.d.ts

@@ -9,10 +9,2 @@ import type { ObjMap } from '../jsutils/ObjMap';

import type { GraphQLSchema } from '../type/schema';
export interface PatchFields {
label?: string;
fields: Map<string, ReadonlyArray<FieldNode>>;
}
export interface FieldsAndPatches {
fields: Map<string, ReadonlyArray<FieldNode>>;
patches: Array<PatchFields>;
}
/**

@@ -35,3 +27,3 @@ * Given a selectionSet, collects all of the fields and returns them.

selectionSet: SelectionSetNode,
): FieldsAndPatches;
): Map<string, ReadonlyArray<FieldNode>>;
/**

@@ -55,2 +47,2 @@ * Given an array of field nodes, collects all of the subfields of the passed

fieldNodes: ReadonlyArray<FieldNode>,
): FieldsAndPatches;
): Map<string, ReadonlyArray<FieldNode>>;

@@ -5,3 +5,2 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap.js';

import {
GraphQLDeferDirective,
GraphQLIncludeDirective,

@@ -29,3 +28,2 @@ GraphQLSkipDirective,

const fields = new AccumulatorMap();
const patches = [];
collectFieldsImpl(

@@ -38,6 +36,5 @@ schema,

fields,
patches,
new Set(),
);
return { fields, patches };
return fields;
}

@@ -63,7 +60,2 @@ /**

const visitedFragmentNames = new Set();
const subPatches = [];
const subFieldsAndPatches = {
fields: subFieldNodes,
patches: subPatches,
};
for (const node of fieldNodes) {

@@ -78,3 +70,2 @@ if (node.selectionSet) {

subFieldNodes,
subPatches,
visitedFragmentNames,

@@ -84,3 +75,3 @@ );

}
return subFieldsAndPatches;
return subFieldNodes;
}

@@ -95,3 +86,2 @@ // eslint-disable-next-line max-params

fields,
patches,
visitedFragmentNames,

@@ -115,31 +105,11 @@ ) {

}
const defer = getDeferValues(variableValues, selection);
if (defer) {
const patchFields = new AccumulatorMap();
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
selection.selectionSet,
patchFields,
patches,
visitedFragmentNames,
);
patches.push({
label: defer.label,
fields: patchFields,
});
} else {
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
selection.selectionSet,
fields,
patches,
visitedFragmentNames,
);
}
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
selection.selectionSet,
fields,
visitedFragmentNames,
);
break;

@@ -149,9 +119,9 @@ }

const fragName = selection.name.value;
if (!shouldIncludeNode(variableValues, selection)) {
if (
visitedFragmentNames.has(fragName) ||
!shouldIncludeNode(variableValues, selection)
) {
continue;
}
const defer = getDeferValues(variableValues, selection);
if (visitedFragmentNames.has(fragName) && !defer) {
continue;
}
visitedFragmentNames.add(fragName);
const fragment = fragments[fragName];

@@ -164,33 +134,11 @@ if (

}
if (!defer) {
visitedFragmentNames.add(fragName);
}
if (defer) {
const patchFields = new AccumulatorMap();
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
fragment.selectionSet,
patchFields,
patches,
visitedFragmentNames,
);
patches.push({
label: defer.label,
fields: patchFields,
});
} else {
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
fragment.selectionSet,
fields,
patches,
visitedFragmentNames,
);
}
collectFieldsImpl(
schema,
fragments,
variableValues,
runtimeType,
fragment.selectionSet,
fields,
visitedFragmentNames,
);
break;

@@ -202,19 +150,2 @@ }

/**
* Returns an object containing the `@defer` arguments if a field should be
* deferred based on the experimental flag, defer directive present and
* not disabled by the "if" argument.
*/
function getDeferValues(variableValues, node) {
const defer = getDirectiveValues(GraphQLDeferDirective, node, variableValues);
if (!defer) {
return;
}
if (defer.if === false) {
return;
}
return {
label: typeof defer.label === 'string' ? defer.label : undefined,
};
}
/**
* Determines if a field should be included based on the `@include` and `@skip`

@@ -221,0 +152,0 @@ * directives, where `@skip` has higher precedence than `@include`.

@@ -59,3 +59,2 @@ import type { Maybe } from '../jsutils/Maybe';

errors: Array<GraphQLError>;
subsequentPayloads: Array<AsyncPayloadRecord>;
}

@@ -67,7 +66,6 @@ /**

* - `data` is the result of a successful execution of the query.
* - `hasNext` is true if a future payload is expected.
* - `extensions` is reserved for adding non-standard properties.
*/
export interface ExecutionResult<
TData = unknown,
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,

@@ -77,3 +75,2 @@ > {

data?: TData | null;
hasNext?: boolean;
extensions?: TExtensions;

@@ -87,40 +84,4 @@ }

data?: TData | null;
hasNext?: boolean;
extensions?: TExtensions;
}
/**
* The result of an asynchronous GraphQL patch.
*
* - `errors` is included when any errors occurred as a non-empty array.
* - `data` is the result of the additional asynchronous data.
* - `path` is the location of data.
* - `label` is the label provided to `@defer` or `@stream`.
* - `hasNext` is true if a future payload is expected.
* - `extensions` is reserved for adding non-standard properties.
*/
export interface ExecutionPatchResult<
TData = unknown,
TExtensions = ObjMap<unknown>,
> {
errors?: ReadonlyArray<GraphQLError>;
data?: TData | null;
path?: ReadonlyArray<string | number>;
label?: string;
hasNext: boolean;
extensions?: TExtensions;
}
export interface FormattedExecutionPatchResult<
TData = unknown,
TExtensions = ObjMap<unknown>,
> {
errors?: ReadonlyArray<GraphQLFormattedError>;
data?: TData | null;
path?: ReadonlyArray<string | number>;
label?: string;
hasNext: boolean;
extensions?: TExtensions;
}
export declare type AsyncExecutionResult =
| ExecutionResult
| ExecutionPatchResult;
export interface ExecutionArgs {

@@ -151,5 +112,3 @@ schema: GraphQLSchema;

args: ExecutionArgs,
): PromiseOrValue<
ExecutionResult | AsyncGenerator<AsyncExecutionResult, void, void>
>;
): PromiseOrValue<ExecutionResult>;
/**

@@ -262,20 +221,1 @@ * Also implements the "Executing requests" section of the GraphQL specification.

): PromiseOrValue<AsyncIterable<unknown> | ExecutionResult>;
declare class AsyncPayloadRecord {
errors: Array<GraphQLError>;
label?: string;
path?: Path;
data?: PromiseOrValue<unknown>;
parentContext?: AsyncPayloadRecord;
iterator?: AsyncIterator<unknown>;
isCompletedIterator?: boolean;
constructor(opts: {
label?: string;
path?: Path;
iterator?: AsyncIterator<unknown>;
parentContext?: AsyncPayloadRecord;
});
addData(data: PromiseOrValue<unknown>): void;
getData(): PromiseOrValue<unknown>;
setIsCompletedIterator(): void;
}
export {};

@@ -22,3 +22,2 @@ import { inspect } from '../jsutils/inspect.js';

} from '../type/definition.js';
import { GraphQLStreamDirective } from '../type/directives.js';
import { assertValidSchema } from '../type/validate.js';

@@ -29,9 +28,4 @@ import {

} from './collectFields.js';
import { flattenAsyncIterator } from './flattenAsyncIterator.js';
import { mapAsyncIterator } from './mapAsyncIterator.js';
import {
getArgumentValues,
getDirectiveValues,
getVariableValues,
} from './values.js';
import { getArgumentValues, getVariableValues } from './values.js';
/* eslint-disable max-params */

@@ -90,9 +84,3 @@ // This file contains a lot of such errors but we plan to refactor it anyway

return result.then(
(data) => {
const initialResult = buildResponse(data, exeContext.errors);
if (exeContext.subsequentPayloads.length > 0) {
return yieldSubsequentPayloads(exeContext, initialResult);
}
return initialResult;
},
(data) => buildResponse(data, exeContext.errors),
(error) => {

@@ -104,7 +92,3 @@ exeContext.errors.push(error);

}
const initialResult = buildResponse(result, exeContext.errors);
if (exeContext.subsequentPayloads.length > 0) {
return yieldSubsequentPayloads(exeContext, initialResult);
}
return initialResult;
return buildResponse(result, exeContext.errors);
} catch (error) {

@@ -123,3 +107,3 @@ exeContext.errors.push(error);

// Assert that the execution was synchronous.
if (isPromise(result) || isAsyncIterable(result)) {
if (isPromise(result)) {
throw new Error('GraphQL execution failed to complete synchronously.');

@@ -212,3 +196,2 @@ }

subscribeFieldResolver: subscribeFieldResolver ?? defaultFieldResolver,
subsequentPayloads: [],
errors: [],

@@ -237,3 +220,3 @@ };

}
const { fields: rootFields, patches } = collectFields(
const rootFields = collectFields(
schema,

@@ -246,9 +229,7 @@ fragments,

const path = undefined;
let result;
switch (operation.operation) {
case OperationTypeNode.QUERY:
result = executeFields(exeContext, rootType, rootValue, path, rootFields);
break;
return executeFields(exeContext, rootType, rootValue, path, rootFields);
case OperationTypeNode.MUTATION:
result = executeFieldsSerially(
return executeFieldsSerially(
exeContext,

@@ -260,20 +241,7 @@ rootType,

);
break;
case OperationTypeNode.SUBSCRIPTION:
// TODO: deprecate `subscribe` and move all logic here
// Temporary solution until we finish merging execute and subscribe together
result = executeFields(exeContext, rootType, rootValue, path, rootFields);
return executeFields(exeContext, rootType, rootValue, path, rootFields);
}
for (const patch of patches) {
const { label, fields: patchFields } = patch;
executeDeferredFragment(
exeContext,
rootType,
rootValue,
patchFields,
label,
path,
);
}
return result;
}

@@ -321,10 +289,3 @@ /**

*/
function executeFields(
exeContext,
parentType,
sourceValue,
path,
fields,
asyncPayloadRecord,
) {
function executeFields(exeContext, parentType, sourceValue, path, fields) {
const results = Object.create(null);

@@ -340,3 +301,2 @@ let containsPromise = false;

fieldPath,
asyncPayloadRecord,
);

@@ -365,11 +325,3 @@ if (result !== undefined) {

*/
function executeField(
exeContext,
parentType,
source,
fieldNodes,
path,
asyncPayloadRecord,
) {
const errors = asyncPayloadRecord?.errors ?? exeContext.errors;
function executeField(exeContext, parentType, source, fieldNodes, path) {
const fieldName = fieldNodes[0].name.value;

@@ -407,11 +359,3 @@ const fieldDef = exeContext.schema.getField(parentType, fieldName);

completed = result.then((resolved) =>
completeValue(
exeContext,
returnType,
fieldNodes,
info,
path,
resolved,
asyncPayloadRecord,
),
completeValue(exeContext, returnType, fieldNodes, info, path, resolved),
);

@@ -426,3 +370,2 @@ } else {

result,
asyncPayloadRecord,
);

@@ -435,3 +378,3 @@ }

const error = locatedError(rawError, fieldNodes, pathToArray(path));
return handleFieldError(error, returnType, errors);
return handleFieldError(error, returnType, exeContext);
});

@@ -442,3 +385,3 @@ }

const error = locatedError(rawError, fieldNodes, pathToArray(path));
return handleFieldError(error, returnType, errors);
return handleFieldError(error, returnType, exeContext);
}

@@ -472,3 +415,3 @@ }

}
function handleFieldError(error, returnType, errors) {
function handleFieldError(error, returnType, exeContext) {
// If the field type is non-nullable, then it is resolved without any

@@ -481,3 +424,3 @@ // protection from errors, however it still properly locates the error.

// a null value for this field if one is encountered.
errors.push(error);
exeContext.errors.push(error);
return null;

@@ -506,11 +449,3 @@ }

*/
function completeValue(
exeContext,
returnType,
fieldNodes,
info,
path,
result,
asyncPayloadRecord,
) {
function completeValue(exeContext, returnType, fieldNodes, info, path, result) {
// If result is an Error, throw a located error.

@@ -530,3 +465,2 @@ if (result instanceof Error) {

result,
asyncPayloadRecord,
);

@@ -553,3 +487,2 @@ if (completed === null) {

result,
asyncPayloadRecord,
);

@@ -572,3 +505,2 @@ }

result,
asyncPayloadRecord,
);

@@ -585,3 +517,2 @@ }

result,
asyncPayloadRecord,
);

@@ -598,34 +529,2 @@ }

/**
* Returns an object containing the `@stream` arguments if a field should be
* streamed based on the experimental flag, stream directive present and
* not disabled by the "if" argument.
*/
function getStreamValues(exeContext, fieldNodes, path) {
// do not stream inner lists of multi-dimensional lists
if (typeof path.key === 'number') {
return;
}
// validation only allows equivalent streams on multiple fields, so it is
// safe to only check the first fieldNode for the stream directive
const stream = getDirectiveValues(
GraphQLStreamDirective,
fieldNodes[0],
exeContext.variableValues,
);
if (!stream) {
return;
}
if (stream.if === false) {
return;
}
typeof stream.initialCount === 'number' ||
invariant(false, 'initialCount must be a number');
stream.initialCount >= 0 ||
invariant(false, 'initialCount must be a positive integer');
return {
initialCount: stream.initialCount,
label: typeof stream.label === 'string' ? stream.label : undefined,
};
}
/**
* Complete a async iterator value by completing the result and calling

@@ -641,6 +540,3 @@ * recursively until all the results are completed.

iterator,
asyncPayloadRecord,
) {
const errors = asyncPayloadRecord?.errors ?? exeContext.errors;
const stream = getStreamValues(exeContext, fieldNodes, path);
let containsPromise = false;

@@ -651,21 +547,2 @@ const completedResults = [];

while (true) {
if (
stream &&
typeof stream.initialCount === 'number' &&
index >= stream.initialCount
) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
executeStreamIterator(
index,
iterator,
exeContext,
fieldNodes,
info,
itemType,
path,
stream.label,
asyncPayloadRecord,
);
break;
}
const fieldPath = addPath(path, index, undefined);

@@ -687,3 +564,2 @@ try {

value,
asyncPayloadRecord,
);

@@ -701,3 +577,3 @@ if (isPromise(completedItem)) {

);
handleFieldError(error, itemType, errors);
handleFieldError(error, itemType, exeContext);
}

@@ -707,3 +583,3 @@ } catch (rawError) {

const error = locatedError(rawError, fieldNodes, pathToArray(fieldPath));
handleFieldError(error, itemType, errors);
handleFieldError(error, itemType, exeContext);
break;

@@ -726,6 +602,4 @@ }

result,
asyncPayloadRecord,
) {
const itemType = returnType.ofType;
const errors = asyncPayloadRecord?.errors ?? exeContext.errors;
if (isAsyncIterable(result)) {

@@ -740,3 +614,2 @@ const iterator = result[Symbol.asyncIterator]();

iterator,
asyncPayloadRecord,
);

@@ -749,10 +622,6 @@ }

}
const stream = getStreamValues(exeContext, fieldNodes, path);
// This is specified as a simple map, however we're optimizing the path
// where the list contains no Promises by avoiding creating another Promise.
let containsPromise = false;
let previousAsyncPayloadRecord = asyncPayloadRecord;
const completedResults = [];
let index = 0;
for (const item of result) {
const completedResults = Array.from(result, (item, index) => {
// No need to modify the info object containing the path,

@@ -763,20 +632,2 @@ // since from here on it is not ever accessed by resolver functions.

let completedItem;
if (
stream &&
typeof stream.initialCount === 'number' &&
index >= stream.initialCount
) {
previousAsyncPayloadRecord = executeStreamField(
itemPath,
item,
exeContext,
fieldNodes,
info,
itemType,
stream.label,
previousAsyncPayloadRecord,
);
index++;
continue;
}
if (isPromise(item)) {

@@ -791,3 +642,2 @@ completedItem = item.then((resolved) =>

resolved,
asyncPayloadRecord,
),

@@ -803,3 +653,2 @@ );

item,
asyncPayloadRecord,
);

@@ -811,21 +660,17 @@ }

// to take a second callback for the error case.
completedResults.push(
completedItem.then(undefined, (rawError) => {
const error = locatedError(
rawError,
fieldNodes,
pathToArray(itemPath),
);
return handleFieldError(error, itemType, errors);
}),
);
} else {
completedResults.push(completedItem);
return completedItem.then(undefined, (rawError) => {
const error = locatedError(
rawError,
fieldNodes,
pathToArray(itemPath),
);
return handleFieldError(error, itemType, exeContext);
});
}
return completedItem;
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(itemPath));
completedResults.push(handleFieldError(error, itemType, errors));
return handleFieldError(error, itemType, exeContext);
}
index++;
}
});
return containsPromise ? Promise.all(completedResults) : completedResults;

@@ -858,3 +703,2 @@ }

result,
asyncPayloadRecord,
) {

@@ -880,3 +724,2 @@ const resolveTypeFn = returnType.resolveType ?? exeContext.typeResolver;

result,
asyncPayloadRecord,
),

@@ -899,3 +742,2 @@ );

result,
asyncPayloadRecord,
);

@@ -961,4 +803,5 @@ }

result,
asyncPayloadRecord,
) {
// Collect sub-fields to execute to complete this value.
const subFieldNodes = collectSubfields(exeContext, returnType, fieldNodes);
// If there is an isTypeOf predicate function, call it with the

@@ -974,9 +817,8 @@ // current result. If isTypeOf returns false, then raise an error rather

}
return collectAndExecuteSubfields(
return executeFields(
exeContext,
returnType,
fieldNodes,
result,
path,
result,
asyncPayloadRecord,
subFieldNodes,
);

@@ -989,10 +831,3 @@ });

}
return collectAndExecuteSubfields(
exeContext,
returnType,
fieldNodes,
path,
result,
asyncPayloadRecord,
);
return executeFields(exeContext, returnType, result, path, subFieldNodes);
}

@@ -1005,38 +840,2 @@ function invalidReturnTypeError(returnType, result, fieldNodes) {

}
function collectAndExecuteSubfields(
exeContext,
returnType,
fieldNodes,
path,
result,
asyncPayloadRecord,
) {
// Collect sub-fields to execute to complete this value.
const { fields: subFieldNodes, patches: subPatches } = collectSubfields(
exeContext,
returnType,
fieldNodes,
);
const subFields = executeFields(
exeContext,
returnType,
result,
path,
subFieldNodes,
asyncPayloadRecord,
);
for (const subPatch of subPatches) {
const { label, fields: subPatchFieldNodes } = subPatch;
executeDeferredFragment(
exeContext,
returnType,
result,
subPatchFieldNodes,
label,
path,
asyncPayloadRecord,
);
}
return subFields;
}
/**

@@ -1154,6 +953,4 @@ * If a resolveType function is not given, then a default resolve behavior is

// "ExecuteQuery" algorithm, for which `execute` is also used.
return flattenAsyncIterator(
mapAsyncIterator(resultOrStream, (payload) =>
executeImpl(buildPerEventExecutionContext(exeContext, payload)),
),
return mapAsyncIterator(resultOrStream, (payload) =>
executeImpl(buildPerEventExecutionContext(exeContext, payload)),
);

@@ -1220,3 +1017,3 @@ }

}
const { fields: rootFields } = collectFields(
const rootFields = collectFields(
schema,

@@ -1282,341 +1079,1 @@ fragments,

}
function executeDeferredFragment(
exeContext,
parentType,
sourceValue,
fields,
label,
path,
parentContext,
) {
const asyncPayloadRecord = new AsyncPayloadRecord({
label,
path,
parentContext,
});
let promiseOrData;
try {
promiseOrData = executeFields(
exeContext,
parentType,
sourceValue,
path,
fields,
asyncPayloadRecord,
);
if (isPromise(promiseOrData)) {
promiseOrData = promiseOrData.then(null, (e) => {
asyncPayloadRecord.errors.push(e);
return null;
});
}
} catch (e) {
asyncPayloadRecord.errors.push(e);
promiseOrData = null;
}
asyncPayloadRecord.addData(promiseOrData);
exeContext.subsequentPayloads.push(asyncPayloadRecord);
}
function executeStreamField(
path,
item,
exeContext,
fieldNodes,
info,
itemType,
label,
parentContext,
) {
const asyncPayloadRecord = new AsyncPayloadRecord({
label,
path,
parentContext,
});
let completedItem;
try {
try {
if (isPromise(item)) {
completedItem = item.then((resolved) =>
completeValue(
exeContext,
itemType,
fieldNodes,
info,
path,
resolved,
asyncPayloadRecord,
),
);
} else {
completedItem = completeValue(
exeContext,
itemType,
fieldNodes,
info,
path,
item,
asyncPayloadRecord,
);
}
if (isPromise(completedItem)) {
// Note: we don't rely on a `catch` method, but we do expect "thenable"
// to take a second callback for the error case.
completedItem = completedItem.then(undefined, (rawError) => {
const error = locatedError(rawError, fieldNodes, pathToArray(path));
return handleFieldError(error, itemType, asyncPayloadRecord.errors);
});
}
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(path));
completedItem = handleFieldError(
error,
itemType,
asyncPayloadRecord.errors,
);
}
} catch (error) {
asyncPayloadRecord.errors.push(error);
asyncPayloadRecord.addData(null);
exeContext.subsequentPayloads.push(asyncPayloadRecord);
return asyncPayloadRecord;
}
if (isPromise(completedItem)) {
completedItem = completedItem.then(
(value) => [value],
(error) => {
asyncPayloadRecord.errors.push(error);
return null;
},
);
} else {
completedItem = [completedItem];
}
asyncPayloadRecord.addData(completedItem);
exeContext.subsequentPayloads.push(asyncPayloadRecord);
return asyncPayloadRecord;
}
async function executeStreamIteratorItem(
iterator,
exeContext,
fieldNodes,
info,
itemType,
asyncPayloadRecord,
fieldPath,
) {
let item;
try {
const { value, done } = await iterator.next();
if (done) {
asyncPayloadRecord.setIsCompletedIterator();
return { done, value: undefined };
}
item = value;
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(fieldPath));
const value = handleFieldError(error, itemType, asyncPayloadRecord.errors);
// don't continue if iterator throws
return { done: true, value };
}
let completedItem;
try {
completedItem = completeValue(
exeContext,
itemType,
fieldNodes,
info,
fieldPath,
item,
asyncPayloadRecord,
);
if (isPromise(completedItem)) {
completedItem = completedItem.then(undefined, (rawError) => {
const error = locatedError(
rawError,
fieldNodes,
pathToArray(fieldPath),
);
return handleFieldError(error, itemType, asyncPayloadRecord.errors);
});
}
return { done: false, value: completedItem };
} catch (rawError) {
const error = locatedError(rawError, fieldNodes, pathToArray(fieldPath));
const value = handleFieldError(error, itemType, asyncPayloadRecord.errors);
return { done: false, value };
}
}
async function executeStreamIterator(
initialIndex,
iterator,
exeContext,
fieldNodes,
info,
itemType,
path,
label,
parentContext,
) {
const subsequentPayloads = exeContext.subsequentPayloads;
let index = initialIndex;
// eslint-disable-next-line no-constant-condition
while (true) {
const fieldPath = addPath(path, index, undefined);
const asyncPayloadRecord = new AsyncPayloadRecord({
label,
path: fieldPath,
parentContext,
iterator,
});
const dataPromise = executeStreamIteratorItem(
iterator,
exeContext,
fieldNodes,
info,
itemType,
asyncPayloadRecord,
fieldPath,
);
asyncPayloadRecord.addData(
dataPromise
.then(({ value }) => value)
.then(
(value) => [value],
(err) => {
asyncPayloadRecord.errors.push(err);
return null;
},
),
);
subsequentPayloads.push(asyncPayloadRecord);
try {
// eslint-disable-next-line no-await-in-loop
const { done } = await dataPromise;
if (done) {
break;
}
} catch (err) {
// do nothing, error is already handled above
}
index++;
}
}
function yieldSubsequentPayloads(exeContext, initialResult) {
let _hasReturnedInitialResult = false;
let isDone = false;
async function race() {
if (exeContext.subsequentPayloads.length === 0) {
// async iterable resolver just finished and no more pending payloads
return {
value: {
hasNext: false,
},
done: false,
};
}
const asyncPayloadRecord = await new Promise((resolve) => {
exeContext.subsequentPayloads.forEach((payload) => {
const data = payload.getData();
if (isPromise(data)) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
data.then(() => {
resolve(payload);
});
} else {
resolve(payload);
}
});
});
const data = await asyncPayloadRecord.data;
if (exeContext.subsequentPayloads.length === 0) {
// a different call to next has exhausted all payloads
return { value: undefined, done: true };
}
const index = exeContext.subsequentPayloads.indexOf(asyncPayloadRecord);
if (index === -1) {
// a different call to next has consumed this payload
return race();
}
exeContext.subsequentPayloads.splice(index, 1);
if (asyncPayloadRecord.isCompletedIterator) {
// async iterable resolver just finished but there may be pending payloads
// return the next one
return race();
}
const returnValue = {
data,
path: asyncPayloadRecord.path ? pathToArray(asyncPayloadRecord.path) : [],
hasNext: exeContext.subsequentPayloads.length > 0,
};
if (asyncPayloadRecord.label) {
returnValue.label = asyncPayloadRecord.label;
}
if (asyncPayloadRecord.errors.length > 0) {
returnValue.errors = asyncPayloadRecord.errors;
}
return {
value: returnValue,
done: false,
};
}
return {
[Symbol.asyncIterator]() {
return this;
},
next: () => {
if (!_hasReturnedInitialResult) {
_hasReturnedInitialResult = true;
return Promise.resolve({
value: {
...initialResult,
hasNext: true,
},
done: false,
});
} else if (exeContext.subsequentPayloads.length === 0 || isDone) {
return Promise.resolve({ value: undefined, done: true });
}
return race();
},
async return() {
await Promise.all(
exeContext.subsequentPayloads.map((asyncPayloadRecord) =>
asyncPayloadRecord.iterator?.return?.(),
),
);
isDone = true;
return { value: undefined, done: true };
},
async throw(error) {
await Promise.all(
exeContext.subsequentPayloads.map((asyncPayloadRecord) =>
asyncPayloadRecord.iterator?.return?.(),
),
);
isDone = true;
return Promise.reject(error);
},
};
}
class AsyncPayloadRecord {
constructor(opts) {
this.label = opts.label;
this.path = opts.path;
this.parentContext = opts.parentContext;
this.iterator = opts.iterator;
this.errors = [];
}
addData(data) {
this.data = data;
}
getData() {
const parentData = this.parentContext?.getData();
if (parentData) {
return Promise.resolve(parentData).then(() => this.data);
}
return this.data;
}
setIsCompletedIterator() {
this.isCompletedIterator = true;
}
}

@@ -14,5 +14,2 @@ export { pathToArray as responsePathAsArray } from '../jsutils/Path';

FormattedExecutionResult,
ExecutionPatchResult,
FormattedExecutionPatchResult,
AsyncExecutionResult,
} from './execute';

@@ -19,0 +16,0 @@ export {

@@ -8,6 +8,3 @@ import type { Maybe } from './jsutils/Maybe';

import type { GraphQLSchema } from './type/schema';
import type {
AsyncExecutionResult,
ExecutionResult,
} from './execution/execute';
import type { ExecutionResult } from './execution/execute';
/**

@@ -64,5 +61,3 @@ * This is the primary entry point function for fulfilling GraphQL operations

}
export declare function graphql(
args: GraphQLArgs,
): Promise<ExecutionResult | AsyncGenerator<AsyncExecutionResult, void, void>>;
export declare function graphql(args: GraphQLArgs): Promise<ExecutionResult>;
/**

@@ -69,0 +64,0 @@ * The graphqlSync function also fulfills GraphQL operations by parsing,

@@ -1,2 +0,1 @@

import { isAsyncIterable } from './jsutils/isAsyncIterable.js';
import { isPromise } from './jsutils/isPromise.js';

@@ -20,3 +19,3 @@ import { parse } from './language/parser.js';

// Assert that the execution was synchronous.
if (isPromise(result) || isAsyncIterable(result)) {
if (isPromise(result)) {
throw new Error('GraphQL execution failed to complete synchronously.');

@@ -23,0 +22,0 @@ }

@@ -55,4 +55,2 @@ /**

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -207,2 +205,3 @@ GraphQLSpecifiedByDirective,

isSelectionNode,
isNullabilityAssertionNode,
isValueNode,

@@ -235,2 +234,6 @@ isConstValueNode,

ArgumentNode,
NullabilityAssertionNode,
NonNullAssertionNode,
ErrorBoundaryNode,
ListNullabilityOperatorNode,
ConstArgumentNode,

@@ -300,5 +303,2 @@ FragmentSpreadNode,

FormattedExecutionResult,
ExecutionPatchResult,
FormattedExecutionPatchResult,
AsyncExecutionResult,
} from './execution/index';

@@ -354,2 +354,3 @@ export {

export {
Anonymizer,
getIntrospectionQuery,

@@ -356,0 +357,0 @@ getOperationAST,

@@ -60,4 +60,2 @@ /**

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -169,2 +167,3 @@ GraphQLSpecifiedByDirective,

isSelectionNode,
isNullabilityAssertionNode,
isValueNode,

@@ -241,2 +240,3 @@ isConstValueNode,

export {
Anonymizer,
// Produce the GraphQL query recommended for a full schema introspection.

@@ -243,0 +243,0 @@ // Accepts optional IntrospectionOptions.

@@ -137,3 +137,6 @@ import type { Kind } from './kinds';

| EnumTypeExtensionNode
| InputObjectTypeExtensionNode;
| InputObjectTypeExtensionNode
| NonNullAssertionNode
| ErrorBoundaryNode
| ListNullabilityOperatorNode;
/**

@@ -216,5 +219,25 @@ * Utility type listing all nodes indexed by their kind.

readonly arguments?: ReadonlyArray<ArgumentNode>;
readonly nullabilityAssertion?: NullabilityAssertionNode;
readonly directives?: ReadonlyArray<DirectiveNode>;
readonly selectionSet?: SelectionSetNode;
}
export declare type NullabilityAssertionNode =
| NonNullAssertionNode
| ErrorBoundaryNode
| ListNullabilityOperatorNode;
export interface ListNullabilityOperatorNode {
readonly kind: Kind.LIST_NULLABILITY_OPERATOR;
readonly loc?: Location;
readonly nullabilityAssertion?: NullabilityAssertionNode;
}
export interface NonNullAssertionNode {
readonly kind: Kind.NON_NULL_ASSERTION;
readonly loc?: Location;
readonly nullabilityAssertion?: ListNullabilityOperatorNode;
}
export interface ErrorBoundaryNode {
readonly kind: Kind.ERROR_BOUNDARY;
readonly loc?: Location;
readonly nullabilityAssertion?: ListNullabilityOperatorNode;
}
export interface ArgumentNode {

@@ -221,0 +244,0 @@ readonly kind: Kind.ARGUMENT;

@@ -64,4 +64,18 @@ /**

SelectionSet: ['selections'],
Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
Field: [
'alias',
'name',
'arguments',
'directives',
'selectionSet',
// Note: Client Controlled Nullability is experimental and may be changed
// or removed in the future.
'nullabilityAssertion',
],
Argument: ['name', 'value'],
// Note: Client Controlled Nullability is experimental and may be changed
// or removed in the future.
ListNullabilityOperator: ['nullabilityAssertion'],
NonNullAssertion: ['nullabilityAssertion'],
ErrorBoundary: ['nullabilityAssertion'],
FragmentSpread: ['name', 'directives'],

@@ -68,0 +82,0 @@ InlineFragment: ['typeCondition', 'directives', 'selectionSet'],

@@ -27,2 +27,6 @@ export { Source } from './source';

FieldNode,
NullabilityAssertionNode,
NonNullAssertionNode,
ErrorBoundaryNode,
ListNullabilityOperatorNode,
ArgumentNode,

@@ -81,2 +85,3 @@ ConstArgumentNode,

isSelectionNode,
isNullabilityAssertionNode,
isValueNode,

@@ -83,0 +88,0 @@ isConstValueNode,

@@ -20,2 +20,3 @@ export { Source } from './source.js';

isSelectionNode,
isNullabilityAssertionNode,
isValueNode,

@@ -22,0 +23,0 @@ isConstValueNode,

@@ -14,2 +14,6 @@ /**

ARGUMENT = 'Argument',
/** Nullability Modifiers */
LIST_NULLABILITY_OPERATOR = 'ListNullabilityOperator',
NON_NULL_ASSERTION = 'NonNullAssertion',
ERROR_BOUNDARY = 'ErrorBoundary',
/** Fragments */

@@ -16,0 +20,0 @@ FRAGMENT_SPREAD = 'FragmentSpread',

@@ -15,2 +15,6 @@ /**

Kind['ARGUMENT'] = 'Argument';
/** Nullability Modifiers */
Kind['LIST_NULLABILITY_OPERATOR'] = 'ListNullabilityOperator';
Kind['NON_NULL_ASSERTION'] = 'NonNullAssertion';
Kind['ERROR_BOUNDARY'] = 'ErrorBoundary';
/** Fragments */

@@ -17,0 +21,0 @@ Kind['FRAGMENT_SPREAD'] = 'FragmentSpread';

@@ -64,2 +64,3 @@ import { syntaxError } from '../error/syntaxError.js';

kind === TokenKind.BANG ||
kind === TokenKind.QUESTION_MARK ||
kind === TokenKind.DOLLAR ||

@@ -238,2 +239,9 @@ kind === TokenKind.AMP ||

return createToken(lexer, TokenKind.BRACE_R, position, position + 1);
case 0x003f: // ?
return createToken(
lexer,
TokenKind.QUESTION_MARK,
position,
position + 1,
);
// StringValue

@@ -240,0 +248,0 @@ case 0x0022: // "

@@ -31,2 +31,3 @@ import type { Maybe } from '../jsutils/Maybe';

NameNode,
NullabilityAssertionNode,
ObjectFieldNode,

@@ -84,2 +85,24 @@ ObjectTypeDefinitionNode,

allowLegacyFragmentVariables?: boolean;
/**
* EXPERIMENTAL:
*
* If enabled, the parser will understand and parse Client Controlled Nullability
* Designators contained in Fields. They'll be represented in the
* `nullabilityAssertion` field of the FieldNode.
*
* The syntax looks like the following:
*
* ```graphql
* {
* nullableField!
* nonNullableField?
* nonNullableSelectionSet? {
* childField!
* }
* }
* ```
* Note: this feature is experimental and may change or be removed in the
* future.
*/
experimentalClientControlledNullability?: boolean;
}

@@ -218,2 +241,3 @@ /**

parseField(): FieldNode;
parseNullabilityAssertion(): NullabilityAssertionNode | undefined;
/**

@@ -220,0 +244,0 @@ * Arguments[Const] : ( Argument[?Const]+ )

@@ -302,2 +302,5 @@ import { syntaxError } from '../error/syntaxError.js';

arguments: this.parseArguments(false),
// Experimental support for Client Controlled Nullability changes
// the grammar of Field:
nullabilityAssertion: this.parseNullabilityAssertion(),
directives: this.parseDirectives(false),

@@ -309,2 +312,32 @@ selectionSet: this.peek(TokenKind.BRACE_L)

}
// TODO: add grammar comment after it finalizes
parseNullabilityAssertion() {
// Note: Client Controlled Nullability is experimental and may be changed or
// removed in the future.
if (this._options?.experimentalClientControlledNullability !== true) {
return undefined;
}
const start = this._lexer.token;
let nullabilityAssertion;
if (this.expectOptionalToken(TokenKind.BRACKET_L)) {
const innerModifier = this.parseNullabilityAssertion();
this.expectToken(TokenKind.BRACKET_R);
nullabilityAssertion = this.node(start, {
kind: Kind.LIST_NULLABILITY_OPERATOR,
nullabilityAssertion: innerModifier,
});
}
if (this.expectOptionalToken(TokenKind.BANG)) {
nullabilityAssertion = this.node(start, {
kind: Kind.NON_NULL_ASSERTION,
nullabilityAssertion,
});
} else if (this.expectOptionalToken(TokenKind.QUESTION_MARK)) {
nullabilityAssertion = this.node(start, {
kind: Kind.ERROR_BOUNDARY,
nullabilityAssertion,
});
}
return nullabilityAssertion;
}
parseArguments(isConst) {

@@ -311,0 +344,0 @@ const item = isConst ? this.parseConstArgument : this.parseArgument;

@@ -6,2 +6,3 @@ import type {

ExecutableDefinitionNode,
NullabilityAssertionNode,
SelectionNode,

@@ -20,2 +21,5 @@ TypeDefinitionNode,

export declare function isSelectionNode(node: ASTNode): node is SelectionNode;
export declare function isNullabilityAssertionNode(
node: ASTNode,
): node is NullabilityAssertionNode;
export declare function isValueNode(node: ASTNode): node is ValueNode;

@@ -22,0 +26,0 @@ export declare function isConstValueNode(node: ASTNode): node is ConstValueNode;

@@ -22,2 +22,9 @@ import { Kind } from './kinds.js';

}
export function isNullabilityAssertionNode(node) {
return (
node.kind === Kind.LIST_NULLABILITY_OPERATOR ||
node.kind === Kind.NON_NULL_ASSERTION ||
node.kind === Kind.ERROR_BOUNDARY
);
}
export function isValueNode(node) {

@@ -24,0 +31,0 @@ return (

@@ -45,4 +45,11 @@ import { printBlockString } from './blockString.js';

Field: {
leave({ alias, name, arguments: args, directives, selectionSet }) {
const prefix = wrap('', alias, ': ') + name;
leave({
alias,
name,
arguments: args,
nullabilityAssertion,
directives,
selectionSet,
}) {
const prefix = join([wrap('', alias, ': '), name], '');
let argsLine = prefix + wrap('(', join(args, ', '), ')');

@@ -52,6 +59,29 @@ if (argsLine.length > MAX_LINE_LENGTH) {

}
return join([argsLine, join(directives, ' '), selectionSet], ' ');
return join([
argsLine,
// Note: Client Controlled Nullability is experimental and may be
// changed or removed in the future.
nullabilityAssertion,
wrap(' ', join(directives, ' ')),
wrap(' ', selectionSet),
]);
},
},
Argument: { leave: ({ name, value }) => name + ': ' + value },
// Nullability Modifiers
ListNullabilityOperator: {
leave({ nullabilityAssertion }) {
return join(['[', nullabilityAssertion, ']']);
},
},
NonNullAssertion: {
leave({ nullabilityAssertion }) {
return join([nullabilityAssertion, '!']);
},
},
ErrorBoundary: {
leave({ nullabilityAssertion }) {
return join([nullabilityAssertion, '?']);
},
},
// Fragments

@@ -58,0 +88,0 @@ FragmentSpread: {

@@ -9,2 +9,3 @@ /**

BANG = '!',
QUESTION_MARK = '?',
DOLLAR = '$',

@@ -11,0 +12,0 @@ AMP = '&',

@@ -10,2 +10,3 @@ /**

TokenKind['BANG'] = '!';
TokenKind['QUESTION_MARK'] = '?';
TokenKind['DOLLAR'] = '$';

@@ -12,0 +13,0 @@ TokenKind['AMP'] = '&';

{
"name": "graphql",
"version": "17.0.0-alpha.1.canary.pr.3659.cef660554446d49cec9a0958afb9690dd0b19193",
"version": "17.0.0-alpha.1.canary.pr.3673.53c289997f206acd10388d6a574341c68cc1a30e",
"description": "A Query Language and Runtime which can target any service.",

@@ -35,3 +35,3 @@ "license": "MIT",

"publishConfig": {
"tag": "canary-pr-3659"
"tag": "canary-pr-3673"
},

@@ -50,3 +50,3 @@ "type": "module",

},
"deprecated": "You are using canary version build from https://github.com/graphql/graphql-js/pull/3659, no gurantees provided so please use your own discretion."
"deprecated": "You are using canary version build from https://github.com/graphql/graphql-js/pull/3673, no gurantees provided so please use your own discretion."
}

@@ -68,10 +68,2 @@ import type { Maybe } from '../jsutils/Maybe';

/**
* Used to conditionally defer fragments.
*/
export declare const GraphQLDeferDirective: GraphQLDirective;
/**
* Used to conditionally stream list fields.
*/
export declare const GraphQLStreamDirective: GraphQLDirective;
/**
* Constant string used for default reason for a deprecation.

@@ -78,0 +70,0 @@ */

@@ -11,3 +11,3 @@ import { inspect } from '../jsutils/inspect.js';

} from './definition.js';
import { GraphQLBoolean, GraphQLInt, GraphQLString } from './scalars.js';
import { GraphQLBoolean, GraphQLString } from './scalars.js';
/**

@@ -102,48 +102,2 @@ * Test if the given value is a GraphQL directive.

/**
* Used to conditionally defer fragments.
*/
export const GraphQLDeferDirective = new GraphQLDirective({
name: 'defer',
description:
'Directs the executor to defer this fragment when the `if` argument is true or undefined.',
locations: [
DirectiveLocation.FRAGMENT_SPREAD,
DirectiveLocation.INLINE_FRAGMENT,
],
args: {
if: {
type: GraphQLBoolean,
description: 'Deferred when true or undefined.',
},
label: {
type: GraphQLString,
description: 'Unique name',
},
},
});
/**
* Used to conditionally stream list fields.
*/
export const GraphQLStreamDirective = new GraphQLDirective({
name: 'stream',
description:
'Directs the executor to stream plural fields when the `if` argument is true or undefined.',
locations: [DirectiveLocation.FIELD],
args: {
if: {
type: GraphQLBoolean,
description: 'Stream when true or undefined.',
},
label: {
type: GraphQLString,
description: 'Unique name',
},
initialCount: {
defaultValue: 0,
type: GraphQLInt,
description: 'Number of items to return immediately',
},
},
});
/**
* Constant string used for default reason for a deprecation.

@@ -150,0 +104,0 @@ */

@@ -116,4 +116,2 @@ export type { Path as ResponsePath } from '../jsutils/Path';

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -120,0 +118,0 @@ GraphQLSpecifiedByDirective,

@@ -76,4 +76,2 @@ export {

GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,

@@ -80,0 +78,0 @@ GraphQLSpecifiedByDirective,

@@ -0,1 +1,2 @@

export { Anonymizer } from './Anonymizer';
export { getIntrospectionQuery } from './getIntrospectionQuery';

@@ -2,0 +3,0 @@ export type {

@@ -0,1 +1,2 @@

export { Anonymizer } from './Anonymizer.js';
// Produce the GraphQL query recommended for a full schema introspection.

@@ -2,0 +3,0 @@ export { getIntrospectionQuery } from './getIntrospectionQuery.js';

@@ -5,4 +5,2 @@ export { validate } from './validate';

export { specifiedRules } from './specifiedRules';
export { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule';
export { DeferStreamDirectiveOnRootFieldRule } from './rules/DeferStreamDirectiveOnRootFieldRule';
export { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule';

@@ -25,3 +23,2 @@ export { FieldsOnCorrectTypeRule } from './rules/FieldsOnCorrectTypeRule';

export { SingleFieldSubscriptionsRule } from './rules/SingleFieldSubscriptionsRule';
export { StreamDirectiveOnListFieldRule } from './rules/StreamDirectiveOnListFieldRule';
export { UniqueArgumentNamesRule } from './rules/UniqueArgumentNamesRule';

@@ -28,0 +25,0 @@ export { UniqueDirectivesPerLocationRule } from './rules/UniqueDirectivesPerLocationRule';

@@ -5,6 +5,2 @@ export { validate } from './validate.js';

export { specifiedRules } from './specifiedRules.js';
// Spec Section: "Defer And Stream Directive Labels Are Unique"
export { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule.js';
// Spec Section: "Defer And Stream Directives Are Used On Valid Root Field"
export { DeferStreamDirectiveOnRootFieldRule } from './rules/DeferStreamDirectiveOnRootFieldRule.js';
// Spec Section: "Executable Definitions"

@@ -44,4 +40,2 @@ export { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule.js';

export { SingleFieldSubscriptionsRule } from './rules/SingleFieldSubscriptionsRule.js';
// Spec Section: "Stream Directives Are Used On List Fields"
export { StreamDirectiveOnListFieldRule } from './rules/StreamDirectiveOnListFieldRule.js';
// Spec Section: "Argument Uniqueness"

@@ -48,0 +42,0 @@ export { UniqueArgumentNamesRule } from './rules/UniqueArgumentNamesRule.js';

@@ -530,12 +530,2 @@ import { inspect } from '../../jsutils/inspect.js';

}
// FIXME https://github.com/graphql/graphql-js/issues/2203
const directives1 = /* c8 ignore next */ node1.directives ?? [];
const directives2 = /* c8 ignore next */ node2.directives ?? [];
if (!sameStreams(directives1, directives2)) {
return [
[responseName, 'they have differing stream directives'],
[node1],
[node2],
];
}
// The return type for each field.

@@ -588,18 +578,2 @@ const type1 = def1?.type;

}
function getStreamDirective(directives) {
return directives.find((directive) => directive.name.value === 'stream');
}
function sameStreams(directives1, directives2) {
const stream1 = getStreamDirective(directives1);
const stream2 = getStreamDirective(directives2);
if (!stream1 && !stream2) {
// both fields do not have streams
return true;
} else if (stream1 && stream2) {
// check if both fields have equivalent streams
return stringifyArguments(stream1) === stringifyArguments(stream2);
}
// fields have a mix of stream and no stream
return false;
}
// Two types conflict if both types could not apply to a value simultaneously.

@@ -606,0 +580,0 @@ // Composite types are ignored as their individual field types will be compared

@@ -28,3 +28,3 @@ import { GraphQLError } from '../../error/GraphQLError.js';

}
const { fields } = collectFields(
const fields = collectFields(
schema,

@@ -31,0 +31,0 @@ fragments,

@@ -1,5 +0,1 @@

// Spec Section: "Defer And Stream Directive Labels Are Unique"
import { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule.js';
// Spec Section: "Defer And Stream Directives Are Used On Valid Root Field"
import { DeferStreamDirectiveOnRootFieldRule } from './rules/DeferStreamDirectiveOnRootFieldRule.js';
// Spec Section: "Executable Definitions"

@@ -48,4 +44,2 @@ import { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule.js';

import { SingleFieldSubscriptionsRule } from './rules/SingleFieldSubscriptionsRule.js';
// Spec Section: "Stream Directives Are Used On List Fields"
import { StreamDirectiveOnListFieldRule } from './rules/StreamDirectiveOnListFieldRule.js';
import { UniqueArgumentDefinitionNamesRule } from './rules/UniqueArgumentDefinitionNamesRule.js';

@@ -101,5 +95,2 @@ // Spec Section: "Argument Uniqueness"

UniqueDirectivesPerLocationRule,
DeferStreamDirectiveOnRootFieldRule,
DeferStreamDirectiveLabelRule,
StreamDirectiveOnListFieldRule,
KnownArgumentNamesRule,

@@ -106,0 +97,0 @@ UniqueArgumentNamesRule,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc