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
72 lines (61 loc) • 2.44 kB
text/typescript
import {type CliCommandContext, type CliV3CommandContext} from '@sanity/cli'
import path from 'path'
import readPkgUp from 'read-pkg-up'
import {createSchema} from 'sanity'
import {isMainThread, Worker} from 'worker_threads'
import {
type ResolvedGraphQLAPI,
type ResolvedSourceProperties,
type SchemaDefinitionish,
type TypeResolvedGraphQLAPI,
} from './types'
export async function getGraphQLAPIs(cliContext: CliCommandContext): Promise<ResolvedGraphQLAPI[]> {
if (!isModernCliConfig(cliContext)) {
throw new Error('Expected Sanity studio of version 3 or above')
}
if (!isMainThread) {
throw new Error('getGraphQLAPIs() must be called from the main thread')
}
const defaultSchema = createSchema({name: 'default', types: []})
const defaultTypes = defaultSchema.getTypeNames()
const isCustomType = (type: SchemaDefinitionish) => !defaultTypes.includes(type.name)
const apis = await getApisWithSchemaTypes(cliContext)
const resolved = apis.map(
({schemaTypes, ...api}): ResolvedSourceProperties => ({
schema: createSchema({name: 'default', types: schemaTypes.filter(isCustomType)}),
...api,
}),
)
return resolved
}
function getApisWithSchemaTypes(cliContext: CliCommandContext): Promise<TypeResolvedGraphQLAPI[]> {
return new Promise<TypeResolvedGraphQLAPI[]>((resolve, reject) => {
const {cliConfig, cliConfigPath, workDir} = cliContext
const rootPkgPath = readPkgUp.sync({cwd: __dirname})?.path
if (!rootPkgPath) {
throw new Error('Could not find root directory for `sanity` package')
}
const rootDir = path.dirname(rootPkgPath)
const workerPath = path.join(rootDir, 'lib', '_internal', 'cli', 'threads', 'getGraphQLAPIs.js')
const worker = new Worker(workerPath, {
workerData: {cliConfig: serialize(cliConfig || {}), cliConfigPath, workDir},
// eslint-disable-next-line no-process-env
env: process.env,
})
worker.on('message', resolve)
worker.on('error', reject)
worker.on('exit', (code) => {
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`))
})
})
}
function isModernCliConfig(config: CliCommandContext): config is CliV3CommandContext {
return config.sanityMajorVersion >= 3
}
function serialize<T>(obj: T): T {
try {
return JSON.parse(JSON.stringify(obj))
} catch (cause) {
throw new Error(`Failed to serialize CLI configuration`, {cause})
}
}