sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
1,428 lines • 60.2 kB
JavaScript
import { upperFirst, uniqBy, startCase, flatten, get } from "lodash-es";
import oneline from "oneline";
import { hideBin } from "yargs/helpers";
import yargs from "yargs/yargs";
import { getClientUrl, debug } from "./_internal.js";
import { getIt } from "get-it";
import { promise } from "get-it/middleware";
import { generateHelpUrl } from "./generate-help-url.esm.js";
import { Schema } from "@sanity/schema";
import { isDeprecationConfiguration } from "@sanity/types";
import logSymbols from "log-symbols";
import pluralize from "pluralize-esm";
import { getGraphQLAPIs } from "./getGraphQLAPIs.js";
const request = getIt([promise()]);
class HttpError extends Error {
constructor(message) {
super(message), this.name = "HttpError";
}
}
async function getUrlHeaders(url, headers = {}) {
const response = await request({
url,
stream: !0,
maxRedirects: 0,
method: "HEAD",
headers
});
if (response.statusCode >= 400) {
const error = new HttpError(`Request returned HTTP ${response.statusCode}`);
throw error.statusCode = response.statusCode, error;
}
return response.body.resume(), response.headers;
}
const SCHEMA_LIFT_ANONYMOUS_OBJECT_TYPE = "schema-lift-anonymous-object-type", consoleOutputter = {
error: (...args) => console.error(...args)
};
class SchemaError extends Error {
constructor(problemGroups) {
super("Schema errors encountered"), this.name = "SchemaError", this.problemGroups = problemGroups;
}
print(output) {
(output || consoleOutputter).error(`Uh oh\u2026 found errors in schema:
`), this.problemGroups.forEach((group) => {
group.problems.forEach((problem) => {
const icon = logSymbols[problem.severity] || logSymbols.info;
output.error(` ${icon} ${upperFirst(problem.severity)}: ${getPath(group.path)}`), output.error(` ${problem.message}`), problem.helpId && output.error(` See ${generateHelpUrl(problem.helpId)}`), output.error("");
});
});
}
}
function getPath(path) {
return path.map((segment) => segment.kind === "type" && segment.name && segment.type ? `${segment.name} - (${segment.type})` : segment.kind === "property" && segment.name ? segment.name : null).filter(Boolean).join(" / ");
}
const skipTypes = ["document", "reference"], allowedJsonTypes = ["object", "array"], disallowedCustomizedMembers = ["object", "array", "image", "file", "block"], disabledBlockFields = ["markDefs"], scalars = ["string", "number", "boolean"], internal = /* @__PURE__ */ Symbol("internal");
function getBaseType(baseSchema, typeName) {
return typeName === "crossDatasetReference" ? Schema.compile({
types: [{
name: "__placeholder__",
type: "crossDatasetReference",
// Just needs _something_ to refer to, doesn't matter what
to: [{
type: "sanity.imageAsset"
}]
}],
parent: baseSchema
}).get("__placeholder__") : typeName === "globalDocumentReference" ? Schema.compile({
types: [{
name: "__placeholder__",
type: "globalDocumentReference",
// Just needs _something_ to refer to, doesn't matter what
to: [{
type: "sanity.imageAsset"
}]
}],
parent: baseSchema
}).get("__placeholder__") : Schema.compile({
types: [{
name: "__placeholder__",
type: typeName,
options: {
hotspot: !0
}
}],
parent: baseSchema
}).get("__placeholder__");
}
function getTypeName(str) {
const name = startCase(str).replace(/\s+/g, "");
return name === "Number" ? "Float" : name;
}
function isBaseType(type) {
return type.name !== type.jsonType && allowedJsonTypes.includes(type.jsonType) && !skipTypes.includes(type.name) && !isReference(type);
}
function isBlockType(typeDef) {
return typeDef.name === "block" ? !0 : typeDef.type ? isBlockType(typeDef.type) : !1;
}
function hasBlockParent(typeDef) {
return typeDef.type && typeDef.type.name === "block" && !typeDef.type.type ? !0 : !!(typeDef.type && hasBlockParent(typeDef.type));
}
function isArrayOfBlocks(typeDef) {
const type = typeDef.type || typeDef;
return !("jsonType" in type) || type.jsonType !== "array" ? !1 : (type.of || []).some(hasBlockParent);
}
function isType(typeDef, typeName) {
let type = typeDef;
for (; type; ) {
if (type.name === typeName || type.type && type.type.name === typeName)
return !0;
type = type.type;
}
return !1;
}
function isReference(typeDef) {
return isType(typeDef, "reference");
}
function isCrossDatasetReference(typeDef) {
return isType(typeDef, "crossDatasetReference");
}
function getCrossDatasetReferenceMetadata(typeDef) {
if (!isCrossDatasetReference(typeDef)) return;
function getTypeNames(type) {
if (type)
return "to" in type ? type.to.map((t) => t.type).filter((t) => typeof t == "string") : getTypeNames(type.type);
}
function getDataset(type) {
if (type) {
if ("dataset" in type && typeof type.dataset == "string") return type.dataset;
if (type.type) return getDataset(type.type);
}
}
const typeNames = getTypeNames(typeDef);
if (!typeNames) return;
const dataset = getDataset(typeDef);
if (typeof dataset == "string")
return {
typeNames,
dataset
};
}
function extractFromSanitySchema(sanitySchema, extractOptions = {}) {
const {
nonNullDocumentFields,
withUnionCache
} = extractOptions, unionRecursionGuards = /* @__PURE__ */ new Set(), unionDefinitionCache = /* @__PURE__ */ new Map();
if (sanitySchema._validation && sanitySchema._validation.some((group) => group.problems.some((problem) => problem.severity === "error")) && Array.isArray(sanitySchema._validation))
throw new SchemaError(sanitySchema._validation);
const sanityTypes = sanitySchema._original?.types || [], typeNames = sanitySchema.getTypeNames(), unionTypes = [], types = [];
for (const typeName of typeNames) {
const schemaType = sanitySchema.get(typeName);
if (schemaType === void 0 || !isBaseType(schemaType))
continue;
const convertedType = convertType(schemaType);
types.push(convertedType);
}
return {
types: [...types, ...unionTypes],
interfaces: [getDocumentInterfaceDefinition()]
};
function isTopLevelType(typeName) {
return typeNames.includes(typeName);
}
function mapFieldType(field) {
if (!field.type)
throw new Error("Field has no type!");
const jsonType = "jsonType" in field ? field.jsonType : "", isScalar = scalars.includes(jsonType);
if (isScalar && jsonType === "number")
return hasValidationFlag(field, "integer") ? "Int" : "Float";
if (isScalar)
return getTypeName(jsonType);
const type = field.type.type || field.type;
if (type.type)
return mapFieldType(type);
switch (type.name) {
case "number":
return hasValidationFlag(field, "integer") ? "Int" : "Float";
default:
return getTypeName(type.name);
}
}
function isArrayType(type) {
return !!("jsonType" in type && type.jsonType === "array" || type.type && type.type.jsonType === "array");
}
function _convertType(type, parent, options) {
let name;
return type.type ? name = type.type.name : "jsonType" in type && (name = type.jsonType), isReference(type) ? getReferenceDefinition(type) : isArrayType(type) ? getArrayDefinition(type, parent, options) : name === "document" ? getDocumentDefinition(type) : name === "block" || name === "object" || hasFields(type) ? getObjectDefinition(type, parent) : {
type: mapFieldType(type),
description: getDescription(type)
};
}
function convertType(type, parent, props = {}) {
const mapped = _convertType(type, parent || "", {
isField: !!props.fieldName
}), gqlName = props.fieldName || mapped.name, originalName = type.name, original = gqlName === originalName ? {} : {
originalName
}, crossDatasetReferenceMetadata = getCrossDatasetReferenceMetadata(type);
return {
...getDeprecation$1(type.type),
...props,
...mapped,
...original,
...crossDatasetReferenceMetadata && {
crossDatasetReferenceMetadata
}
};
}
function isField(def) {
return !("jsonType" in def) || !def.jsonType;
}
function getObjectDefinition(def, parent) {
const isInline = isField(def), isDocument = def.type ? def.type.name === "document" : !1, actualType = isInline ? def.type : def;
if (typeNeedsHoisting(actualType))
throw createLiftTypeError(def.name, parent || "", actualType.name);
if (isInline && parent && def.type.name === "object")
throw createLiftTypeError(def.name, parent);
if (parent && def.type && isTopLevelType(def.type.name))
return {
type: getTypeName(def.type.name)
};
const name = `${parent || ""}${getTypeName(def.name)}`, fields = collectFields(def), firstUnprefixed = Math.max(0, fields.findIndex((field) => field.name[0] !== "_")), keyField = createStringField("_key");
fields.splice(firstUnprefixed, 0, keyField), isDocument || fields.splice(firstUnprefixed + 1, 0, createStringField("_type"));
const objectFields = isBlockType(def) ? fields.filter((field) => !disabledBlockFields.includes(field.name)) : fields;
return {
kind: "Type",
name,
type: "Object",
description: getDescription(def),
fields: objectFields.map((field) => isArrayOfBlocks(field) ? buildRawField(field, name) : convertType(field, name, {
fieldName: field.name,
...getDeprecation$1(def)
})),
[internal]: {
...getDeprecation$1(def)
}
};
}
function buildRawField(field, parentName) {
return {
...convertType(field, parentName, {
fieldName: `${field.name}Raw`
}),
type: "JSON",
isRawAlias: !0
};
}
function createStringField(name) {
return {
name,
type: {
jsonType: "string",
name: "string",
type: {
name: "string",
type: void 0,
jsonType: "string"
}
}
};
}
function collectFields(def) {
const fields = gatherAllFields(def);
if (fields.length > 0)
return fields;
const extended = getBaseType(sanitySchema, def.name);
return gatherAllFields(extended);
}
function getReferenceDefinition(def, parent) {
const base = {
description: getDescription(def),
isReference: !0
}, candidates = arrayify(gatherAllReferenceCandidates(def));
if (candidates.length === 0)
throw new Error("No candidates for reference");
if (candidates.length === 1)
return {
type: getTypeName(candidates[0].type.name),
...base
};
const allTypeNames = candidates.map((c) => getTypeName(c.type.name)), targetTypes = [...new Set(allTypeNames)].sort(), name = targetTypes.join("Or");
return unionTypes.some((item) => item.name === name) || unionTypes.push({
kind: "Union",
name,
types: targetTypes
}), {
type: name,
...base
};
}
function getArrayDefinition(def, parent, options = {}) {
const base = {
description: getDescription(def),
kind: "List"
}, name = !options.isField && def.name ? {
name: getTypeName(def.name)
} : {}, candidates = def.type?.type && "of" in def.type ? arrayify(def.type.of) : def.of;
return candidates.length === 1 ? {
children: getArrayChildDefinition(candidates[0], def),
...base,
...name
} : {
children: getUnionDefinition(candidates, def, {
grandParent: parent
}),
...base,
...name
};
}
function getArrayChildDefinition(child, arrayDef) {
if (typeNeedsHoisting(child))
throw createLiftTypeError(child.name, arrayDef.name);
return isReference(child) ? getReferenceDefinition(child) : scalars.includes(child.jsonType) && !scalars.includes(child.name) ? {
type: mapFieldType(child)
} : {
type: getTypeName(child.name)
};
}
function typeNeedsHoisting(type) {
return !!(type.name === "object" || type.jsonType === "object" && !isTopLevelType(type.name) || type.isCustomized && !isTopLevelType(type.name) || type.isCustomized && disallowedCustomizedMembers.includes(type.name));
}
function getUnionDefinition(candidates, parent, options = {}) {
if (candidates.length < 2)
throw new Error("Not enough candidates for a union type");
const guardPathName = `${typeof parent == "object" ? parent.name : parent}`;
if (unionRecursionGuards.has(guardPathName))
return {};
const unionCacheKey = `${options.grandParent}-${guardPathName}-${candidates.map((c) => c.type?.name).join("-")}`;
if (withUnionCache && unionDefinitionCache.has(unionCacheKey))
return unionDefinitionCache.get(unionCacheKey);
try {
unionRecursionGuards.add(guardPathName), candidates.forEach((def, i) => {
if (typeNeedsHoisting(def))
throw createLiftTypeArrayError(i, parent.name, def.type ? def.type.name : def.name, options.grandParent);
});
const converted = candidates.map((def) => convertType(def)), getName = (def) => typeof def.type == "string" ? def.type : def.type.name, flattened = converted.reduce((acc, candidate) => {
const union = unionTypes.find((item) => item.name === candidate.type);
return union ? acc.concat(union.types.map((type) => ({
type,
isReference: candidate.isReference
}))) : acc.concat(candidate);
}, []);
let allCandidatesAreDocuments = !0;
const refs = [], inlineObjs = [], allTypeNames = [];
for (const def of flattened) {
def.isReference && refs.push(def.type), isReference || inlineObjs.push(def.name || "");
const typeName = typeof def.type == "string" ? def.type : def.type.name;
(def.name || def.type) && allTypeNames.push(def.isReference ? typeName : def.name || "");
const typeDef = sanityTypes.find((type) => type.name === getName(def));
(!typeDef || typeDef.type !== "document") && (allCandidatesAreDocuments = !1);
}
const interfaces = allCandidatesAreDocuments ? ["Document"] : void 0, possibleTypes = [...new Set(allTypeNames)].sort();
if (possibleTypes.length < 2)
throw new Error(`Not enough types for a union type. Parent: ${parent.name}`);
const name = possibleTypes.join("Or");
unionTypes.some((item) => item.name === name) || unionTypes.push({
kind: "Union",
name,
types: possibleTypes,
interfaces
});
const references = refs.length > 0 ? refs : void 0, inlineObjects = inlineObjs.length > 0 ? inlineObjs : void 0, unionDefinition = isReference(parent) ? {
type: name,
references
} : {
type: name,
references,
inlineObjects
};
return unionDefinitionCache.set(unionCacheKey, unionDefinition), unionDefinition;
} finally {
unionRecursionGuards.delete(guardPathName);
}
}
function getDocumentDefinition(def) {
const objectDef = getObjectDefinition(def), fields = getDocumentInterfaceFields(def).concat(objectDef.fields);
return {
...objectDef,
fields,
interfaces: ["Document"]
};
}
function getDocumentInterfaceDefinition() {
return {
kind: "Interface",
name: "Document",
description: "A Sanity document",
fields: getDocumentInterfaceFields()
};
}
function getDocumentInterfaceFields(type) {
const isNullable = typeof nonNullDocumentFields == "boolean" ? !nonNullDocumentFields : !0;
return [{
fieldName: "_id",
type: "ID",
isNullable,
description: "Document ID",
...getDeprecation$1(type)
}, {
fieldName: "_type",
type: "String",
isNullable,
description: "Document type",
...getDeprecation$1(type)
}, {
fieldName: "_createdAt",
type: "Datetime",
isNullable,
description: "Date the document was created",
...getDeprecation$1(type)
}, {
fieldName: "_updatedAt",
type: "Datetime",
isNullable,
description: "Date the document was last modified",
...getDeprecation$1(type)
}, {
fieldName: "_rev",
type: "String",
isNullable,
description: "Current document revision",
...getDeprecation$1(type)
}];
}
function arrayify(thing) {
return Array.isArray(thing) ? thing : thing === null || typeof thing > "u" ? [] : [thing];
}
function hasValidationFlag(field, flag) {
return "validation" in field && Array.isArray(field.validation) && field.validation.some((rule) => rule && "_rules" in rule && rule._rules.some((item) => item.flag === flag));
}
function getDescription(type) {
const description = type.type && type.type.description;
return typeof description == "string" ? description : void 0;
}
function gatherAllReferenceCandidates(type) {
const allFields = gatherReferenceCandidates(type);
return uniqBy(allFields, "name");
}
function gatherReferenceCandidates(type) {
const refTo = "to" in type ? type.to : [];
return "type" in type && type.type ? [...gatherReferenceCandidates(type.type), ...refTo] : refTo;
}
function gatherAllFields(type) {
const allFields = gatherFields(type);
return uniqBy(allFields, "name");
}
function gatherFields(type) {
return "fields" in type ? type.type ? gatherFields(type.type).concat(type.fields) : type.fields : [];
}
function hasFieldsLikeShape(type) {
return typeof type == "object" && type !== null && "fields" in type;
}
function hasArrayOfFields(type) {
return hasFieldsLikeShape(type) && Array.isArray(type.fields);
}
function hasFields(type) {
return hasArrayOfFields(type) ? gatherAllFields(type).length > 0 : "type" in type && type.type ? hasFields(type.type) : !1;
}
}
function createLiftTypeArrayError(index, parent, inlineType = "object", grandParent = "") {
const helpUrl = generateHelpUrl(SCHEMA_LIFT_ANONYMOUS_OBJECT_TYPE), context = [grandParent, parent].filter(Boolean).join("/");
return new HelpfulError(oneline`
Encountered anonymous inline ${inlineType} at index ${index} for type/field ${context}.
To use this type with GraphQL you will need to create a top-level schema type for it.
See ${helpUrl}`, helpUrl);
}
function createLiftTypeError(typeName, parent, inlineType = "object") {
const helpUrl = generateHelpUrl(SCHEMA_LIFT_ANONYMOUS_OBJECT_TYPE);
return new HelpfulError(oneline`
Encountered anonymous inline ${inlineType} "${typeName}" for field/type "${parent}".
To use this field with GraphQL you will need to create a top-level schema type for it.
See ${helpUrl}`, helpUrl);
}
class HelpfulError extends Error {
constructor(message, helpUrl) {
super(message), this.name = "HelpfulError", this.helpUrl = helpUrl;
}
}
function getDeprecation$1(type) {
return isDeprecationConfiguration(type) ? {
deprecationReason: type.deprecated.reason
} : {};
}
function isUnion(type) {
return type.kind === "Union";
}
function isNonUnion(type) {
return !isUnion(type) && "type" in type;
}
function isDocumentType(type) {
return isNonUnion(type) && type.type === "Object" && Array.isArray(type.interfaces) && type.interfaces.includes("Document");
}
const filterCreators$2 = {
ID: createIdFilters$1,
String: createStringFilters$1,
Url: createStringFilters$1,
Float: createNumberFilters,
Integer: createNumberFilters,
Boolean: createBooleanFilters$1,
Datetime: createDateFilters$1,
Date: createDateFilters$1,
Object: createObjectFilters
};
function generateTypeFilters$2(types) {
return types.filter(isNonUnion).filter((type) => type.type === "Object" && type.interfaces && type.interfaces.includes("Document")).map((type) => {
const name = `${type.name}Filter`, fields = flatten(type.fields.map(createFieldFilters$2)).filter(Boolean);
return {
name,
kind: "InputObject",
fields: [...fields, ...getDocumentFilters$2()]
};
});
}
function createFieldFilters$2(field) {
return filterCreators$2[field.type] ? filterCreators$2[field.type](field) : field.kind === "List" ? createListFilters() : field.isReference ? createReferenceFilters(field) : createInlineTypeFilters();
}
function getFieldName(field, modifier = "") {
const suffix = modifier ? `_${modifier}` : "";
return `${field.fieldName}${suffix}`;
}
function getDocumentFilters$2() {
return [{
fieldName: "references",
type: "ID",
description: "All documents references the given document ID",
constraint: {
comparator: "REFERENCES"
}
}, {
fieldName: "is_draft",
type: "Boolean",
description: "All documents that are drafts",
constraint: {
field: "_id",
comparator: "IS_DRAFT"
}
}];
}
function createIsDefinedFilter(field) {
return {
fieldName: getFieldName(field, "is_defined"),
type: "Boolean",
description: "All documents that have a value for this field",
constraint: {
field: field.fieldName,
comparator: "IS_DEFINED"
}
};
}
function createEqualityFilter(field) {
return {
fieldName: getFieldName(field),
type: field.type,
description: "All documents that are equal to given value",
constraint: {
field: field.fieldName,
comparator: "EQUALS"
}
};
}
function createInequalityFilter(field) {
return {
fieldName: getFieldName(field, "not"),
type: field.type,
description: "All documents that are not equal to given value",
constraint: {
field: field.fieldName,
comparator: "NOT_EQUALS"
}
};
}
function createDefaultFilters(field) {
return [createEqualityFilter(field), createInequalityFilter(field), createIsDefinedFilter(field)];
}
function createGtLtFilters(field) {
return [{
fieldName: getFieldName(field, "lt"),
type: field.type,
description: "All documents are less than given value",
constraint: {
field: field.fieldName,
comparator: "LT"
}
}, {
fieldName: getFieldName(field, "lte"),
type: field.type,
description: "All documents are less than or equal to given value",
constraint: {
field: field.fieldName,
comparator: "LTE"
}
}, {
fieldName: getFieldName(field, "gt"),
type: field.type,
description: "All documents are greater than given value",
constraint: {
field: field.fieldName,
comparator: "GT"
}
}, {
fieldName: getFieldName(field, "gte"),
type: field.type,
description: "All documents are greater than or equal to given value",
constraint: {
field: field.fieldName,
comparator: "GTE"
}
}];
}
function createBooleanFilters$1(field) {
return createDefaultFilters(field);
}
function createIdFilters$1(field) {
return createStringFilters$1(field);
}
function createDateFilters$1(field) {
return createDefaultFilters(field).concat(createGtLtFilters(field));
}
function createStringFilters$1(field) {
return [...createDefaultFilters(field), {
fieldName: getFieldName(field, "matches"),
type: "String",
description: "All documents contain (match) the given word/words",
constraint: {
field: field.fieldName,
comparator: "MATCHES"
}
}, {
fieldName: getFieldName(field, "in"),
kind: "List",
children: {
type: "String",
isNullable: !1
},
description: "All documents match one of the given values",
constraint: {
field: field.fieldName,
comparator: "IN"
}
}, {
fieldName: getFieldName(field, "not_in"),
kind: "List",
children: {
type: "String",
isNullable: !1
},
description: "None of the values match any of the given values",
constraint: {
field: field.fieldName,
comparator: "NOT_IN"
}
}];
}
function createNumberFilters(field) {
return createDefaultFilters(field).concat(createGtLtFilters(field));
}
function createObjectFilters(field) {
return [];
}
function createListFilters() {
return [];
}
function createInlineTypeFilters() {
return [];
}
function createReferenceFilters(field) {
return [{
fieldName: getFieldName(field),
type: "ID",
constraint: {
field: `${field.fieldName}._ref`,
comparator: "EQUALS"
}
}];
}
function pluralizeTypeName(name) {
const words = startCase(name).split(" "), last = words[words.length - 1], plural = pluralize(last.toLowerCase()).replace(/(\d)s$/g, "$1S");
return words[words.length - 1] = upperFirst(plural), words.join("");
}
function generateTypeQueries$2(types, filters) {
const queries = [], queryable = types.filter(isNonUnion).filter((type) => type.type === "Object" && type.interfaces && type.interfaces.includes("Document"));
return queryable.forEach((type) => {
queries.push({
fieldName: type.name,
type: type.name,
constraints: [{
field: "_id",
comparator: "EQUALS",
value: {
kind: "argumentValue",
argName: "id"
}
}],
args: [{
name: "id",
description: `${type.name} document ID`,
type: "ID",
isNullable: !1
}]
});
}), queryable.forEach((type) => {
const filterName = `${type.name}Filter`, hasFilter = filters.find((filter) => filter.name === filterName);
queries.push({
fieldName: `all${pluralizeTypeName(type.name)}`,
filter: `_type == "${type.originalName || type.name}"`,
type: {
kind: "List",
isNullable: !1,
children: {
type: type.name,
isNullable: !1
}
},
args: hasFilter ? [{
name: "where",
type: filterName,
isFieldFilter: !0
}, ...getLimitOffsetArgs()] : getLimitOffsetArgs()
});
}), queries;
}
function getLimitOffsetArgs() {
return [{
name: "limit",
type: "Int",
description: "Max documents to return",
isFieldFilter: !1
}, {
name: "offset",
type: "Int",
description: "Offset at which to start returning documents from",
isFieldFilter: !1
}];
}
var gen1 = (extracted) => {
const filters = generateTypeFilters$2(extracted.types), queries = generateTypeQueries$2(extracted.types, filters);
return {
types: [...extracted.types, ...filters],
queries,
interfaces: extracted.interfaces,
generation: "gen1"
};
};
function createBooleanFilters() {
return {
name: "BooleanFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "Boolean",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "Boolean",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "is_defined",
type: "Boolean",
description: "Checks if the value is defined."
}]
};
}
function createDateFilters() {
return {
name: "DateFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "Date",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "Date",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "gt",
type: "Date",
description: "Checks if the value is greater than the given input."
}, {
fieldName: "gte",
type: "Date",
description: "Checks if the value is greater than or equal to the given input."
}, {
fieldName: "lt",
type: "Date",
description: "Checks if the value is lesser than the given input."
}, {
fieldName: "lte",
type: "Date",
description: "Checks if the value is lesser than or equal to the given input."
}, {
fieldName: "is_defined",
type: "Boolean",
description: "Checks if the value is defined."
}]
};
}
function createDateTimeFilters() {
return {
name: "DatetimeFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "Datetime",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "Datetime",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "gt",
type: "Datetime",
description: "Checks if the value is greater than the given input."
}, {
fieldName: "gte",
type: "Datetime",
description: "Checks if the value is greater than or equal to the given input."
}, {
fieldName: "lt",
type: "Datetime",
description: "Checks if the value is lesser than the given input."
}, {
fieldName: "lte",
type: "Datetime",
description: "Checks if the value is lesser than or equal to the given input."
}, {
fieldName: "is_defined",
type: "Boolean",
description: "Checks if the value is defined."
}]
};
}
function createDocumentFilters$1() {
return {
name: "DocumentFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "references",
type: "ID",
description: "All documents referencing the given document ID."
}, {
fieldName: "is_draft",
type: "Boolean",
description: "All documents that are drafts."
}]
};
}
function createFloatFilters() {
return {
name: "FloatFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "Float",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "Float",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "gt",
type: "Float",
description: "Checks if the value is greater than the given input."
}, {
fieldName: "gte",
type: "Float",
description: "Checks if the value is greater than or equal to the given input."
}, {
fieldName: "lt",
type: "Float",
description: "Checks if the value is lesser than the given input."
}, {
fieldName: "lte",
type: "Float",
description: "Checks if the value is lesser than or equal to the given input."
}, {
fieldName: "is_defined",
type: "Boolean",
description: "Checks if the value is defined."
}]
};
}
function createIdFilters() {
return {
name: "IDFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "ID",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "ID",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "matches",
type: "ID",
description: "Checks if the value matches the given word/words."
}, {
fieldName: "in",
kind: "List",
children: {
type: "ID",
isNullable: !1
},
description: "Checks if the value is equal to one of the given values."
}, {
fieldName: "nin",
kind: "List",
children: {
type: "ID",
isNullable: !1
},
description: "Checks if the value is not equal to one of the given values."
}]
};
}
function createIntegerFilters() {
return {
name: "IntFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "Int",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "Int",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "gt",
type: "Int",
description: "Checks if the value is greater than the given input."
}, {
fieldName: "gte",
type: "Int",
description: "Checks if the value is greater than or equal to the given input."
}, {
fieldName: "lt",
type: "Int",
description: "Checks if the value is lesser than the given input."
}, {
fieldName: "lte",
type: "Int",
description: "Checks if the value is lesser than or equal to the given input."
}, {
fieldName: "is_defined",
type: "Boolean",
description: "Checks if the value is defined."
}]
};
}
function createStringFilters() {
return {
name: "StringFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "eq",
type: "String",
description: "Checks if the value is equal to the given input."
}, {
fieldName: "neq",
type: "String",
description: "Checks if the value is not equal to the given input."
}, {
fieldName: "matches",
type: "String",
description: "Checks if the value matches the given word/words."
}, {
fieldName: "in",
kind: "List",
children: {
type: "String",
isNullable: !1
},
description: "Checks if the value is equal to one of the given values."
}, {
fieldName: "nin",
kind: "List",
children: {
type: "String",
isNullable: !1
},
description: "Checks if the value is not equal to one of the given values."
}, {
fieldName: "is_defined",
type: "Boolean",
description: "Checks if the value is defined."
}]
};
}
const typeAliases$1 = {
Url: "String",
Text: "String",
Email: "String"
}, filterCreators$1 = {
ID: createIdFilters,
String: createStringFilters,
Float: createFloatFilters,
Integer: createIntegerFilters,
Boolean: createBooleanFilters,
Datetime: createDateTimeFilters,
Date: createDateFilters,
Document: createDocumentFilters$1
};
function generateTypeFilters$1(types) {
const builtInTypeKeys = Object.keys(filterCreators$1), builtinTypeValues = Object.values(filterCreators$1), objectTypes = types.filter(isNonUnion).filter((type) => type.type === "Object" && !["Block", "Span"].includes(type.name) && !type.interfaces && !builtInTypeKeys.includes(type.type)), unionTypes = types.filter(isUnion).map((type) => type.name), documentTypes = types.filter(isNonUnion).filter((type) => type.type === "Object" && type.interfaces && type.interfaces.includes("Document")), builtinTypeFilters = createBuiltinTypeFilters$1(builtinTypeValues), objectTypeFilters = createObjectTypeFilters$1(objectTypes, {
unionTypes
}), documentTypeFilters = createDocumentTypeFilters$1(documentTypes, {
unionTypes
});
return [...builtinTypeFilters, ...objectTypeFilters, ...documentTypeFilters];
}
function createBuiltinTypeFilters$1(builtinTypeValues) {
return builtinTypeValues.map((filterCreator) => filterCreator());
}
function createObjectTypeFilters$1(objectTypes, options) {
return objectTypes.map((objectType) => ({
name: `${objectType.name}Filter`,
kind: "InputObject",
fields: createFieldFilters$1(objectType, options)
}));
}
function createDocumentTypeFilters$1(documentTypes, options) {
return documentTypes.map((documentType) => ({
name: `${documentType.name}Filter`,
kind: "InputObject",
fields: [...getDocumentFilters$1(), ...createFieldFilters$1(documentType, options)]
}));
}
function createFieldFilters$1(objectType, options) {
const {
unionTypes
} = options;
return objectType.fields.filter((field) => field.type !== "JSON" && field.kind !== "List" && !unionTypes.includes(field.type)).map((field) => ({
fieldName: field.fieldName,
type: `${typeAliases$1[field.type] || field.type}Filter`,
isReference: field.isReference
}));
}
function getDocumentFilters$1() {
return [{
fieldName: "_",
type: "DocumentFilter",
description: "Apply filters on document level"
}];
}
function generateTypeQueries$1(types, sortings) {
const queries = [], queryable = types.filter(isDocumentType), isSortable = (type) => sortings.some((sorting) => sorting.name === `${type.name}Sorting`);
return queries.push({
fieldName: "Document",
type: "Document",
constraints: [{
field: "_id",
comparator: "eq",
value: {
kind: "argumentValue",
argName: "id"
}
}],
args: [{
name: "id",
description: "Document ID",
type: "ID",
isNullable: !1
}]
}), queryable.forEach((type) => {
queries.push({
fieldName: type.name,
type: type.name,
constraints: [{
field: "_id",
comparator: "eq",
value: {
kind: "argumentValue",
argName: "id"
}
}],
args: [{
name: "id",
description: `${type.name} document ID`,
type: "ID",
isNullable: !1
}]
});
}), queryable.forEach((type) => {
const sorting = [];
isSortable(type) && sorting.push({
name: "sort",
type: {
kind: "List",
isNullable: !0,
children: {
type: `${type.name}Sorting`,
isNullable: !1
}
}
}), queries.push({
fieldName: `all${upperFirst(type.name)}`,
filter: `_type == "${type.originalName || type.name}"`,
type: {
kind: "List",
isNullable: !1,
children: {
type: type.name,
isNullable: !1
}
},
args: [{
name: "where",
type: `${type.name}Filter`,
isFieldFilter: !0
}, ...sorting, {
name: "limit",
type: "Int",
description: "Max documents to return",
isFieldFilter: !1
}, {
name: "offset",
type: "Int",
description: "Offset at which to start returning documents from",
isFieldFilter: !1
}]
});
}), queries;
}
const builtInTypes$1 = ["Boolean", "Date", "Datetime", "Email", "Float", "ID", "Integer", "String", "Text", "Url"], builtInSortingEnum$1 = {
name: "SortOrder",
kind: "Enum",
values: [{
name: "ASC",
description: "Sorts on the value in ascending order.",
value: 1
}, {
name: "DESC",
description: "Sorts on the value in descending order.",
value: 2
}]
};
function generateTypeSortings$1(types) {
const objectTypes = types.filter(isNonUnion).filter((type) => type.type === "Object" && !["Block", "Span"].includes(type.name) && // TODO: What do we do with blocks?
!type.interfaces && !builtInTypes$1.includes(type.name)), documentTypes = types.filter(isDocumentType), hasFields = (type) => type.fields.length > 0, objectTypeSortings = createObjectTypeSortings$1(objectTypes), documentTypeSortings = createDocumentTypeSortings$1(documentTypes);
return [...[...objectTypeSortings, ...documentTypeSortings].filter(hasFields), builtInSortingEnum$1];
}
function createObjectTypeSortings$1(objectTypes) {
return objectTypes.map((objectType) => ({
name: `${objectType.name}Sorting`,
kind: "InputObject",
fields: objectType.fields.filter((field) => field.type !== "JSON" && field.kind !== "List").filter((field) => !field.isReference).map((field) => ({
fieldName: field.fieldName,
type: builtInTypes$1.includes(field.type) ? builtInSortingEnum$1.name : `${field.type}Sorting`
}))
}));
}
function createDocumentTypeSortings$1(documentTypes) {
return documentTypes.map((documentType) => ({
name: `${documentType.name}Sorting`,
kind: "InputObject",
fields: documentType.fields.filter((field) => field.type !== "JSON" && field.kind !== "List").filter((field) => !field.isReference).map((field) => ({
fieldName: field.fieldName,
type: builtInTypes$1.includes(field.type) ? builtInSortingEnum$1.name : `${field.type}Sorting`
}))
}));
}
var gen2 = (extracted) => {
const filters = generateTypeFilters$1(extracted.types), sortings = generateTypeSortings$1(extracted.types), queries = generateTypeQueries$1(extracted.types, sortings.filter((node) => node.kind === "InputObject"));
return {
types: [...extracted.types, ...filters, ...sortings],
queries,
interfaces: extracted.interfaces,
generation: "gen2"
};
};
function createDocumentFilters() {
return {
name: "Sanity_DocumentFilter",
kind: "InputObject",
isConstraintFilter: !0,
fields: [{
fieldName: "references",
type: "ID",
description: "All documents referencing the given document ID."
}, {
fieldName: "is_draft",
type: "Boolean",
description: "All documents that are drafts."
}]
};
}
function getFilterFieldName(fieldName, suffix = "Filter") {
return `${fieldName}${suffix}`;
}
const typeAliases = {
Url: "String",
Text: "String",
Email: "String"
}, filterCreators = {
ID: createIdFilters,
String: createStringFilters,
Float: createFloatFilters,
Integer: createIntegerFilters,
Boolean: createBooleanFilters,
Datetime: createDateTimeFilters,
Date: createDateFilters,
Document: createDocumentFilters
};
function generateTypeFilters(types, options) {
const {
filterSuffix
} = options || {}, builtInTypeKeys = Object.keys(filterCreators), builtinTypeValues = Object.values(filterCreators), objectTypes = types.filter(isNonUnion).filter((type) => type.type === "Object" && !["Block", "Span"].includes(type.name) && // TODO: What do we do with blocks?
!type.interfaces && !builtInTypeKeys.includes(type.type)), unionTypes = types.filter(isUnion).map((type) => type.name), documentTypes = types.filter((type) => type.name === "Document" || isDocumentType(type)), builtinTypeFilters = createBuiltinTypeFilters(builtinTypeValues), objectTypeFilters = createObjectTypeFilters(objectTypes, {
unionTypes,
filterSuffix
}), documentTypeFilters = createDocumentTypeFilters(documentTypes, {
unionTypes,
filterSuffix
});
return builtinTypeFilters.concat(objectTypeFilters).concat(documentTypeFilters);
}
function createBuiltinTypeFilters(builtinTypeValues) {
return builtinTypeValues.map((filterCreator) => filterCreator());
}
function createObjectTypeFilters(objectTypes, options) {
return objectTypes.map((objectType) => ({
name: getFilterFieldName(objectType.name, options.filterSuffix),
kind: "InputObject",
fields: createFieldFilters(objectType, options)
}));
}
function createDocumentTypeFilters(documentTypes, options) {
return documentTypes.map((documentType) => ({
name: getFilterFieldName(documentType.name, options.filterSuffix),
kind: "InputObject",
fields: [...getDocumentFilters(), ...createFieldFilters(documentType, options)]
}));
}
function createFieldFilters(objectType, options) {
const {
unionTypes
} = options;
return objectType.fields ? objectType.fields.filter((field) => field.type !== "JSON" && field.kind !== "List" && !unionTypes.includes(field.type)).map((field) => {
const typeName = typeAliases[field.type] || field.type, filterSuffix = Object.keys({
...typeAliases,
...filterCreators
}).includes(typeName) ? void 0 : options.filterSuffix;
return {
fieldName: field.fieldName,
type: getFilterFieldName(typeAliases[field.type] || field.type, filterSuffix),
isReference: field.isReference
};
}) : [];
}
function getDocumentFilters() {
return [{
fieldName: "_",
type: "Sanity_DocumentFilter",
description: "Apply filters on document level"
}];
}
function generateTypeQueries(types, sortings, options) {
const {
filterSuffix
} = options || {}, queries = [], documentTypes = types.filter(isDocumentType), documentsFilter = `_type in [${documentTypes.map((docType) => JSON.stringify(docType.originalName || docType.name)).join(", ")}]`, documentInterface = types.find((type) => type.name === "Document");
if (!documentInterface || isUnion(documentInterface))
throw new Error("Failed to find document interface");
const queryable = [...documentTypes, documentInterface], isSortable = (type) => sortings.some((sorting) => sorting.name === `${type.name}Sorting`);
return queryable.forEach((type) => {
queries.push({
fieldName: type.name,
type: type.name,
constraints: [{
field: "_id",
comparator: "eq",
value: {
kind: "argumentValue",
argName: "id"
}
}],
args: [{
name: "id",
description: `${type.name} document ID`,
type: "ID",
isNullable: !1
}],
...getDeprecation(type)
});
}), queryable.forEach((type) => {
const sorting = [];
isSortable(type) && sorting.push({
name: "sort",
type: {
kind: "List",
isNullable: !0,
children: {
type: `${type.name}Sorting`,
isNullable: !1
}
}
}), queries.push({
fieldName: `all${upperFirst(type.name)}`,
filter: type.name === "Document" && type.kind === "Interface" ? documentsFilter : `_type == ${JSON.stringify(type.originalName || type.name)}`,
type: {
kind: "List",
isNullable: !1,
children: {
type: type.name,
isNullable: !1
}
},
args: [{
name: "where",
type: getFilterFieldName(type.name, filterSuffix),
isFieldFilter: !0
}, ...sorting, {
name: "limit",
type: "Int",
description: "Max documents to return",
isFieldFilter: !1
}, {
name: "offset",
type: "Int",
description: "Offset at which to start returning documents from",
isFieldFilter: !1
}],
...getDeprecation(type)
});
}), queries;
}
function getDeprecation(type) {
return type[internal]?.deprecationReason ? {
deprecationReason: type[internal].deprecationReason
} : {};
}
const builtInTypes = ["Boolean", "Date", "Datetime", "Email", "Float", "ID", "Integer", "String", "Text", "Url"], builtInSortingEnum = {
name: "SortOrder",
kind: "Enum",
values: [{
name: "ASC",
description: "Sorts on the value in ascending order.",
value: 1
}, {
name: "DESC",
description: "Sorts on the value in descending order.",
value: 2
}]
};
function generateTypeSortings(types) {
const objectTypes = types.filter(isNonUnion).filter((type) => type.type === "Object" && !["Block", "Span"].includes(type.name) && // TODO: What do we do with blocks?
!type.interfaces && !builtInTypes.includes(type.name)), documentTypes = types.filter((type) => type.name === "Document" || isDocumentType(type)), hasFields = (type) => type.fields.length > 0, objectTypeSortings = createObjectTypeSortings(objectTypes), documentTypeSortings = createDocumentTypeSortings(documentTypes);
return [...[...objectTypeSortings, ...documentTypeSortings].filter(hasFields), builtInSortingEnum];
}
function createObjectTypeSortings(objectTypes) {
return objectTypes.map((objectType) => ({
name: `${objectType.name}Sorting`,
kind: "InputObject",
fields: objectType.fields.filter((field) => field.type !== "JSON" && field.kind !== "List").filter((field) => !field.isReference).map((field) => ({
fieldName: field.fieldName,
type: builtInTypes.includes(field.type) ? builtInSortingEnum.name : `${field.type}Sorting`
}))
}));
}
function createDocumentTypeSortings(documentTypes) {
return documentTypes.map((documentType) => ({
name: `${documentType.name}Sorting`,
kind: "InputObject",
fields: documentType.fields.filter((field) => field.type !== "JSON" && field.kind !== "List").filter((field) => !field.isReference).map((field) => ({
fieldName: field.fieldName,
type: builtInTypes.includes(field.type) ? builtInSortingEnum.name : `${field.type}Sorting`
}))
}));
}
var gen3 = (extracted, options) => {
const documentInterface = extracted.interfaces.find((iface) => iface.name === "Document");
if (!documentInterface || isUnion(documentInterface))
throw new Error("Failed to find document interface");
const types = [...extracted.types, documentInterface], filters = generateTypeFilters(types, options), sortings = generateTypeSortings(types), queries = generateTypeQueries(types, sortings.filter((node) => node.kind === "InputObject"), options);
return {
types: [...extracted.types, ...filters, ...sortings],
queries,
interfaces: extracted.interfaces,
generation: "gen3"
};
};
const latestGeneration = "gen3", generations = {
gen1,
gen2,
gen3
}, apiIdRegex = /^[a-z0-9_-]+$/, isInteractive = process.stdout.isTTY && process.env.TERM !== "dumb" && !("CI" in process.env), ignoredWarnings = ["OPTIONAL_INPUT_FIELD_ADDED"], ignoredBreaking = [];
async function deployGraphQLApiAction(args, context) {
const flags = await parseCliFlags(args), {
force,
dryRun,
api: onlyApis,
dataset: datasetFlag,
tag: tagFlag,
playground: playgroundFlag,
generation: generationFlag,
"non-null-document-fields": nonNullDocumentFieldsFlag,
withUnionCache
} = flags, {
apiClient,
output,
prompt
} = context;
let spinner;
const client = apiClient({
requireUser: !0,
// Don't throw if we do not have a project ID defined, as we will infer it from the
// source/ workspace of each configured API later
requireProject: !1
}).config({
apiVersion: "2023-08-01"
}), apiDefs = await getGraphQLAPIs(context);
let hasMultipleApis = apiDefs.length > 1;
flags.api && (hasMultipleApis = flags.api.length > 1);
const usedFlags = [datasetFlag && "--dataset", tagFlag && "--tag", typeof playgroundFlag < "u" && "--playground", typeof generationFlag < "u" && "--generation", typeof nonNullDocumentFieldsFlag < "u" && "--non-null-document-fields"].filter(Boolean);
hasMultipleApis && usedFlags.length > 0 && (output.warn(`WARN: More than one API defined, and ${usedFlags.join("/")} is specified`), output.warn("WARN: This will use the specified flag(s) for ALL APIs, overriding config!"), flags.force ? output.warn("WARN: --force specified, continuing...") : await prompt.single({
type: "confirm",
message: "Continue with flag overrides for all APIs?",
default: !1
}) || process.exit(1));
const deployTasks = [];
for (const apiId of o