mirror of
https://github.com/cypress-io/cypress.git
synced 2025-12-30 11:09:49 -06:00
154 lines
5.0 KiB
TypeScript
154 lines
5.0 KiB
TypeScript
// @ts-expect-error - no types
|
|
import rp from '@cypress/request-promise'
|
|
import path from 'path'
|
|
import pDefer from 'p-defer'
|
|
import chalk from 'chalk'
|
|
import fs from 'fs-extra'
|
|
import { buildSchema, extendSchema, GraphQLSchema, introspectionFromSchema, isObjectType, parse } from 'graphql'
|
|
import { minifyIntrospectionQuery } from '@urql/introspection'
|
|
|
|
import { nexusTypegen, watchNexusTypegen } from '../utils/nexusTypegenUtil'
|
|
import { monorepoPaths } from '../monorepoPaths'
|
|
import { spawned, universalSpawn } from '../utils/childProcessUtils'
|
|
import { DEFAULT_INTERNAL_CLOUD_ENV } from '../gulpConstants'
|
|
|
|
export async function nexusCodegen () {
|
|
return nexusTypegen({
|
|
cwd: monorepoPaths.pkgDataContext,
|
|
filePath: path.join(monorepoPaths.pkgDataContext, 'src/schema.ts'),
|
|
outputPath: path.join(monorepoPaths.pkgDataContext, 'src/gen/nxs.gen.ts'),
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Watches & regenerates the
|
|
*/
|
|
export async function nexusCodegenWatch () {
|
|
return watchNexusTypegen({
|
|
cwd: monorepoPaths.pkgDataContext,
|
|
watchPaths: [
|
|
'src/**/*.ts',
|
|
],
|
|
filePath: path.join(monorepoPaths.pkgDataContext, 'graphql/schema.ts'),
|
|
outputPath: path.join(monorepoPaths.pkgDataContext, 'src/gen/nxs.gen.ts'),
|
|
})
|
|
}
|
|
|
|
export async function graphqlCodegen () {
|
|
return spawned('gql-codegen', 'yarn graphql-codegen --config graphql/graphql-codegen.yml', {
|
|
cwd: monorepoPaths.pkgDataContext,
|
|
waitForExit: true,
|
|
})
|
|
}
|
|
|
|
export async function graphqlCodegenWatch () {
|
|
const spawned = universalSpawn('graphql-codegen', ['--watch', '--config', 'graphql/graphql-codegen.yml'], {
|
|
cwd: monorepoPaths.pkgDataContext,
|
|
})
|
|
const dfd = pDefer()
|
|
let hasResolved = false
|
|
|
|
spawned.stdout.on('data', (chunk) => {
|
|
const strs = `${chunk}`.split('\n').filter((f) => f)
|
|
const timestampRegex = /\[\d{2}:\d{2}:\d{2}\]/
|
|
const isFailureBlock = strs.some((s) => s.includes('[failed]'))
|
|
|
|
strs.forEach((str) => {
|
|
let codegenMsg = timestampRegex.test(str) ? str.slice(10) : str
|
|
|
|
if (codegenMsg.includes('Watching for changes') && !hasResolved) {
|
|
dfd.resolve({})
|
|
}
|
|
|
|
if (codegenMsg === str) {
|
|
process.stdout.write(
|
|
`${chalk.cyan('graphqlCodegen')}: ${chalk.gray(str)}\n`,
|
|
)
|
|
} else if (codegenMsg.startsWith(' Generate .') || isFailureBlock) {
|
|
codegenMsg = codegenMsg.includes('[failed]')
|
|
? chalk.red(codegenMsg)
|
|
: chalk.yellow(codegenMsg)
|
|
|
|
process.stdout.write(`${chalk.cyan('graphqlCodegen')}: ${codegenMsg}\n`)
|
|
}
|
|
})
|
|
})
|
|
|
|
spawned.stderr.on('data', (data) => {
|
|
console.error(chalk.red(String(data)))
|
|
})
|
|
|
|
return dfd.promise
|
|
}
|
|
|
|
const ENV_MAP = {
|
|
development: 'http://localhost:3000',
|
|
staging: 'https://cloud-staging.cypress.io',
|
|
production: 'https://cloud.cypress.io',
|
|
}
|
|
|
|
export async function syncRemoteGraphQL () {
|
|
if (!ENV_MAP[DEFAULT_INTERNAL_CLOUD_ENV]) {
|
|
throw new Error(`Expected --env to be one of ${Object.keys(ENV_MAP).join(', ')}`)
|
|
}
|
|
|
|
try {
|
|
const body = await rp.get(`${ENV_MAP[DEFAULT_INTERNAL_CLOUD_ENV]}/test-runner-graphql-schema`)
|
|
|
|
// TODO(tim): fix
|
|
await fs.ensureDir(path.join(monorepoPaths.pkgDataContext, 'src/gen'))
|
|
await fs.promises.writeFile(path.join(monorepoPaths.pkgDataContext, 'schemas/cloud.graphql'), body)
|
|
} catch (error) {
|
|
console.error('Could not sync remote GraphQL schema', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates the schema so the urql GraphCache is
|
|
*/
|
|
export async function generateFrontendSchema () {
|
|
const schemaContents = await fs.promises.readFile(path.join(monorepoPaths.pkgDataContext, 'schemas/schema.graphql'), 'utf8')
|
|
const schema = buildSchema(schemaContents, { assumeValid: true })
|
|
const testExtensions = generateTestExtensions(schema)
|
|
const extendedSchema = extendSchema(schema, parse(testExtensions))
|
|
|
|
const URQL_INTROSPECTION_PATH = path.join(monorepoPaths.pkgDataContext, 'src/gen/urql-introspection.gen.ts')
|
|
|
|
await fs.ensureDir(path.dirname(URQL_INTROSPECTION_PATH))
|
|
await fs.ensureDir(path.join(monorepoPaths.pkgFrontendShared, 'src/generated'))
|
|
await fs.writeFile(path.join(monorepoPaths.pkgFrontendShared, 'src/generated/schema-for-tests.gen.json'), JSON.stringify(introspectionFromSchema(extendedSchema), null, 2))
|
|
|
|
await fs.promises.writeFile(
|
|
URQL_INTROSPECTION_PATH,
|
|
`/* eslint-disable */\nexport const urqlSchema = ${JSON.stringify(minifyIntrospectionQuery(introspectionFromSchema(schema)), null, 2)} as const`,
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Adds two fields to the GraphQL types specific to testing
|
|
*
|
|
* @param schema
|
|
* @returns
|
|
*/
|
|
function generateTestExtensions (schema: GraphQLSchema) {
|
|
const objects: string[] = []
|
|
const typesMap = schema.getTypeMap()
|
|
|
|
for (const [typeName, type] of Object.entries(typesMap)) {
|
|
if (!typeName.startsWith('__') && isObjectType(type)) {
|
|
if (isObjectType(type)) {
|
|
objects.push(typeName)
|
|
}
|
|
}
|
|
}
|
|
|
|
return `
|
|
union TestUnion = ${objects.join(' | ')}
|
|
|
|
extend type Query {
|
|
testFragmentMember: TestUnion!
|
|
testFragmentMemberList(count: Int = 2): [TestUnion!]!
|
|
}
|
|
`
|
|
}
|