import { buildSchema, parse } from 'graphql'; import { createHive } from '@graphql-hive/core'; const isFederation = process.env.FEDERATION === '1'; const isSchemaReportingEnabled = process.env.SCHEMA_REPORTING !== '0'; const isUsageReportingEnabled = process.env.USAGE_REPORTING !== '0'; const envName = process.env.STAGING ? 'staging' : process.env.DEV ? 'dev' : 'local'; const schemaReportingEndpoint = envName === 'staging' ? 'https://app.staging.graphql-hive.com/registry' : envName === 'dev' ? 'https://app.dev.graphql-hive.com/registry' : 'http://localhost:3001/graphql'; const usageReportingEndpoint = envName === 'staging' ? 'https://app.staging.graphql-hive.com/usage' : envName === 'dev' ? 'https://app.dev.graphql-hive.com/usage' : 'http://localhost:4001'; console.log(` Environment: ${envName} Schema reporting endpoint: ${schemaReportingEndpoint} Usage reporting endpoint: ${usageReportingEndpoint} Schema reporting: ${isSchemaReportingEnabled ? 'enabled' : 'disabled'} Usage reporting: ${isUsageReportingEnabled ? 'enabled' : 'disabled'} `); const createInstance = ( service: null | { name: string; url: string; }, ) => { return createHive({ token: process.env.TOKEN!, agent: { name: 'Hive Seed Script', maxSize: 10, }, debug: true, enabled: true, reporting: isSchemaReportingEnabled ? { endpoint: schemaReportingEndpoint, author: 'Hive Seed Script', commit: '1', serviceName: service?.name, serviceUrl: service?.url, } : false, usage: isUsageReportingEnabled ? { clientInfo: () => ({ name: 'Fake Hive Client', version: '1.1.1', }), endpoint: usageReportingEndpoint, max: 10, sampleRate: 1, } : false, }); }; async function single() { const hiveInstance = createInstance(null); await hiveInstance.info(); const schema = buildSchema(/* GraphQL */ ` type Query { field(arg: String): String nested: NestedQuery! } type NestedQuery { test: String } `); const query1 = parse(/* GraphQL */ ` query test { field withArg: field(arg: "test") nested { test } } `); const query2 = parse(/* GraphQL */ ` query testAnother { field } `); hiveInstance.reportSchema({ schema }); const operationsPerBatch = process.env.OPERATIONS ? parseInt(process.env.OPERATIONS) : 1; setInterval( () => { for (let i = 0; i < operationsPerBatch; i++) { const randNumber = Math.random() * 100; console.log('Reporting usage query...'); const done = hiveInstance.collectUsage(); done( { document: randNumber > 50 ? query1 : query2, schema, variableValues: {}, contextValue: {}, }, randNumber > 90 ? { errors: undefined, } : { errors: [{ message: 'oops' }], }, ); } }, process.env.INTERVAL ? parseInt(process.env.INTERVAL) : 1000, ); } const publishMutationDocument = /* GraphQL */ ` mutation schemaPublish($input: SchemaPublishInput!) { schemaPublish(input: $input) { __typename ... on SchemaPublishSuccess { initial valid message linkToWebsite changes { nodes { message criticality } total } } ... on SchemaPublishError { valid linkToWebsite changes { nodes { message criticality } total } errors { nodes { message } total } } } } `; async function federation() { const instance = createInstance(null); const schemaInventory = /* GraphQL */ ` type Product implements ProductItf @key(fields: "id") { id: ID! dimensions: ProductDimension @external delivery(zip: String): DeliveryEstimates @requires(fields: "dimensions { size weight }") } type ProductDimension @shareable { size: String weight: Float } type DeliveryEstimates { estimatedDelivery: String fastestDelivery: String } interface ProductItf { id: ID! dimensions: ProductDimension delivery(zip: String): DeliveryEstimates } enum ShippingClass { STANDARD EXPRESS OVERNIGHT } `; const schemaPandas = /* GraphQL */ ` directive @tag(name: String!) repeatable on FIELD_DEFINITION type Query { allPandas: [Panda] panda(name: ID!): Panda } type Panda { name: ID! favoriteFood: String @tag(name: "nom-nom-nom") } `; const schemaProducts = /* GraphQL */ ` directive @myDirective(a: String!) on FIELD_DEFINITION directive @hello on FIELD_DEFINITION type Query { allProducts: [ProductItf] product(id: ID!): ProductItf } interface ProductItf implements SkuItf { id: ID! sku: String name: String package: String variation: ProductVariation dimensions: ProductDimension createdBy: User hidden: String @inaccessible oldField: String @deprecated(reason: "refactored out") } interface SkuItf { sku: String } type Product implements ProductItf & SkuItf @key(fields: "id") @key(fields: "sku package") @key(fields: "sku variation { id }") { id: ID! @tag(name: "hi-from-products") sku: String name: String @hello package: String variation: ProductVariation dimensions: ProductDimension createdBy: User hidden: String reviewsScore: Float! oldField: String } enum ShippingClass { STANDARD EXPRESS } type ProductVariation { id: ID! name: String } type ProductDimension @shareable { size: String weight: Float } type User @key(fields: "email") { email: ID! totalProductsCreated: Int @shareable } `; const schemaReviews = /* GraphQL */ ` type Product implements ProductItf @key(fields: "id") { id: ID! reviewsCount: Int! reviewsScore: Float! @shareable @override(from: "products") reviews: [Review!]! } interface ProductItf { id: ID! reviewsCount: Int! reviewsScore: Float! reviews: [Review!]! } type Query { review(id: Int!): Review } type Review { id: Int! body: String! } `; const schemaUsers = /* GraphQL */ ` directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT type User @key(fields: "email") { email: ID! @tag(name: "test-from-users") name: String totalProductsCreated: Int createdAt: DateTime } scalar DateTime `; let res = await fetch(schemaReportingEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.TOKEN}`, }, body: JSON.stringify({ query: publishMutationDocument, variables: { input: { author: 'MoneyBoy', commit: '1977', sdl: schemaInventory, service: 'Inventory', url: 'https://inventory.localhost/graphql', }, }, }), }).then(res => res.json()); console.log(JSON.stringify(res, null, 2)); res = await fetch(schemaReportingEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.TOKEN}`, }, body: JSON.stringify({ query: publishMutationDocument, variables: { input: { author: 'MoneyBoy', commit: '1977', sdl: schemaPandas, service: 'Panda', url: 'https://panda.localhost/graphql', }, }, }), }).then(res => res.json()); console.log(JSON.stringify(res, null, 2)); res = await fetch(schemaReportingEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.TOKEN}`, }, body: JSON.stringify({ query: publishMutationDocument, variables: { input: { author: 'MoneyBoy', commit: '1977', sdl: schemaProducts, service: 'Products', url: 'https://products.localhost/graphql', }, }, }), }).then(res => res.json()); console.log(JSON.stringify(res, null, 2)); res = await fetch(schemaReportingEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.TOKEN}`, }, body: JSON.stringify({ query: publishMutationDocument, variables: { input: { author: 'MoneyBoy', commit: '1977', sdl: schemaReviews, service: 'Reviews', url: 'https://reviews.localhost/graphql', }, }, }), }).then(res => res.json()); console.log(JSON.stringify(res, null, 2)); res = await fetch(schemaReportingEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.TOKEN}`, }, body: JSON.stringify({ query: publishMutationDocument, variables: { input: { author: 'MoneyBoy', commit: '1977', sdl: schemaUsers, service: 'Users', url: 'https://users.localhost/graphql', }, }, }), }).then(res => res.json()); console.log(JSON.stringify(res, null, 2)); await instance.info(); } if (isFederation === false) { await single(); } else { await federation(); }