Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNH] #3748

Closed
wants to merge 6 commits into from
Closed

[DNH] #3748

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 83 additions & 0 deletions packages/app/src/cli/commands/app/logs.ts
@@ -0,0 +1,83 @@
import {selectDeveloperPlatformClient} from '../../utilities/developer-platform-client.js'
import Command from '../../utilities/app-command.js'
import {appFlags} from '../../flags.js'
import {logs} from '../../services/logs.js'
import {globalFlags} from '@shopify/cli-kit/node/cli'

export default class Logs extends Command {
static summary = 'Streams logs from your app.'
static descriptionWithMarkdown = `Stream function Logs.`

static flags = {
...globalFlags,
...appFlags,
}

static description = this.descriptionWithoutMarkdown()

public async run(): Promise<void> {
const {flags} = await this.parse(Logs)
console.log('[logs.ts run()] flags passed in', flags)
const apiKey = flags['client-id'] || flags['api-key']
const developerPlatformClient = selectDeveloperPlatformClient()
const commandOptions = {
directory: flags.path,
reset: flags.reset,
storeFqdn: flags.store,
apiKey,
}
// interface LogOptions {
// apiKey: string
// storeId: string
// developerPlatformClient: DeveloperPlatformClient
// }

console.log('[logs.ts run()] wipLogsConfig', commandOptions)
await logs(commandOptions)
}
}

// interface LogContextOptions {
// directory: string
// apiKey?: string
// storeFqdn?: string
// reset: boolean
// }

// interface LogContextOutput {
// remoteApp: Omit<OrganizationApp, 'apiSecretKeys'> & {apiSecret?: string}
// storeId: string
// developerPlatformClient: DeveloperPlatformClient
// }

// // returns localApp...
// async function ensureLogsContext(
// options: LogContextOptions,
// developerPlatformClient: DeveloperPlatformClient,
// ): Promise<LogContextOutput> {
// const {configuration, cachedInfo, remoteApp} = await getAppContext({
// ...options,
// developerPlatformClient,
// promptLinkingApp: !options.apiKey,
// })

// const orgId = getOrganization() || cachedInfo?.orgId || (await selectOrg(developerPlatformClient))

// const {app: selectedApp, store: selectedStore} = await fetchDevDataFromOptions(
// options,
// orgId,
// developerPlatformClient,
// )
// const organization = await fetchOrgFromId(orgId, developerPlatformClient)

// return {
// storeId: '2',
// apiKey: remoteApp?.apiKey,
// }
// }

// async function selectOrg(developerPlatformClient: DeveloperPlatformClient): Promise<string> {
// const orgs = await fetchOrganizations(developerPlatformClient)
// const org = await selectOrganizationPrompt(orgs)
// return org.id
// }
2 changes: 2 additions & 0 deletions packages/app/src/cli/index.ts
Expand Up @@ -3,6 +3,7 @@ import ConfigLink from './commands/app/config/link.js'
import ConfigUse from './commands/app/config/use.js'
import Deploy from './commands/app/deploy.js'
import Dev from './commands/app/dev.js'
import Logs from './commands/app/logs.js'
import DraftExtensionsPush from './commands/app/draft-extensions/push.js'
import EnvPull from './commands/app/env/pull.js'
import EnvShow from './commands/app/env/show.js'
Expand All @@ -23,6 +24,7 @@ import WebhookTriggerDeprecated from './commands/webhook/trigger.js'
const APP_COMMANDS = {
'app:build': Build,
'app:deploy': Deploy,
'app:logs': Logs,
'app:dev': Dev,
'app:import-extensions': ImportExtensions,
'app:info': AppInfo,
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/cli/services/dev.ts
Expand Up @@ -134,6 +134,9 @@ async function prepareForDev(commandOptions: DevOptions): Promise<DevConfig> {
developerPlatformClient,
)

// TODO: Do this behind a flag.
const streamAppEvents = true

return {
storeFqdn,
storeId,
Expand All @@ -146,6 +149,7 @@ async function prepareForDev(commandOptions: DevOptions): Promise<DevConfig> {
partnerUrlsUpdated,
graphiqlPort,
graphiqlKey,
streamAppEvents,
}
}

Expand Down
59 changes: 59 additions & 0 deletions packages/app/src/cli/services/dev/processes/app-events-process.ts
@@ -0,0 +1,59 @@
import {BaseProcess, DevProcessFunction} from './types.js'
import {partnersRequest} from '@shopify/cli-kit/node/api/partners'
import {gql} from 'graphql-request'

export interface AppEventsQueryOptions {

Check failure on line 5 in packages/app/src/cli/services/dev/processes/app-events-process.ts

View workflow job for this annotation

GitHub Actions / knip-reporter-annotations-check

packages/app/src/cli/services/dev/processes/app-events-process.ts#L5

'AppEventsQueryOptions' is an unused type
shopId: string
apiKey: string
token: string
}

export interface AppEventsSubscribeProcess extends BaseProcess<AppEventsQueryOptions> {
type: 'app-events-subscribe'
}

interface Props {
partnersSessionToken: string
subscription: {
shopId: string
apiKey: string
}
}

const AppEventsSubscribeMutation = gql`
mutation AppEventsSubscribe($input: AppEventsSubscribeInput!) {
appEventsSubscribe(input: $input) {
jwtToken
success
errors
}
}
`

export function setupAppEventsSubscribeProcess({
partnersSessionToken,
subscription: {shopId, apiKey},
}: Props): AppEventsSubscribeProcess | undefined {
return {
type: 'app-events-subscribe',
prefix: 'app-events',
function: subscribeToAppEvents,
options: {
shopId,
apiKey,
token: partnersSessionToken,
},
}
}

export const subscribeToAppEvents: DevProcessFunction<AppEventsQueryOptions> = async ({stdout}, options) => {

Check failure on line 49 in packages/app/src/cli/services/dev/processes/app-events-process.ts

View workflow job for this annotation

GitHub Actions / knip-reporter-annotations-check

packages/app/src/cli/services/dev/processes/app-events-process.ts#L49

'subscribeToAppEvents' is an unused export
const result = await partnersRequest(AppEventsSubscribeMutation, options.token, {
input: {shopId: options.shopId, apiKey: options.apiKey},
})
console.log('[subscribeToAppEvents](AppEventsSubscribeMutation) result: ', result)

stdout.write(`Subscribed to App Events for SHOP ID ${options.shopId} Api Key ${options.apiKey}\n`)
}
// console.log('result', result)
// const objString = JSON.stringify(result)
// stdout.write(`Result: ${objString}\n`)
@@ -0,0 +1,59 @@
import {BaseProcess, DevProcessFunction} from './types.js'
import {partnersRequest} from '@shopify/cli-kit/node/api/partners'
import {gql} from 'graphql-request'

export interface AppEventsQueryOptions {
shopId: string
apiKey: string
token: string
}

export interface AppEventsSubscribeProcess extends BaseProcess<AppEventsQueryOptions> {
type: 'app-events-subscribe'
}

interface Props {
partnersSessionToken: string
subscription: {
shopId: string
apiKey: string
}
}

const AppEventsSubscribeMutation = gql`
mutation AppEventsSubscribe($input: AppEventsSubscribeInput!) {
appEventsSubscribe(input: $input) {
jwtToken
success
errors
}
}
`

export function setupAppEventsSubscribeProcess({
partnersSessionToken,
subscription: {shopId, apiKey},
}: Props): AppEventsSubscribeProcess | undefined {
return {
type: 'app-events-subscribe',
prefix: 'app-events',
function: subscribeToAppEvents,
options: {
shopId,
apiKey,
token: partnersSessionToken,
},
}
}

export const subscribeToAppEvents: DevProcessFunction<AppEventsQueryOptions> = async ({stdout}, options) => {
const result = await partnersRequest(AppEventsSubscribeMutation, options.token, {
input: {shopId: options.shopId, apiKey: options.apiKey},
})
console.log('[subscribeToAppEvents](AppEventsSubscribeMutation) result: ', result)

stdout.write(`Subscribed to App Events for SHOP ID ${options.shopId} Api Key ${options.apiKey}\n`)
}
// console.log('result', result)
// const objString = JSON.stringify(result)
// stdout.write(`Result: ${objString}\n`)
21 changes: 21 additions & 0 deletions packages/app/src/cli/services/dev/processes/setup-dev-processes.ts
Expand Up @@ -3,6 +3,7 @@ import {PreviewThemeAppExtensionsProcess, setupPreviewThemeAppExtensionsProcess}
import {PreviewableExtensionProcess, setupPreviewableExtensionsProcess} from './previewable-extension.js'
import {DraftableExtensionProcess, setupDraftableExtensionsProcess} from './draftable-extension.js'
import {SendWebhookProcess, setupSendUninstallWebhookProcess} from './uninstall-webhook.js'
import {AppEventsSubscribeProcess, setupAppEventsSubscribeProcess} from './app-events-process.js'
import {GraphiQLServerProcess, setupGraphiQLServerProcess} from './graphiql.js'
import {WebProcess, setupWebProcesses} from './web.js'
import {environmentVariableNames} from '../../../constants.js'
Expand All @@ -29,6 +30,7 @@ type DevProcessDefinition =
| PreviewableExtensionProcess
| DraftableExtensionProcess
| GraphiQLServerProcess
| AppEventsSubscribeProcess

export type DevProcesses = DevProcessDefinition[]

Expand All @@ -49,6 +51,7 @@ export interface DevConfig {
developerPlatformClient: DeveloperPlatformClient
storeFqdn: string
storeId: string
streamAppEvents?: boolean
commandOptions: DevOptions
network: DevNetworkOptions
partnerUrlsUpdated: boolean
Expand All @@ -63,6 +66,7 @@ export async function setupDevProcesses({
remoteApp,
storeFqdn,
storeId,
streamAppEvents,
commandOptions,
network,
graphiqlPort,
Expand All @@ -77,6 +81,15 @@ export async function setupDevProcesses({
const appPreviewUrl = buildAppURLForWeb(storeFqdn, apiKey)
const shouldRenderGraphiQL = !isTruthy(process.env[environmentVariableNames.disableGraphiQLExplorer])

// TODO: Probably a better way to do this...
const {token: partnersSessionToken} = await developerPlatformClient.session()
const functionIds = localApp.allExtensions.filter((ext) => ext.type === 'function').map((ext) => ext.devUUID)

console.log('functions')
console.log('ids: ', functionIds)
console.log('apikey: ', apiKey)
console.log('[STREAMING APP EVENTS]', streamAppEvents)

const processes = [
...(await setupWebProcesses({
webs: localApp.webs,
Expand Down Expand Up @@ -137,6 +150,14 @@ export async function setupDevProcesses({
apiSecret,
remoteAppUpdated,
}),
streamAppEvents &&
setupAppEventsSubscribeProcess({
partnersSessionToken,
subscription: {
shopId: storeId,
apiKey,
},
}),
].filter(stripUndefineds)

// Add http server proxy & configure ports, for processes that need it
Expand Down
13 changes: 13 additions & 0 deletions packages/app/src/cli/services/dev/ui.tsx
@@ -1,5 +1,6 @@
import {PartnersURLs} from './urls.js'
import {Dev, DevProps} from './ui/components/Dev.js'
import {Logs, LogProps} from '../logs/ui/components/Logs.js'
import {AppInterface, isCurrentAppSchema} from '../../models/app/app.js'
import {OrganizationApp} from '../../models/organization.js'
import {getAppConfigurationShorthand} from '../../models/app/loader.js'
Expand Down Expand Up @@ -62,6 +63,18 @@ export async function outputUpdateURLsResult(
}
}

export async function renderLogs({processes, abortController, pollingTime}: LogProps) {
if (terminalSupportsRawMode(process.stdin)) {
console.log('time to workn on <Log />')
return render(<Logs processes={processes} abortController={abortController} pollingTime={pollingTime} />, {
exitOnCtrlC: false,
})
} else {
console.log('time to workn on <Log /> non interactive')
return <></>
}
}

export async function renderDev({
processes,
previewUrl,
Expand Down