Skip to content

Commit

Permalink
Merge pull request #4884 from Shopify/dev-dash-webhooks-api
Browse files Browse the repository at this point in the history
Introduce dev dash webhooks API
  • Loading branch information
cdarne authored Nov 28, 2024
2 parents 01ae069 + 62c69bb commit 2c6914b
Show file tree
Hide file tree
Showing 31 changed files with 627 additions and 61 deletions.
6 changes: 6 additions & 0 deletions bin/get-graphql-schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ const schemas = [
repo: 'shopify',
pathToFile: 'areas/core/shopify/db/graphql/admin_schema_unstable_public.graphql',
localPath: './packages/cli-kit/src/cli/api/graphql/admin/admin_schema.graphql',
},
{
repo: 'shopify',
pathToFile: 'areas/core/shopify/db/graphql/webhooks_schema_unstable_public.graphql',
localPath: './packages/app/src/cli/api/graphql/webhooks/webhooks_schema.graphql',
branch: 'dd',
}
]

Expand Down
6 changes: 5 additions & 1 deletion graphql.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
function projectFactory(name: string, schemaName: string, project: string = 'app') {
return {
schema: `./packages/${project}/src/cli/api/graphql/${name}/${schemaName}`,
documents: [`./packages/${project}/src/cli/api/graphql/${name}/queries/**/*.graphql`,`./packages/${project}/src/cli/api/graphql/${name}/mutations/**/*.graphql`],
documents: [
`./packages/${project}/src/cli/api/graphql/${name}/queries/**/*.graphql`,
`./packages/${project}/src/cli/api/graphql/${name}/mutations/**/*.graphql`,
],
extensions: {
codegen: {
generates: {
Expand Down Expand Up @@ -78,5 +81,6 @@ export default {
appDev: projectFactory('app-dev', 'app_dev_schema.graphql'),
appManagement: projectFactory('app-management', 'app_management_schema.graphql'),
admin: projectFactory('admin', 'admin_schema.graphql', 'cli-kit'),
webhooks: projectFactory('webhooks', 'webhooks_schema.graphql'),
},
}
1 change: 1 addition & 0 deletions nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"build:types",
"graphql-codegen:generate:business-platform",
"graphql-codegen:generate:partners",
"graphql-codegen:generate:webhooks",
"graphql-codegen:postfix",
"graphql-codegen:formatting"
],
Expand Down
26 changes: 21 additions & 5 deletions packages/app/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,17 @@
"{projectRoot}/src/cli/api/graphql/business-platform-destinations/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/business-platform-organizations/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/app-dev/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts"
"{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/webhooks/generated/**/*.ts"
],
"options": {
"commands": [
"pnpm eslint 'src/cli/api/graphql/partners/generated/**/*.{ts,tsx}' --fix",
"pnpm eslint 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix",
"pnpm eslint 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix",
"pnpm eslint 'src/cli/api/graphql/app-dev/generated/**/*.{ts,tsx}' --fix",
"pnpm eslint 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}' --fix"
"pnpm eslint 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}' --fix",
"pnpm eslint 'src/cli/api/graphql/webhooks/generated/**/*.{ts,tsx}' --fix"
],
"cwd": "packages/app"
}
Expand Down Expand Up @@ -137,6 +139,17 @@
"cwd": "{workspaceRoot}"
}
},
"graphql-codegen:generate:webhooks": {
"executor": "nx:run-commands",
"inputs": ["{workspaceRoot}/graphql.config.ts", "{projectRoot}/src/cli/api/graphql/webhooks/**/*.graphql"],
"outputs": ["{projectRoot}/src/cli/api/graphql/webhooks/generated/**/*.ts"],
"options": {
"commands": [
"pnpm exec graphql-codegen --project=webhooks"
],
"cwd": "{workspaceRoot}"
}
},
"graphql-codegen:generate:app-management": {
"executor": "nx:run-commands",
"inputs": ["{workspaceRoot}/graphql.config.ts", "{projectRoot}/src/cli/api/graphql/app-management/**/*.graphql"],
Expand All @@ -155,23 +168,26 @@
"graphql-codegen:generate:business-platform-destinations",
"graphql-codegen:generate:business-platform-organizations",
"graphql-codegen:generate:app-dev",
"graphql-codegen:generate:app-management"
"graphql-codegen:generate:app-management",
"graphql-codegen:generate:webhooks"
],
"inputs": [{ "dependentTasksOutputFiles": "**/*.ts" }],
"outputs": [
"{projectRoot}/src/cli/api/graphql/partners/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/business-platform-destinations/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/business-platform-organizations/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/app-dev/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts"
"{projectRoot}/src/cli/api/graphql/app-management/generated/**/*.ts",
"{projectRoot}/src/cli/api/graphql/webhooks/generated/**/*.ts"
],
"options": {
"commands": [
"find ./packages/app/src/cli/api/graphql/partners/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;",
"find ./packages/app/src/cli/api/graphql/business-platform-destinations/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;",
"find ./packages/app/src/cli/api/graphql/business-platform-organizations/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;",
"find ./packages/app/src/cli/api/graphql/app-dev/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;",
"find ./packages/app/src/cli/api/graphql/app-management/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;"
"find ./packages/app/src/cli/api/graphql/app-management/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;",
"find ./packages/app/src/cli/api/graphql/webhooks/generated/ -type f -name '*.ts' -exec sh -c 'sed -i \"\" \"s|import \\* as Types from '\\''./types'\\'';|import \\* as Types from '\\''./types.js'\\'';|g; s|export const \\([A-Za-z0-9_]*\\)Document =|export const \\1 =|g\" \"$0\"' {} \\;"
],
"cwd": "{workspaceRoot}"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
import * as Types from './types.js'

import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'

export type AvailableTopicsQueryVariables = Types.Exact<{
apiVersion: Types.Scalars['String']['input']
}>

export type AvailableTopicsQuery = {availableTopics?: string[] | null}

export const AvailableTopics = {
kind: 'Document',
definitions: [
{
kind: 'OperationDefinition',
operation: 'query',
name: {kind: 'Name', value: 'availableTopics'},
variableDefinitions: [
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}},
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'Field',
name: {kind: 'Name', value: 'availableTopics'},
arguments: [
{
kind: 'Argument',
name: {kind: 'Name', value: 'apiVersion'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}},
},
],
},
],
},
},
],
} as unknown as DocumentNode<AvailableTopicsQuery, AvailableTopicsQueryVariables>
111 changes: 111 additions & 0 deletions packages/app/src/cli/api/graphql/webhooks/generated/cli-testing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
import * as Types from './types.js'

import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'

export type CliTestingMutationVariables = Types.Exact<{
address: Types.Scalars['String']['input']
apiKey?: Types.InputMaybe<Types.Scalars['String']['input']>
apiVersion: Types.Scalars['String']['input']
deliveryMethod: Types.Scalars['String']['input']
sharedSecret: Types.Scalars['String']['input']
topic: Types.Scalars['String']['input']
}>

export type CliTestingMutation = {
cliTesting?: {headers?: string | null; samplePayload?: string | null; success: boolean; errors: string[]} | null
}

export const CliTesting = {
kind: 'Document',
definitions: [
{
kind: 'OperationDefinition',
operation: 'mutation',
name: {kind: 'Name', value: 'CliTesting'},
variableDefinitions: [
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'address'}},
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
},
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}},
type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}},
},
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}},
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
},
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'deliveryMethod'}},
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
},
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'sharedSecret'}},
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
},
{
kind: 'VariableDefinition',
variable: {kind: 'Variable', name: {kind: 'Name', value: 'topic'}},
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'Field',
name: {kind: 'Name', value: 'cliTesting'},
arguments: [
{
kind: 'Argument',
name: {kind: 'Name', value: 'address'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'address'}},
},
{
kind: 'Argument',
name: {kind: 'Name', value: 'apiKey'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'apiKey'}},
},
{
kind: 'Argument',
name: {kind: 'Name', value: 'apiVersion'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'apiVersion'}},
},
{
kind: 'Argument',
name: {kind: 'Name', value: 'deliveryMethod'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'deliveryMethod'}},
},
{
kind: 'Argument',
name: {kind: 'Name', value: 'sharedSecret'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'sharedSecret'}},
},
{
kind: 'Argument',
name: {kind: 'Name', value: 'topic'},
value: {kind: 'Variable', name: {kind: 'Name', value: 'topic'}},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{kind: 'Field', name: {kind: 'Name', value: 'headers'}},
{kind: 'Field', name: {kind: 'Name', value: 'samplePayload'}},
{kind: 'Field', name: {kind: 'Name', value: 'success'}},
{kind: 'Field', name: {kind: 'Name', value: 'errors'}},
{kind: 'Field', name: {kind: 'Name', value: '__typename'}},
],
},
},
],
},
},
],
} as unknown as DocumentNode<CliTestingMutation, CliTestingMutationVariables>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
import * as Types from './types.js'

import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'

export type PublicApiVersionsQueryVariables = Types.Exact<{[key: string]: never}>

export type PublicApiVersionsQuery = {publicApiVersions: {handle: string}[]}

export const PublicApiVersions = {
kind: 'Document',
definitions: [
{
kind: 'OperationDefinition',
operation: 'query',
name: {kind: 'Name', value: 'publicApiVersions'},
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'Field',
name: {kind: 'Name', value: 'publicApiVersions'},
selectionSet: {
kind: 'SelectionSet',
selections: [
{kind: 'Field', name: {kind: 'Name', value: 'handle'}},
{kind: 'Field', name: {kind: 'Name', value: '__typename'}},
],
},
},
],
},
},
],
} as unknown as DocumentNode<PublicApiVersionsQuery, PublicApiVersionsQueryVariables>
16 changes: 16 additions & 0 deletions packages/app/src/cli/api/graphql/webhooks/generated/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention */
export type Maybe<T> = T | null
export type InputMaybe<T> = Maybe<T>
export type Exact<T extends {[key: string]: unknown}> = {[K in keyof T]: T[K]}
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {[SubKey in K]?: Maybe<T[SubKey]>}
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {[SubKey in K]: Maybe<T[SubKey]>}
export type MakeEmpty<T extends {[key: string]: unknown}, K extends keyof T> = {[_ in K]?: never}
export type Incremental<T> = T | {[P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never}
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
ID: {input: string; output: string}
String: {input: string; output: string}
Boolean: {input: boolean; output: boolean}
Int: {input: number; output: number}
Float: {input: number; output: number}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
query availableTopics($apiVersion: String!) {
availableTopics(apiVersion: $apiVersion)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mutation CliTesting($address: String!, $apiKey: String, $apiVersion: String!, $deliveryMethod: String!, $sharedSecret: String!, $topic: String!) {
cliTesting(address: $address, apiKey: $apiKey, apiVersion: $apiVersion, deliveryMethod: $deliveryMethod, sharedSecret: $sharedSecret, topic: $topic) {
headers
samplePayload
success
errors
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query publicApiVersions {
publicApiVersions {
handle
}
}
1 change: 1 addition & 0 deletions packages/app/src/cli/commands/app/webhook/trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export default class WebhookTrigger extends AppCommand {
clientSecret: flags['client-secret'] || flags['shared-secret'],
path: flags.path,
config: flags.config,
organizationId: appContextResult.organization.id,
}

await webhookTriggerService(usedFlags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export async function setupDevProcesses({
webs: reloadedApp.webs,
backendPort: network.backendPort,
frontendPort: network.frontendPort,
organizationId: remoteApp.organizationId,
developerPlatformClient,
storeFqdn,
apiSecret,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface SendWebhookOptions {
storeFqdn: string
apiSecret: string
webhooksPath: string
organizationId: string
}

export interface SendWebhookProcess extends BaseProcess<SendWebhookOptions> {
Expand All @@ -23,6 +24,7 @@ export const sendWebhook: DevProcessFunction<SendWebhookOptions> = async ({stdou
address: `http://localhost:${options.deliveryPort}${options.webhooksPath}`,
sharedSecret: options.apiSecret,
storeFqdn: options.storeFqdn,
organizationId: options.organizationId,
})
}

Expand All @@ -31,12 +33,14 @@ export function setupSendUninstallWebhookProcess({
remoteAppUpdated,
backendPort,
frontendPort,
organizationId,
...options
}: Pick<SendWebhookOptions, 'developerPlatformClient' | 'storeFqdn' | 'apiSecret'> & {
remoteAppUpdated: boolean
backendPort: number
frontendPort: number
webs: Web[]
organizationId: string
}): SendWebhookProcess | undefined {
const {backendConfig, frontendConfig} = frontAndBackendConfig(webs)
const webhooksPath =
Expand All @@ -52,6 +56,7 @@ export function setupSendUninstallWebhookProcess({
options: {
deliveryPort: backendConfig ? backendPort : frontendPort,
webhooksPath,
organizationId,
...options,
},
}
Expand Down
Loading

0 comments on commit 2c6914b

Please sign in to comment.