UNPKG

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

260 lines (259 loc) • 10.5 kB
"use strict"; var chalk = require("chalk"), extractManifestAction = require("./extractManifestAction.js"), uniqBy = require("lodash/uniqBy"), fs = require("node:fs/promises"), path = require("node:path"); function _interopDefaultCompat(e) { return e && typeof e == "object" && "default" in e ? e : { default: e }; } var chalk__default = /* @__PURE__ */ _interopDefaultCompat(chalk), uniqBy__default = /* @__PURE__ */ _interopDefaultCompat(uniqBy), path__default = /* @__PURE__ */ _interopDefaultCompat(path); const SANITY_WORKSPACE_SCHEMA_TYPE = "sanity.workspace.schema"; function isDefined(value) { return value != null; } const createManifestReader = ({ manifestDir, output, jsonReader = parseJsonFile }) => { let parsedManifest; const parsedWorkspaces = {}, getManifest = async () => { if (parsedManifest) return parsedManifest?.parsedJson; const manifestFile = path__default.default.join(manifestDir, extractManifestAction.MANIFEST_FILENAME), result = await jsonReader(manifestFile); if (!result) throw new Error(`Manifest does not exist at ${manifestFile}. To create the manifest file, omit --no-extract-manifest or run "sanity manifest extract" first.`); return output.print(chalk__default.default.gray(`\u21B3 Read manifest from ${manifestFile} (last modified: ${result.lastModified})`)), parsedManifest = result, result.parsedJson; }; return { getManifest, getWorkspaceSchema: async (workspaceName) => { if (parsedWorkspaces[workspaceName]) return parsedWorkspaces[workspaceName]?.parsedJson; const manifest = await getManifest(); if (!manifest) throw Error("Manifest is required to read workspace schema."); const workspaceManifest = manifest.workspaces.find((workspace) => workspace.name === workspaceName); if (!workspaceManifest) throw Error(`No workspace named "${workspaceName}" found in manifest.`); const workspaceSchemaFile = path__default.default.join(manifestDir, workspaceManifest.schema), result = await jsonReader(workspaceSchemaFile); if (!result) throw Error(`Workspace schema file at "${workspaceSchemaFile}" does not exist.`); return parsedWorkspaces[workspaceName] = result, result.parsedJson; } }; }; function resolveManifestDirectory(workDir, customPath) { const defaultOutputDir = path.resolve(path.join(workDir, "dist")), outputDir = path.resolve(defaultOutputDir), defaultStaticPath = path.join(outputDir, "static"), staticPath = customPath ?? defaultStaticPath; return path__default.default.resolve(process.cwd(), staticPath); } async function parseJsonFile(filePath) { let stats; try { stats = await fs.stat(filePath); } catch { return; } const content = await fs.readFile(filePath, "utf-8"), lastModified = stats.mtime.toISOString(), json = JSON.parse(content); if (!json) throw new Error(`JSON file "${filePath}" was empty.`); return { parsedJson: json, path: filePath, lastModified }; } const validForIdChars = "a-zA-Z0-9._-", validForIdPattern = new RegExp(`^[${validForIdChars}]+$`, "g"), requiredInId = SANITY_WORKSPACE_SCHEMA_TYPE.replace(/[.]/g, "\\."), idPattern = new RegExp(`^(?:[${validForIdChars}]+?\\.)?${requiredInId}\\.([${validForIdChars}]+)$`); class FlagValidationError extends Error { constructor(message) { super(message), this.name = "FlagValidationError"; } } function parseCommonFlags(flags, context, errors) { const manifestDir = parseManifestDir(flags, errors), verbose = !!flags.verbose, extractManifest = flags["extract-manifest"] ?? !0; return { manifestDir: resolveManifestDirectory(context.workDir, manifestDir), verbose, extractManifest }; } function parseDeploySchemasConfig(flags, context) { const errors = [], commonFlags = parseCommonFlags(flags, context, errors), workspaceName = parseWorkspace(flags, errors), idPrefix = parseIdPrefix(flags, errors), schemaRequired = !!flags["schema-required"]; return assertNoErrors(errors), { ...commonFlags, workspaceName, idPrefix, schemaRequired }; } function parseListSchemasConfig(flags, context) { const errors = [], commonFlags = parseCommonFlags(flags, context, errors), id = parseId(flags, errors), json = !!flags.json; return assertNoErrors(errors), { ...commonFlags, json, id }; } function parseDeleteSchemasConfig(flags, context) { const errors = [], commonFlags = parseCommonFlags(flags, context, errors), ids = parseIds(flags, errors), dataset = parseDataset(flags, errors); return assertNoErrors(errors), { ...commonFlags, dataset, ids }; } function assertNoErrors(errors) { if (errors.length) throw new FlagValidationError(`Invalid arguments: ${errors.map((error) => ` - ${error}`).join(` `)}`); } function parseIds(flags, errors) { const parsedIds = parseNonEmptyString(flags, "ids", errors); if (errors.length) return []; const ids = parsedIds.split(",").map((id) => id.trim()).filter((id) => !!id).map((id) => parseWorkspaceSchemaId(id, errors)).filter(isDefined), uniqueIds = uniqBy__default.default(ids, "schemaId"); return uniqueIds.length < ids.length && errors.push("ids contains duplicates"), !errors.length && !uniqueIds.length && errors.push("ids contains no valid id strings"), uniqueIds; } function parseId(flags, errors) { const id = flags.id === void 0 ? void 0 : parseNonEmptyString(flags, "id", errors); if (id) return parseWorkspaceSchemaId(id, errors)?.schemaId; } function parseWorkspaceSchemaId(id, errors) { const trimmedId = id.trim(); if (!trimmedId.match(validForIdPattern)) { errors.push(`id can only contain characters in [${validForIdChars}] but found: "${trimmedId}"`); return; } if (trimmedId.startsWith("-")) { errors.push(`id cannot start with - (dash) but found: "${trimmedId}"`); return; } if (trimmedId.match(/\.\./g)) { errors.push(`id cannot have consecutive . (period) characters, but found: "${trimmedId}"`); return; } const workspace = trimmedId.match(idPattern)?.[1] ?? ""; if (!workspace) { errors.push(`id must end with ${SANITY_WORKSPACE_SCHEMA_TYPE}.<workspaceName> but found: "${trimmedId}"`); return; } return { schemaId: trimmedId, workspace }; } function parseDataset(flags, errors) { return flags.dataset === void 0 ? void 0 : parseNonEmptyString(flags, "dataset", errors); } function parseWorkspace(flags, errors) { return flags.workspace === void 0 ? void 0 : parseNonEmptyString(flags, "workspace", errors); } function parseManifestDir(flags, errors) { return flags["manifest-dir"] === void 0 ? void 0 : parseNonEmptyString(flags, "manifest-dir", errors); } function parseIdPrefix(flags, errors) { if (flags["id-prefix"] === void 0) return; const idPrefix = parseNonEmptyString(flags, "id-prefix", errors); if (!errors.length) { if (idPrefix.endsWith(".")) { errors.push(`id-prefix argument cannot end with . (period), but was: "${idPrefix}"`); return; } if (!idPrefix.match(validForIdPattern)) { errors.push(`id-prefix can only contain _id compatible characters [${validForIdChars}], but was: "${idPrefix}"`); return; } if (idPrefix.startsWith("-")) { errors.push(`id-prefix cannot start with - (dash) but was: "${idPrefix}"`); return; } if (idPrefix.match(/\.\./g)) { errors.push(`id-prefix cannot have consecutive . (period) characters, but was: "${idPrefix}"`); return; } return idPrefix; } } function parseNonEmptyString(flags, flagName, errors) { const flag = flags[flagName]; return !isString(flag) || !flag ? (errors.push(`${flagName} argument is empty`), "") : flag; } function isString(flag) { return typeof flag == "string"; } function getProjectIdMismatchMessage(workspace, operation) { return `No permissions to ${operation} schema for workspace "${workspace.name}" with projectId "${workspace.projectId}"`; } function throwWriteProjectIdMismatch(workspace, projectId) { if (workspace.projectId !== projectId) throw new Error(getProjectIdMismatchMessage(workspace, "write")); } function filterLogReadProjectIdMismatch(workspace, projectId, output) { const canRead = workspace.projectId === projectId; return canRead || output.warn(`${getProjectIdMismatchMessage(workspace, "read")} \u2013 ignoring it.`), canRead; } async function ensureManifestExtractSatisfied(args) { const { schemaRequired, extractManifest, manifestDir, manifestExtractor, output } = args; if (!extractManifest) return !0; try { return await manifestExtractor(manifestDir), !0; } catch (err) { if (schemaRequired || err instanceof FlagValidationError) throw err; return output.print(chalk__default.default.gray(`\u21B3 Failed to extract manifest: ${err.message}`)), !1; } } function createManifestExtractor(context) { return async (manifestDir) => { const error = await extractManifestAction.extractManifestSafe({ extOptions: { path: manifestDir }, groupOrCommand: "extract", argv: [], argsWithoutOptions: [], extraArguments: [] }, context); if (!context.safe && error) throw error; }; } function createSchemaApiClient(apiClient) { const client = apiClient({ requireUser: !0, requireProject: !0 }).withConfig({ apiVersion: "v2025-03-01", useCdn: !1 }), projectId = client.config().projectId, dataset = client.config().dataset; if (!projectId) throw new Error("Project ID is not defined"); if (!dataset) throw new Error("Dataset is not defined"); return { client, projectId, dataset }; } exports.FlagValidationError = FlagValidationError; exports.SANITY_WORKSPACE_SCHEMA_TYPE = SANITY_WORKSPACE_SCHEMA_TYPE; exports.createManifestExtractor = createManifestExtractor; exports.createManifestReader = createManifestReader; exports.createSchemaApiClient = createSchemaApiClient; exports.ensureManifestExtractSatisfied = ensureManifestExtractSatisfied; exports.filterLogReadProjectIdMismatch = filterLogReadProjectIdMismatch; exports.isDefined = isDefined; exports.parseDeleteSchemasConfig = parseDeleteSchemasConfig; exports.parseDeploySchemasConfig = parseDeploySchemasConfig; exports.parseListSchemasConfig = parseListSchemasConfig; exports.throwWriteProjectIdMismatch = throwWriteProjectIdMismatch; exports.validForIdChars = validForIdChars; exports.validForIdPattern = validForIdPattern; //# sourceMappingURL=schemaApiClient.js.map