Skip to content

Commit

Permalink
Merge pull request #4658 from Shopify/stricter-lint
Browse files Browse the repository at this point in the history
Stricter ESLint ruleset
  • Loading branch information
shauns authored Oct 17, 2024
2 parents 0a99748 + 1506168 commit ede2ab0
Show file tree
Hide file tree
Showing 123 changed files with 254 additions and 89 deletions.
4 changes: 2 additions & 2 deletions graphql.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function projectFactory(name: string, schemaName: string, project: string = 'app
{
add: {
content:
"/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any, tsdoc/syntax */\nimport {JsonMapType} from '@shopify/cli-kit/node/toml'",
"/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any, tsdoc/syntax, @typescript-eslint/no-duplicate-type-constituents */\nimport {JsonMapType} from '@shopify/cli-kit/node/toml'",
},
},
],
Expand All @@ -32,7 +32,7 @@ function projectFactory(name: string, schemaName: string, project: string = 'app
{
add: {
content:
"/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, @typescript-eslint/ban-types */\nimport {JsonMapType} from '@shopify/cli-kit/node/toml'",
"/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/naming-convention, @typescript-eslint/ban-types, @typescript-eslint/no-duplicate-type-constituents */\nimport {JsonMapType} from '@shopify/cli-kit/node/toml'",
},
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
/* eslint-disable @typescript-eslint/consistent-type-definitions, @typescript-eslint/no-duplicate-type-constituents */
import * as Types from './types.js'

import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'
Expand Down
19 changes: 12 additions & 7 deletions packages/app/src/cli/api/graphql/current_account_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ export const CurrentAccountInfoQuery = gql`
}
}
`
interface AccountInfoSchema {
__typename: string
email?: string
orgName?: string
}

type AccountInfoSchema =
| {
__typename: 'UserAccount'
email: string
}
| {
__typename: 'ServiceAccount'
orgName: string
}

export interface CurrentAccountInfoSchema {
currentAccountInfo: AccountInfoSchema
Expand All @@ -40,12 +45,12 @@ function mapAccountInfo(accountInfo: AccountInfoSchema): AccountInfo {
if (accountInfo.__typename === 'UserAccount') {
return {
type: 'UserAccount',
email: accountInfo.email!,
email: accountInfo.email,
}
} else if (accountInfo.__typename === 'ServiceAccount') {
return {
type: 'ServiceAccount',
orgName: accountInfo.orgName!,
orgName: accountInfo.orgName,
}
} else {
return {type: 'UnknownAccount'}
Expand Down
2 changes: 0 additions & 2 deletions packages/app/src/cli/models/app/app.test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ export function testApp(app: Partial<AppInterface> = {}, schemaType: 'current' |
dotenv: app.dotenv,
errors: app.errors,
specifications: app.specifications ?? [],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
configSchema: (app.configSchema ?? AppConfigurationSchema) as any,
remoteFlags: app.remoteFlags ?? [],
})
Expand Down Expand Up @@ -1233,7 +1232,6 @@ const currentAccountInfoResponse: CurrentAccountInfoSchema = {
currentAccountInfo: {
__typename: 'UserAccount',
email: 'user@example.com',
orgName: 'org1',
},
}

Expand Down
1 change: 1 addition & 0 deletions packages/app/src/cli/models/app/app.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {AppErrors, isWebType} from './loader.js'
import {ensurePathStartsWithSlash} from './validation/common.js'
import {ExtensionInstance} from '../extensions/extension-instance.js'
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/cli/models/app/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export async function updateAppIdentifiers(
Object.keys(identifiers.extensions).forEach((identifier) => {
const envVariable = `SHOPIFY_${constantize(identifier)}_ID`
if (!systemEnvironment[envVariable]) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
updatedVariables[envVariable] = identifiers.extensions[identifier]!
}
})
Expand Down Expand Up @@ -137,6 +138,7 @@ export function getAppIdentifiers(
const extensionsIdentifiers: {[key: string]: string} = {}
const processExtension = (extension: ExtensionInstance) => {
if (Object.keys(envVariables).includes(extension.idEnvironmentVariableName)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
extensionsIdentifiers[extension.localIdentifier] = envVariables[extension.idEnvironmentVariableName]!
}
if (developerPlatformClient.supportsAtomicDeployments) {
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/cli/models/app/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ class AppLoader<TConfig extends AppConfiguration, TModuleSpec extends ExtensionS
this.abortOrReport(
outputContent`You can only have one web with the ${outputToken.yellow(webType)} role in your app`,
undefined,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
joinPath(websOfType[1]!.directory, configurationFileNames.web),
)
}
Expand Down Expand Up @@ -1051,6 +1052,7 @@ async function getProjectType(webs: Web[]): Promise<'node' | 'php' | 'ruby' | 'f
outputDebug('Unable to decide project type as no web backend')
return
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const {directory} = backendWebs[0]!

const nodeConfigFile = joinPath(directory, 'package.json')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable no-case-declarations */
import {BaseConfigType, MAX_EXTENSION_HANDLE_LENGTH} from './schemas.js'
import {FunctionConfigType} from './specifications/function.js'
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/cli/models/extensions/specification.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {ZodSchemaType, BaseConfigType, BaseSchema} from './schemas.js'
import {ExtensionInstance} from './extension-instance.js'
import {blocks} from '../../constants.js'
Expand Down Expand Up @@ -398,6 +399,7 @@ function defaultAppConfigReverseTransform<T>(schema: zod.ZodType<T, any, any>, c
result[key] = defaultAppConfigReverseTransform(innerSchema, content)
} else {
if (content[key] !== undefined) result[key] = content[key]
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete content[key]
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ export const WebhookSubscriptionSchema = zod.object({
invalid_type_error: 'Value must be string[]',
})
.optional(),
uri: zod.preprocess(removeTrailingSlash, WebhookSubscriptionUriValidation, {required_error: 'Missing value at'}),
uri: zod.preprocess((arg) => removeTrailingSlash(arg as string), WebhookSubscriptionUriValidation, {
required_error: 'Missing value at',
}),
include_fields: zod.array(zod.string({invalid_type_error: 'Value must be a string'})).optional(),
filter: zod.string({invalid_type_error: 'Value must be a string'}).optional(),
compliance_topics: zod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ interface TransformedWebhookSubscription {
export const SingleWebhookSubscriptionSchema = zod.object({
topic: zod.string(),
api_version: zod.string(),
uri: zod.preprocess(removeTrailingSlash, WebhookSubscriptionUriValidation, {required_error: 'Missing value at'}),
uri: zod.preprocess(removeTrailingSlash as (arg: unknown) => unknown, WebhookSubscriptionUriValidation, {
required_error: 'Missing value at',
}),
include_fields: zod.array(zod.string({invalid_type_error: 'Value must be a string'})).optional(),
filter: zod.string({invalid_type_error: 'Value must be a string'}).optional(),
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const paymentExtensionSpec = createExtensionSpecification({
schema: PaymentsAppExtensionSchema,
appModuleFeatures: (_) => [],
deployConfig: async (config, _) => {
const target = config.targeting[0]!.target
const target = config.targeting[0]?.target
switch (target) {
case OFFSITE_TARGET:
return offsitePaymentsAppExtensionDeployConfig(config as OffsitePaymentsAppExtensionConfigType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ function validateFile(filepath: string, dirname: string): void {
`Make sure all theme app extension files are in the supported directories: ${SUPPORTED_BUCKETS.join(', ')}`,
)
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const filenameValidation = SUPPORTED_EXTS[dirname]!
if (!filepath.match(filenameValidation.validator)) {
throw new AbortError(`Invalid filename in your theme app extension: ${filepath}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export function reduceWebhooks(
const existingSubscription = findSubscription(accumulator, subscription)
if (existingSubscription) {
if (property && subscription?.[property]?.length) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
existingSubscription[property]?.push(...subscription[property]!)
} else {
if (subscription.topics) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ const pubSubRegex = /^pubsub:\/\/(?<gcp_project_id>[^:]+):(?<gcp_topic>.+)$/
const arnRegex =
/^arn:aws:events:(?<aws_region>[a-z]{2}-[a-z]+-[0-9]+)::event-source\/aws\.partner\/shopify\.com(\.test)?\/(?<api_client_id>\d+)\/(?<event_source_name>.+)$/

export const removeTrailingSlash = (arg: unknown) =>
typeof arg === 'string' && arg.endsWith('/') ? arg.replace(/\/+$/, '') : arg
export function removeTrailingSlash(arg: string): string
export function removeTrailingSlash(arg: unknown): unknown {
return typeof arg === 'string' && arg.endsWith('/') ? arg.replace(/\/+$/, '') : arg
}

export const WebhookSubscriptionUriValidation = zod.string({invalid_type_error: 'Value must be string'}).refine(
(uri) => {
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/cli/prompts/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export async function selectConfigFile(directory: string): Promise<Result<string
const files = (await findConfigFiles(directory)).map((path) => basename(path))

if (files.length === 0) return err('Could not find any shopify.app.toml file in the directory.')
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (files.length === 1) return ok(files[0]!)

const chosen = await renderSelectPrompt({
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/cli/prompts/dev.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {Organization, MinimalOrganizationApp, OrganizationStore, MinimalAppIdentifiers} from '../models/organization.js'
import {getTomls} from '../utilities/app/config/getTomls.js'
import {setCachedCommandTomlMap} from '../services/local-storage.js'
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/cli/prompts/generate/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const generateExtensionPrompts = async (
})
}

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const extensionTemplate = extensionTemplates.find((template) => template.identifier === templateType)!

const name = options.name || (await promptName(options.directory, extensionTemplate.defaultName))
Expand Down
10 changes: 6 additions & 4 deletions packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const pollAppLogs = async ({
} catch (error) {
outputWarn(`Error while polling app logs.`)
outputWarn(`Retrying in ${POLLING_ERROR_RETRY_INTERVAL_MS / 1000} seconds.`)
outputDebug(`${error}}\n`)
outputDebug(`${error as string}}\n`)

setTimeout(() => {
pollAppLogs({
Expand All @@ -149,9 +149,11 @@ export const pollAppLogs = async ({
function handleFunctionRunLog(log: AppLogData, payload: {[key: string]: unknown}, stdout: Writable) {
const fuel = ((payload.fuel_consumed as number) / ONE_MILLION).toFixed(4)
if (log.status === 'success') {
stdout.write(`Function export "${payload.export}" executed successfully using ${fuel}M instructions.`)
stdout.write(`Function export "${payload.export as string}" executed successfully using ${fuel}M instructions.`)
} else if (log.status === 'failure') {
stdout.write(`❌ Function export "${payload.export}" failed to execute with error: ${payload.error_type}`)
stdout.write(
`❌ Function export "${payload.export as string}" failed to execute with error: ${payload.error_type as string}`,
)
}
const logs = payload.logs as string
if (logs.length > 0) {
Expand Down Expand Up @@ -180,7 +182,7 @@ function handleFunctionNetworkAccessLog(log: AppLogData, payload: {[key: string]
if (log.status === 'success') {
stdout.write('Function network access request executed successfully.')
} else if (log.status === 'failure') {
stdout.write(`❌ Function network access request failed to execute with error: ${payload.error}.`)
stdout.write(`❌ Function network access request failed to execute with error: ${payload.error as string}.`)
}
}
}
6 changes: 3 additions & 3 deletions packages/app/src/cli/services/app-logs/dev/write-app-logs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {AppLogData, AppLogPayload} from '../types.js'
import {AppLogData} from '../types.js'
import {toFormattedAppLogJson} from '../utils.js'
import {joinPath} from '@shopify/cli-kit/node/path'
import {writeLog, getLogsDir} from '@shopify/cli-kit/node/logs'
Expand All @@ -19,7 +19,7 @@ export const writeAppLogsToFile = async ({
}: {
appLog: AppLogData
// eslint-disable-next-line @typescript-eslint/no-explicit-any
appLogPayload: AppLogPayload | any
appLogPayload: any
apiKey: string
stdout: Writable
storeName: string
Expand All @@ -38,7 +38,7 @@ export const writeAppLogsToFile = async ({
identifier,
}
} catch (error) {
stdout.write(`Error while writing log to file: ${error}\n`)
stdout.write(`Error while writing log to file: ${error as string}\n`)
throw error
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/cli/services/app-logs/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ export function sources(app: AppInterface) {
const tokens = source.split('.')

if (tokens.length >= 2) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const sourceNamespace = tokens[0]!

if (!sourcesByNamespace.has(sourceNamespace)) {
sourcesByNamespace.set(sourceNamespace, [])
}

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sourcesByNamespace.set(sourceNamespace, [...sourcesByNamespace.get(sourceNamespace)!, source])
}
})
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/cli/services/app-logs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class NetworkAccessRequestExecutedLog {
connectTimeMs: number | null
writeReadTimeMs: number | null
httpRequest: unknown
httpResponse: unknown | null
httpResponse: unknown
error: string | null

constructor({
Expand All @@ -134,7 +134,7 @@ export class NetworkAccessRequestExecutedLog {
connectTimeMs: number | null
writeReadTimeMs: number | null
httpRequest: unknown
httpResponse: unknown | null
httpResponse: unknown
error: string | null
}) {
this.attempt = attempt
Expand Down
9 changes: 4 additions & 5 deletions packages/app/src/cli/services/app-logs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
NetworkAccessRequestExecutionInBackgroundLog,
NetworkAccessResponseFromCacheLog,
ErrorResponse,
AppLogPayload,
AppLogData,
} from './types.js'
import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js'
Expand Down Expand Up @@ -175,7 +174,7 @@ export const toFormattedAppLogJson = ({
prettyPrint = true,
}: {
appLog: AppLogData
appLogPayload: AppLogPayload | unknown
appLogPayload: unknown
prettyPrint: boolean
storeName: string
}): string => {
Expand Down Expand Up @@ -203,7 +202,7 @@ export const toFormattedAppLogJson = ({
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const parseAppLogPayload = (payload: string, logType: string): AppLogPayload | any => {
export const parseAppLogPayload = (payload: string, logType: string): any => {
const parsedPayload = camelcaseKeys(JSON.parse(payload), {deep: true})

if (logType === LOG_TYPE_FUNCTION_RUN) {
Expand Down Expand Up @@ -233,7 +232,7 @@ export const subscribeToAppLogs = async (
outputWarn('App log streaming is not available in this session.')
throw new AbortError(errorOutput)
} else {
outputDebug(`Subscribed to App Events for shop ID(s) ${variables.shopIds}`)
outputDebug(`Subscribed to App Events for shop ID(s) ${variables.shopIds.join(', ')}`)
outputDebug(`Success: ${success}\n`)
}
return jwtToken
Expand All @@ -250,6 +249,6 @@ export function prettyPrintJsonIfPossible(json: unknown) {
return json
}
} catch (error) {
throw new Error(`Error parsing JSON: ${error}`)
throw new Error(`Error parsing JSON: ${error as string}`)
}
}
1 change: 1 addition & 0 deletions packages/app/src/cli/services/app/select-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export async function selectApp(): Promise<OrganizationApp> {
hasMorePages,
)
const fullSelectedApp = await developerPlatformClient.appFromId(selectedApp)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return fullSelectedApp!
}

Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/cli/services/build/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export async function buildUIExtension(extension: ExtensionInstance, options: Ex
options.stdout.write(`${extension.localIdentifier} successfully built`)
}

export interface BuildFunctionExtensionOptions extends ExtensionBuildOptions {}
export type BuildFunctionExtensionOptions = ExtensionBuildOptions

/**
* Builds a function extension
Expand Down Expand Up @@ -192,6 +192,7 @@ async function buildOtherFunction(extension: ExtensionInstance, options: BuildFu
async function runCommand(buildCommand: string, extension: ExtensionInstance, options: BuildFunctionExtensionOptions) {
const buildCommandComponents = buildCommand.split(' ')
options.stdout.write(`Building function ${extension.localIdentifier}...`)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await exec(buildCommandComponents[0]!, buildCommandComponents.slice(1), {
stdout: options.stdout,
stderr: options.stderr,
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/cli/services/context.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {selectOrCreateApp} from './dev/select-app.js'
import {fetchOrgFromId, fetchOrganizations, fetchStoreByDomain} from './dev/fetch.js'
import {convertToTransferDisabledStoreIfNeeded, selectStore} from './dev/select-store.js'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {ensureExtensionsIds} from './identifiers-extensions.js'
import {EnsureDeploymentIdsPresenceOptions, LocalSource, RemoteSource} from './identifiers.js'
import {versionDiffByVersion} from '../release/version-diff.js'
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/cli/services/context/id-matching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ function matchByUID(

local.forEach((localSource) => {
const possibleMatch = remote.find((remoteSource) => remoteSource.uid === localSource.uid)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (possibleMatch) matched[localSource.localIdentifier] = possibleMatch.uid!
})

Expand Down Expand Up @@ -121,6 +122,7 @@ function migrateLegacyFunctions(

const remoteId = pendingMigrations[localId]
if (remoteId) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete pendingMigrations[functionExtension.localIdentifier]
migrated[functionExtension.localIdentifier] = remoteId
}
Expand Down
Loading

0 comments on commit ede2ab0

Please sign in to comment.