diff --git a/packages/@sanity/cli/package.json b/packages/@sanity/cli/package.json index 0c7c284edfb..cb8a33c8aec 100644 --- a/packages/@sanity/cli/package.json +++ b/packages/@sanity/cli/package.json @@ -60,6 +60,7 @@ "@sanity/client": "^6.24.1", "@sanity/codegen": "3.67.1", "@sanity/telemetry": "^0.7.7", + "@sanity/template-validator": "^1.0.2", "@sanity/util": "3.67.1", "chalk": "^4.1.2", "debug": "^4.3.4", @@ -72,8 +73,7 @@ "prettier": "^3.3.0", "semver": "^7.3.5", "silver-fleece": "1.1.0", - "validate-npm-package-name": "^3.0.0", - "yaml": "^2.6.1" + "validate-npm-package-name": "^3.0.0" }, "devDependencies": { "@repo/package.config": "workspace:*", diff --git a/packages/@sanity/cli/src/actions/init-project/bootstrapRemoteTemplate.ts b/packages/@sanity/cli/src/actions/init-project/bootstrapRemoteTemplate.ts index 7eca8f489ca..977746a7ea3 100644 --- a/packages/@sanity/cli/src/actions/init-project/bootstrapRemoteTemplate.ts +++ b/packages/@sanity/cli/src/actions/init-project/bootstrapRemoteTemplate.ts @@ -11,7 +11,7 @@ import { checkNeedsReadToken, downloadAndExtractRepo, generateSanityApiReadToken, - getMonoRepo, + getPackages, type RepoInfo, tryApplyPackageName, validateRemoteTemplate, @@ -40,7 +40,7 @@ export async function bootstrapRemoteTemplate( const spinner = output.spinner(`Bootstrapping files from template "${name}"`).start() debug('Validating remote template') - const packages = await getMonoRepo(repoInfo, bearerToken) + const packages = await getPackages(repoInfo, bearerToken) await validateRemoteTemplate(repoInfo, packages, bearerToken) debug('Create new directory "%s"', outputPath) diff --git a/packages/@sanity/cli/src/util/remoteTemplate.ts b/packages/@sanity/cli/src/util/remoteTemplate.ts index fbfc184e3f8..77db18ec5e9 100644 --- a/packages/@sanity/cli/src/util/remoteTemplate.ts +++ b/packages/@sanity/cli/src/util/remoteTemplate.ts @@ -4,25 +4,21 @@ import {Readable} from 'node:stream' import {pipeline} from 'node:stream/promises' import {type ReadableStream} from 'node:stream/web' +import { + ENV_TEMPLATE_FILES, + getMonoRepo, + REQUIRED_ENV_VAR, + validateSanityTemplate, +} from '@sanity/template-validator' import {x} from 'tar' -import {parse as parseYaml} from 'yaml' import {type CliApiClient, type PackageJson} from '../types' const ENV_VAR = { - PROJECT_ID: /SANITY(?:_STUDIO)?_PROJECT_ID/, // Matches SANITY_PROJECT_ID and SANITY_STUDIO_PROJECT_ID - DATASET: /SANITY(?:_STUDIO)?_DATASET/, // Matches SANITY_DATASET and SANITY_STUDIO_DATASET + ...REQUIRED_ENV_VAR, READ_TOKEN: 'SANITY_API_READ_TOKEN', } as const -const ENV_FILE = { - TEMPLATE: '.env.template', - EXAMPLE: '.env.example', - LOCAL_EXAMPLE: '.env.local.example', -} as const - -const ENV_TEMPLATE_FILES = [ENV_FILE.TEMPLATE, ENV_FILE.EXAMPLE, ENV_FILE.LOCAL_EXAMPLE] as const - type EnvData = { projectId: string dataset: string @@ -40,6 +36,11 @@ export type RepoInfo = { filePath: string } +function getGitHubRawContentUrl(repoInfo: RepoInfo): string { + const {username, name, branch, filePath} = repoInfo + return `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}` +} + function isGithubRepoShorthand(value: string): boolean { if (URL.canParse(value)) { return false @@ -191,222 +192,29 @@ export async function downloadAndExtractRepo( * Supports pnpm workspaces, Lerna, Rush, and npm workspaces (package.json). * @returns Promise that resolves to an array of package paths/names if monorepo is detected, undefined otherwise */ -export async function getMonoRepo( +export async function getPackages( repoInfo: RepoInfo, bearerToken?: string, ): Promise { - const {username, name, branch, filePath} = repoInfo - const baseUrl = `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}` - const headers: Record = {} if (bearerToken) { headers.Authorization = `Bearer ${bearerToken}` } - - type MonorepoHandler = { - check: (content: string) => string[] | undefined - } - - const handlers: Record = { - 'package.json': { - check: (content) => { - try { - const pkg = JSON.parse(content) - if (!pkg.workspaces) return undefined - return Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages - } catch { - return undefined - } - }, - }, - 'pnpm-workspace.yaml': { - check: (content) => { - try { - const config = parseYaml(content) - return config.packages - } catch { - return undefined - } - }, - }, - 'lerna.json': { - check: (content) => { - try { - const config = JSON.parse(content) - return config.packages - } catch { - return undefined - } - }, - }, - 'rush.json': { - check: (content) => { - try { - const config = JSON.parse(content) - return config.projects?.map((p: {packageName: string}) => p.packageName) - } catch { - return undefined - } - }, - }, - } - - const fileChecks = await Promise.all( - Object.keys(handlers).map(async (file) => { - const response = await fetch(`${baseUrl}/${file}`, {headers}) - return {file, exists: response.status === 200, content: await response.text()} - }), - ) - - for (const check of fileChecks) { - if (!check.exists) continue - const result = handlers[check.file].check(check.content) - if (result) return result - } - - return undefined -} - -/** - * Validates a single package within a repository against required criteria. - */ -async function validatePackage( - baseUrl: string, - packagePath: string, - headers: Record, -): Promise<{ - hasSanityConfig: boolean - hasSanityCli: boolean - hasEnvFile: boolean - hasSanityDep: boolean -}> { - const packageUrl = packagePath ? `${baseUrl}/${packagePath}` : baseUrl - - const requiredFiles = [ - 'package.json', - 'sanity.config.ts', - 'sanity.config.js', - 'sanity.cli.ts', - 'sanity.cli.js', - ...ENV_TEMPLATE_FILES, - ] - - const fileChecks = await Promise.all( - requiredFiles.map(async (file) => { - const response = await fetch(`${packageUrl}/${file}`, {headers}) - return {file, exists: response.status === 200, content: await response.text()} - }), - ) - - const packageJson = fileChecks.find((f) => f.file === 'package.json') - if (!packageJson?.exists) { - throw new Error(`Package at ${packagePath || 'root'} must include a package.json file`) - } - - let hasSanityDep = false - try { - const pkg: PackageJson = JSON.parse(packageJson.content) - hasSanityDep = !!(pkg.dependencies?.sanity || pkg.devDependencies?.sanity) - } catch (err) { - throw new Error(`Invalid package.json file in ${packagePath || 'root'}`) - } - - const hasSanityConfig = fileChecks.some( - (f) => f.exists && (f.file === 'sanity.config.ts' || f.file === 'sanity.config.js'), - ) - - const hasSanityCli = fileChecks.some( - (f) => f.exists && (f.file === 'sanity.cli.ts' || f.file === 'sanity.cli.js'), - ) - - const envFile = fileChecks.find( - (f) => f.exists && ENV_TEMPLATE_FILES.includes(f.file as (typeof ENV_TEMPLATE_FILES)[number]), - ) - if (envFile) { - const envContent = envFile.content - const hasProjectId = envContent.match(ENV_VAR.PROJECT_ID) - const hasDataset = envContent.match(ENV_VAR.DATASET) - - if (!hasProjectId || !hasDataset) { - const missing = [] - if (!hasProjectId) missing.push('SANITY_PROJECT_ID or SANITY_STUDIO_PROJECT_ID') - if (!hasDataset) missing.push('SANITY_DATASET or SANITY_STUDIO_DATASET') - throw new Error( - `Environment template in ${ - packagePath || 'repo' - } must include the following variables: ${missing.join(', ')}`, - ) - } - } - - return { - hasSanityConfig, - hasSanityCli, - hasEnvFile: Boolean(envFile), - hasSanityDep, - } + return getMonoRepo(getGitHubRawContentUrl(repoInfo), headers) } -/** - * Validates a GitHub repository template against required criteria. - * Supports both monorepo and single-package repositories. - * - * For monorepos: - * - Each package must have a valid package.json - * - At least one package must include 'sanity' in dependencies or devDependencies - * - At least one package must have sanity.config.js/ts and sanity.cli.js/ts - * - Each package must have a .env.template, .env.example, or .env.local.example - * - * For single-package repositories: - * - Must have a valid package.json with 'sanity' dependency - * - Must have sanity.config.js/ts and sanity.cli.js/ts - * - Must have .env.template, .env.example, or .env.local.example - * - * Environment files must include: - * - SANITY_PROJECT_ID or SANITY_STUDIO_PROJECT_ID variable - * - SANITY_DATASET or SANITY_STUDIO_DATASET variable - * - * @throws Error if validation fails with specific reason - */ export async function validateRemoteTemplate( repoInfo: RepoInfo, packages: string[] = [''], bearerToken?: string, ): Promise { - const {username, name, branch, filePath} = repoInfo - const baseUrl = `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}` - const headers: Record = {} if (bearerToken) { headers.Authorization = `Bearer ${bearerToken}` } - - const validations = await Promise.all( - packages.map((pkg) => validatePackage(baseUrl, pkg, headers)), - ) - - const hasSanityDep = validations.some((v) => v.hasSanityDep) - if (!hasSanityDep) { - throw new Error('At least one package must include "sanity" as a dependency in package.json') - } - - const hasSanityConfig = validations.some((v) => v.hasSanityConfig) - if (!hasSanityConfig) { - throw new Error('At least one package must include a sanity.config.js or sanity.config.ts file') - } - - const hasSanityCli = validations.some((v) => v.hasSanityCli) - if (!hasSanityCli) { - throw new Error('At least one package must include a sanity.cli.js or sanity.cli.ts file') - } - - const missingEnvPackages = packages.filter((pkg, i) => !validations[i].hasEnvFile) - if (missingEnvPackages.length > 0) { - throw new Error( - `The following packages are missing .env.template, .env.example, or .env.local.example files: ${missingEnvPackages.join( - ', ', - )}`, - ) + const result = await validateSanityTemplate(getGitHubRawContentUrl(repoInfo), packages, headers) + if (!result.isValid) { + throw new Error(result.errors.join('\n')) } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index edca5823280..79924ecabf5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,7 +50,7 @@ importers: version: 0.11.1(debug@4.4.0) '@sanity/pkg-utils': specifier: 6.12.0 - version: 6.12.0(@types/babel__core@7.20.5)(@types/node@22.10.1)(babel-plugin-react-compiler@19.0.0-beta-37ed2a7-20241206)(debug@4.4.0)(typescript@5.7.2) + version: 6.12.0(@types/babel__core@7.20.5)(@types/node@22.10.1)(typescript@5.7.2) '@sanity/prettier-config': specifier: ^1.0.3 version: 1.0.3(prettier@3.4.2) @@ -809,6 +809,9 @@ importers: '@sanity/telemetry': specifier: ^0.7.7 version: 0.7.9(react@19.0.0-rc-f994737d14-20240522) + '@sanity/template-validator': + specifier: ^1.0.2 + version: 1.0.2(@types/babel__core@7.20.5)(@types/node@22.10.1)(debug@4.4.0) '@sanity/util': specifier: 3.67.1 version: link:../util @@ -848,9 +851,6 @@ importers: validate-npm-package-name: specifier: ^3.0.0 version: 3.0.0 - yaml: - specifier: ^2.6.1 - version: 2.6.1 devDependencies: '@repo/package.config': specifier: workspace:* @@ -2092,6 +2092,9 @@ packages: '@actions/exec@1.1.1': resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} + '@actions/github@6.0.0': + resolution: {integrity: sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==} + '@actions/http-client@2.2.3': resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} @@ -3975,21 +3978,43 @@ packages: resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==} engines: {node: '>= 14'} + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + '@octokit/core@4.2.4': resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==} engines: {node: '>= 14'} + '@octokit/core@5.2.0': + resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==} + engines: {node: '>= 18'} + '@octokit/endpoint@7.0.6': resolution: {integrity: sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==} engines: {node: '>= 14'} + '@octokit/endpoint@9.0.5': + resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==} + engines: {node: '>= 18'} + '@octokit/graphql@5.0.6': resolution: {integrity: sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==} engines: {node: '>= 14'} + '@octokit/graphql@7.1.0': + resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==} + engines: {node: '>= 18'} + '@octokit/openapi-types@18.1.1': resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==} + '@octokit/openapi-types@20.0.0': + resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} + + '@octokit/openapi-types@22.2.0': + resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} + '@octokit/plugin-enterprise-rest@6.0.1': resolution: {integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==} @@ -3999,11 +4024,23 @@ packages: peerDependencies: '@octokit/core': '>=4' + '@octokit/plugin-paginate-rest@9.2.1': + resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + '@octokit/plugin-request-log@1.0.4': resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==} peerDependencies: '@octokit/core': '>=3' + '@octokit/plugin-rest-endpoint-methods@10.4.1': + resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + '@octokit/plugin-rest-endpoint-methods@7.2.3': resolution: {integrity: sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==} engines: {node: '>= 14'} @@ -4014,10 +4051,18 @@ packages: resolution: {integrity: sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==} engines: {node: '>= 14'} + '@octokit/request-error@5.1.0': + resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==} + engines: {node: '>= 18'} + '@octokit/request@6.2.8': resolution: {integrity: sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==} engines: {node: '>= 14'} + '@octokit/request@8.4.0': + resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} + engines: {node: '>= 18'} + '@octokit/rest@19.0.11': resolution: {integrity: sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==} engines: {node: '>= 14'} @@ -4028,6 +4073,12 @@ packages: '@octokit/types@10.0.0': resolution: {integrity: sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==} + '@octokit/types@12.6.0': + resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} + + '@octokit/types@13.6.2': + resolution: {integrity: sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==} + '@octokit/types@9.3.2': resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==} @@ -4607,6 +4658,10 @@ packages: peerDependencies: react: ^18.2 || >=19.0.0-rc + '@sanity/template-validator@1.0.2': + resolution: {integrity: sha512-tg/zyMr5YO7wt7/hd8K55Ywppbz8nDi0StirOKYMtulG06Jx4IAMmP8IrSpYIutdNoYKiPyyMoWHlhT+HMgCAg==} + engines: {node: '>=18.0.0'} + '@sanity/test@0.0.1-alpha.1': resolution: {integrity: sha512-o2X2Veh9YWyVK/Iou/cToSS6ufcTLREoCVMcvBQbSqCFUIGaN1Ko3zxChJMWdf39dyaJ/ixMKtc8pciF/tL6Sw==} hasBin: true @@ -11782,6 +11837,13 @@ snapshots: dependencies: '@actions/io': 1.1.3 + '@actions/github@6.0.0': + dependencies: + '@actions/http-client': 2.2.3 + '@octokit/core': 5.2.0 + '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.2.0) + '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.0) + '@actions/http-client@2.2.3': dependencies: tunnel: 0.0.6 @@ -13819,6 +13881,8 @@ snapshots: '@octokit/auth-token@3.0.4': {} + '@octokit/auth-token@4.0.0': {} + '@octokit/core@4.2.4(encoding@0.1.13)': dependencies: '@octokit/auth-token': 3.0.4 @@ -13831,12 +13895,27 @@ snapshots: transitivePeerDependencies: - encoding + '@octokit/core@5.2.0': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.0 + '@octokit/request': 8.4.0 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.6.2 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + '@octokit/endpoint@7.0.6': dependencies: '@octokit/types': 9.3.2 is-plain-object: 5.0.0 universal-user-agent: 6.0.1 + '@octokit/endpoint@9.0.5': + dependencies: + '@octokit/types': 13.6.2 + universal-user-agent: 6.0.1 + '@octokit/graphql@5.0.6(encoding@0.1.13)': dependencies: '@octokit/request': 6.2.8(encoding@0.1.13) @@ -13845,8 +13924,18 @@ snapshots: transitivePeerDependencies: - encoding + '@octokit/graphql@7.1.0': + dependencies: + '@octokit/request': 8.4.0 + '@octokit/types': 13.6.2 + universal-user-agent: 6.0.1 + '@octokit/openapi-types@18.1.1': {} + '@octokit/openapi-types@20.0.0': {} + + '@octokit/openapi-types@22.2.0': {} + '@octokit/plugin-enterprise-rest@6.0.1': {} '@octokit/plugin-paginate-rest@6.1.2(@octokit/core@4.2.4(encoding@0.1.13))': @@ -13855,10 +13944,20 @@ snapshots: '@octokit/tsconfig': 1.0.2 '@octokit/types': 9.3.2 + '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 12.6.0 + '@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.4(encoding@0.1.13))': dependencies: '@octokit/core': 4.2.4(encoding@0.1.13) + '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 12.6.0 + '@octokit/plugin-rest-endpoint-methods@7.2.3(@octokit/core@4.2.4(encoding@0.1.13))': dependencies: '@octokit/core': 4.2.4(encoding@0.1.13) @@ -13870,6 +13969,12 @@ snapshots: deprecation: 2.3.1 once: 1.4.0 + '@octokit/request-error@5.1.0': + dependencies: + '@octokit/types': 13.6.2 + deprecation: 2.3.1 + once: 1.4.0 + '@octokit/request@6.2.8(encoding@0.1.13)': dependencies: '@octokit/endpoint': 7.0.6 @@ -13881,6 +13986,13 @@ snapshots: transitivePeerDependencies: - encoding + '@octokit/request@8.4.0': + dependencies: + '@octokit/endpoint': 9.0.5 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.6.2 + universal-user-agent: 6.0.1 + '@octokit/rest@19.0.11(encoding@0.1.13)': dependencies: '@octokit/core': 4.2.4(encoding@0.1.13) @@ -13896,6 +14008,14 @@ snapshots: dependencies: '@octokit/openapi-types': 18.1.1 + '@octokit/types@12.6.0': + dependencies: + '@octokit/openapi-types': 20.0.0 + + '@octokit/types@13.6.2': + dependencies: + '@octokit/openapi-types': 22.2.0 + '@octokit/types@9.3.2': dependencies: '@octokit/openapi-types': 18.1.1 @@ -14703,6 +14823,56 @@ snapshots: - debug - supports-color + '@sanity/pkg-utils@6.12.0(@types/babel__core@7.20.5)(@types/node@22.10.1)(typescript@5.7.2)': + dependencies: + '@babel/core': 7.26.0 + '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) + '@babel/types': 7.26.3 + '@microsoft/api-extractor': 7.48.0(@types/node@22.10.1) + '@microsoft/tsdoc-config': 0.17.1 + '@optimize-lodash/rollup-plugin': 5.0.0(rollup@4.28.1) + '@rollup/plugin-alias': 5.1.1(rollup@4.28.1) + '@rollup/plugin-babel': 6.0.4(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@4.28.1) + '@rollup/plugin-commonjs': 28.0.1(rollup@4.28.1) + '@rollup/plugin-json': 6.1.0(rollup@4.28.1) + '@rollup/plugin-node-resolve': 15.3.0(rollup@4.28.1) + '@rollup/plugin-replace': 6.0.1(rollup@4.28.1) + '@rollup/plugin-terser': 0.4.4(rollup@4.28.1) + '@sanity/browserslist-config': 1.0.3 + browserslist: 4.24.2 + cac: 6.7.14 + chalk: 4.1.2 + chokidar: 4.0.1 + esbuild: 0.24.0 + esbuild-register: 3.6.0(esbuild@0.24.0) + find-config: 1.0.0 + get-latest-version: 5.1.0(debug@4.4.0) + git-url-parse: 16.0.0 + globby: 11.1.0 + jsonc-parser: 3.3.1 + mkdirp: 3.0.1 + outdent: 0.8.0 + parse-git-config: 3.0.0 + pkg-up: 3.1.0 + prettier: 3.4.2 + pretty-bytes: 5.6.0 + prompts: 2.4.2 + recast: 0.23.9 + rimraf: 4.4.1 + rollup: 4.28.1 + rollup-plugin-esbuild: 6.1.1(esbuild@0.24.0)(rollup@4.28.1) + rxjs: 7.8.1 + treeify: 1.1.0 + typescript: 5.7.2 + uuid: 11.0.3 + zod: 3.23.8 + zod-validation-error: 3.4.0(zod@3.23.8) + transitivePeerDependencies: + - '@types/babel__core' + - '@types/node' + - debug + - supports-color + '@sanity/presentation@1.19.8(@emotion/is-prop-valid@1.3.1)(@sanity/color@3.0.6)(debug@4.4.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': dependencies: '@sanity/client': 6.24.1(debug@4.4.0) @@ -14763,6 +14933,20 @@ snapshots: rxjs: 7.8.1 typeid-js: 0.3.0 + '@sanity/template-validator@1.0.2(@types/babel__core@7.20.5)(@types/node@22.10.1)(debug@4.4.0)': + dependencies: + '@actions/core': 1.11.1 + '@actions/github': 6.0.0 + '@sanity/pkg-utils': 6.12.0(@types/babel__core@7.20.5)(@types/node@22.10.1)(babel-plugin-react-compiler@19.0.0-beta-37ed2a7-20241206)(debug@4.4.0)(typescript@5.7.2) + typescript: 5.7.2 + yaml: 2.6.1 + transitivePeerDependencies: + - '@types/babel__core' + - '@types/node' + - babel-plugin-react-compiler + - debug + - supports-color + '@sanity/test@0.0.1-alpha.1': dependencies: '@playwright/test': 1.49.1