chore: switch to @eslint-react/eslint-plugin, lint entire codebase (#7119)
This commit is contained in:
@@ -19,3 +19,6 @@ fb7d1be2f3325d076b7c967b1730afcef37922c2
|
||||
|
||||
# 3.0 prettier & lint everywhere
|
||||
6789e61488a1d3de56f472ac3214faf344030005
|
||||
|
||||
# 3.0 prettier & lint everywhere again
|
||||
83fd4c66222d7846eeb5cc332dfa99bf1e830831
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { jest } from '@jest/globals'
|
||||
import fs from 'fs'
|
||||
import fse from 'fs-extra'
|
||||
import globby from 'globby'
|
||||
import * as os from 'node:os'
|
||||
import path from 'path'
|
||||
|
||||
import type { CliArgs, DbType, ProjectTemplate } from '../types.js'
|
||||
|
||||
import { createProject } from './create-project.js'
|
||||
import { dbReplacements } from './replacements.js'
|
||||
import { getValidTemplates } from './templates.js'
|
||||
import globby from 'globby'
|
||||
import { jest } from '@jest/globals'
|
||||
import fs from 'fs'
|
||||
import * as os from 'node:os'
|
||||
|
||||
describe('createProject', () => {
|
||||
let projectDir: string
|
||||
@@ -27,7 +29,6 @@ describe('createProject', () => {
|
||||
})
|
||||
|
||||
describe('#createProject', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const args = {
|
||||
_: ['project-name'],
|
||||
'--db': 'mongodb',
|
||||
@@ -41,15 +42,15 @@ describe('createProject', () => {
|
||||
const template: ProjectTemplate = {
|
||||
name: 'plugin',
|
||||
type: 'plugin',
|
||||
url: 'https://github.com/payloadcms/payload-plugin-template',
|
||||
description: 'Template for creating a Payload plugin',
|
||||
url: 'https://github.com/payloadcms/payload-plugin-template',
|
||||
}
|
||||
await createProject({
|
||||
cliArgs: args,
|
||||
projectName,
|
||||
projectDir,
|
||||
template,
|
||||
packageManager,
|
||||
projectDir,
|
||||
projectName,
|
||||
template,
|
||||
})
|
||||
|
||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||
@@ -84,14 +85,14 @@ describe('createProject', () => {
|
||||
|
||||
await createProject({
|
||||
cliArgs,
|
||||
projectName,
|
||||
projectDir,
|
||||
template: template as ProjectTemplate,
|
||||
packageManager,
|
||||
dbDetails: {
|
||||
dbUri: `${db}://localhost:27017/create-project-test`,
|
||||
type: db as DbType,
|
||||
dbUri: `${db}://localhost:27017/create-project-test`,
|
||||
},
|
||||
packageManager,
|
||||
projectDir,
|
||||
projectName,
|
||||
template: template as ProjectTemplate,
|
||||
})
|
||||
|
||||
const dbReplacement = dbReplacements[db as DbType]
|
||||
|
||||
@@ -24,13 +24,13 @@ const writeFile = promisify(fs.writeFile)
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
type InitNextArgs = Pick<CliArgs, '--debug'> & {
|
||||
type InitNextArgs = {
|
||||
dbType: DbType
|
||||
nextAppDetails?: NextAppDetails
|
||||
packageManager: PackageManager
|
||||
projectDir: string
|
||||
useDistFiles?: boolean
|
||||
}
|
||||
} & Pick<CliArgs, '--debug'>
|
||||
|
||||
type InitNextResult =
|
||||
| {
|
||||
@@ -144,11 +144,11 @@ async function addPayloadConfigToTsConfig(projectDir: string, isSrcDir: boolean)
|
||||
}
|
||||
|
||||
function installAndConfigurePayload(
|
||||
args: InitNextArgs & {
|
||||
args: {
|
||||
nextAppDetails: NextAppDetails
|
||||
nextConfigType: NextConfigType
|
||||
useDistFiles?: boolean
|
||||
},
|
||||
} & InitNextArgs,
|
||||
):
|
||||
| { payloadConfigPath: string; success: true }
|
||||
| { payloadConfigPath?: string; reason: string; success: false } {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { parseAndModifyConfigContent, withPayloadStatement } from './wrap-next-config.js'
|
||||
import * as p from '@clack/prompts'
|
||||
import { jest } from '@jest/globals'
|
||||
|
||||
import { parseAndModifyConfigContent, withPayloadStatement } from './wrap-next-config.js'
|
||||
|
||||
const esmConfigs = {
|
||||
defaultNextConfig: `/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
export default nextConfig;
|
||||
`,
|
||||
nextConfigExportNamedDefault: `const nextConfig = {};
|
||||
const wrapped = someFunc(asdf);
|
||||
export { wrapped as default };
|
||||
`,
|
||||
nextConfigWithFunc: `const nextConfig = {};
|
||||
export default someFunc(nextConfig);
|
||||
@@ -14,10 +19,6 @@ export default someFunc(nextConfig);
|
||||
export default someFunc(
|
||||
nextConfig
|
||||
);
|
||||
`,
|
||||
nextConfigExportNamedDefault: `const nextConfig = {};
|
||||
const wrapped = someFunc(asdf);
|
||||
export { wrapped as default };
|
||||
`,
|
||||
nextConfigWithSpread: `const nextConfig = {
|
||||
...someConfig,
|
||||
@@ -27,12 +28,16 @@ export default nextConfig;
|
||||
}
|
||||
|
||||
const cjsConfigs = {
|
||||
anonConfig: `module.exports = {};`,
|
||||
defaultNextConfig: `
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
module.exports = nextConfig;
|
||||
`,
|
||||
anonConfig: `module.exports = {};`,
|
||||
nextConfigExportNamedDefault: `const nextConfig = {};
|
||||
const wrapped = someFunc(asdf);
|
||||
module.exports = wrapped;
|
||||
`,
|
||||
nextConfigWithFunc: `const nextConfig = {};
|
||||
module.exports = someFunc(nextConfig);
|
||||
`,
|
||||
@@ -40,10 +45,6 @@ module.exports = someFunc(nextConfig);
|
||||
module.exports = someFunc(
|
||||
nextConfig
|
||||
);
|
||||
`,
|
||||
nextConfigExportNamedDefault: `const nextConfig = {};
|
||||
const wrapped = someFunc(asdf);
|
||||
module.exports = wrapped;
|
||||
`,
|
||||
nextConfigWithSpread: `const nextConfig = { ...someConfig };
|
||||
module.exports = nextConfig;
|
||||
@@ -76,7 +77,7 @@ describe('parseAndInsertWithPayload', () => {
|
||||
configType,
|
||||
)
|
||||
expect(modifiedConfigContent).toContain(importStatement)
|
||||
expect(modifiedConfigContent).toMatch(/withPayload\(someFunc\(\n nextConfig\n\)\)/)
|
||||
expect(modifiedConfigContent).toMatch(/withPayload\(someFunc\(\n {2}nextConfig\n\)\)/)
|
||||
})
|
||||
|
||||
it('should parse the config with a spread', () => {
|
||||
@@ -137,7 +138,7 @@ describe('parseAndInsertWithPayload', () => {
|
||||
configType,
|
||||
)
|
||||
expect(modifiedConfigContent).toContain(requireStatement)
|
||||
expect(modifiedConfigContent).toMatch(/withPayload\(someFunc\(\n nextConfig\n\)\)/)
|
||||
expect(modifiedConfigContent).toMatch(/withPayload\(someFunc\(\n {2}nextConfig\n\)\)/)
|
||||
})
|
||||
it('should parse the config with a named export as default', () => {
|
||||
const { modifiedConfigContent } = parseAndModifyConfigContent(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
import * as p from '@clack/prompts'
|
||||
import chalk from 'chalk'
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import type { ConnectOptions } from 'mongoose'
|
||||
import type { Connect } from 'payload'
|
||||
|
||||
@@ -24,7 +23,7 @@ export const connect: Connect = async function connect(
|
||||
|
||||
const urlToConnect = this.url
|
||||
|
||||
const connectionOptions: ConnectOptions & { useFacet: undefined } = {
|
||||
const connectionOptions: { useFacet: undefined } & ConnectOptions = {
|
||||
autoIndex: true,
|
||||
...this.connectOptions,
|
||||
useFacet: undefined,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { CreateMigration, MigrationTemplateArgs } from 'payload'
|
||||
|
||||
import fs from 'fs'
|
||||
|
||||
@@ -86,7 +86,6 @@ export const find: Find = async function find(
|
||||
return {
|
||||
...result,
|
||||
docs: docs.map((doc) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
doc.id = doc._id
|
||||
return sanitizeInternalFields(doc)
|
||||
}),
|
||||
|
||||
@@ -104,7 +104,6 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
|
||||
return {
|
||||
...result,
|
||||
docs: docs.map((doc) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
doc.id = doc._id
|
||||
return sanitizeInternalFields(doc)
|
||||
}),
|
||||
|
||||
@@ -101,7 +101,6 @@ export const findVersions: FindVersions = async function findVersions(
|
||||
return {
|
||||
...result,
|
||||
docs: docs.map((doc) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
doc.id = doc._id
|
||||
return sanitizeInternalFields(doc)
|
||||
}),
|
||||
|
||||
@@ -43,10 +43,10 @@ export interface Args {
|
||||
/** Set to false to disable auto-pluralization of collection names, Defaults to true */
|
||||
autoPluralization?: boolean
|
||||
/** Extra configuration options */
|
||||
connectOptions?: ConnectOptions & {
|
||||
connectOptions?: {
|
||||
/** Set false to disable $facet aggregation in non-supporting databases, Defaults to true */
|
||||
useFacet?: boolean
|
||||
}
|
||||
} & ConnectOptions
|
||||
/** Set to true to disable hinting to MongoDB to use 'id' as index. This is currently done when counting documents for pagination. Disabling this optimization might fix some problems with AWS DocumentDB. Defaults to false */
|
||||
disableIndexHints?: boolean
|
||||
migrationDir?: string
|
||||
@@ -59,19 +59,19 @@ export interface Args {
|
||||
url: false | string
|
||||
}
|
||||
|
||||
export type MongooseAdapter = BaseDatabaseAdapter &
|
||||
Args & {
|
||||
collections: {
|
||||
[slug: string]: CollectionModel
|
||||
}
|
||||
connection: Connection
|
||||
globals: GlobalModel
|
||||
mongoMemoryServer: MongoMemoryReplSet
|
||||
sessions: Record<number | string, ClientSession>
|
||||
versions: {
|
||||
[slug: string]: CollectionModel
|
||||
}
|
||||
export type MongooseAdapter = {
|
||||
collections: {
|
||||
[slug: string]: CollectionModel
|
||||
}
|
||||
connection: Connection
|
||||
globals: GlobalModel
|
||||
mongoMemoryServer: MongoMemoryReplSet
|
||||
sessions: Record<number | string, ClientSession>
|
||||
versions: {
|
||||
[slug: string]: CollectionModel
|
||||
}
|
||||
} & Args &
|
||||
BaseDatabaseAdapter
|
||||
|
||||
declare module 'payload' {
|
||||
export interface DatabaseAdapter
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { PaginateOptions } from 'mongoose'
|
||||
import type { Init, SanitizedCollectionConfig } from 'payload'
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
/* eslint-disable class-methods-use-this */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import type { IndexOptions, Schema, SchemaOptions, SchemaTypeOptions } from 'mongoose'
|
||||
import type {
|
||||
ArrayField,
|
||||
@@ -196,12 +193,10 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
|
||||
if (field.localized && config.localization) {
|
||||
config.localization.localeCodes.forEach((localeCode) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error Possible incorrect typing in mongoose types, this works
|
||||
schema.path(`${field.name}.${localeCode}`).discriminator(blockItem.slug, blockSchema)
|
||||
})
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error Possible incorrect typing in mongoose types, this works
|
||||
schema.path(field.name).discriminator(blockItem.slug, blockSchema)
|
||||
}
|
||||
|
||||
@@ -20,11 +20,10 @@ export async function buildAndOrConditions({
|
||||
const completedConditions = []
|
||||
// Loop over all AND / OR operations and add them to the AND / OR query param
|
||||
// Operations should come through as an array
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
||||
for (const condition of where) {
|
||||
// If the operation is properly formatted as an object
|
||||
if (typeof condition === 'object') {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const result = await parseParams({
|
||||
collectionSlug,
|
||||
fields,
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { SanitizedConfig, sanitizeConfig } from 'payload'
|
||||
import { Config } from 'payload'
|
||||
import type { Config, SanitizedConfig } from 'payload'
|
||||
|
||||
import { sanitizeConfig } from 'payload'
|
||||
|
||||
import { getLocalizedSortProperty } from './getLocalizedSortProperty.js'
|
||||
|
||||
let config: SanitizedConfig
|
||||
|
||||
describe('get localized sort property', () => {
|
||||
beforeAll(async () => {
|
||||
config = (await sanitizeConfig({
|
||||
config = await sanitizeConfig({
|
||||
localization: {
|
||||
locales: ['en', 'es'],
|
||||
defaultLocale: 'en',
|
||||
fallback: true,
|
||||
locales: ['en', 'es'],
|
||||
},
|
||||
} as Config)) as SanitizedConfig
|
||||
} as Config)
|
||||
})
|
||||
it('passes through a non-localized sort property', async () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['title'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -25,6 +26,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['title'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('title')
|
||||
@@ -32,7 +34,6 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('properly localizes an un-localized sort property', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['title'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -42,6 +43,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['title'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('title.en')
|
||||
@@ -49,7 +51,6 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('keeps specifically asked-for localized sort properties', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['title', 'es'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -59,6 +60,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['title', 'es'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('title.es')
|
||||
@@ -66,7 +68,6 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('properly localizes nested sort properties', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['group', 'title'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -82,6 +83,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['group', 'title'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('group.title.en')
|
||||
@@ -89,7 +91,6 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('keeps requested locale with nested sort properties', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['group', 'title', 'es'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -105,6 +106,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['group', 'title', 'es'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('group.title.es')
|
||||
@@ -112,7 +114,6 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('properly localizes field within row', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['title'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -127,6 +128,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['title'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('title.en')
|
||||
@@ -134,7 +136,6 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('properly localizes field within named tab', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['tab', 'title'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
@@ -154,6 +155,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['tab', 'title'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('tab.title.en')
|
||||
@@ -161,14 +163,12 @@ describe('get localized sort property', () => {
|
||||
|
||||
it('properly localizes field within unnamed tab', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
segments: ['title'],
|
||||
config,
|
||||
fields: [
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
label: 'Tab',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
@@ -176,11 +176,13 @@ describe('get localized sort property', () => {
|
||||
localized: true,
|
||||
},
|
||||
],
|
||||
label: 'Tab',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
locale: 'en',
|
||||
segments: ['title'],
|
||||
})
|
||||
|
||||
expect(result).toStrictEqual('title.en')
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import type { FilterQuery } from 'mongoose'
|
||||
import type { Field, Operator, Payload, Where } from 'payload'
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
|
||||
return {
|
||||
...result,
|
||||
docs: docs.map((doc) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
doc = {
|
||||
_id: doc.parent,
|
||||
id: doc.parent,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { resendAdapter } from './index.js'
|
||||
import { Payload } from 'payload'
|
||||
import type { Payload } from 'payload'
|
||||
|
||||
import { jest } from '@jest/globals'
|
||||
|
||||
import { resendAdapter } from './index.js'
|
||||
|
||||
describe('email-resend', () => {
|
||||
const defaultFromAddress = 'dev@payloadcms.com'
|
||||
const defaultFromName = 'Payload CMS'
|
||||
@@ -29,16 +31,16 @@ describe('email-resend', () => {
|
||||
) as jest.Mock
|
||||
|
||||
const adapter = resendAdapter({
|
||||
apiKey,
|
||||
defaultFromAddress,
|
||||
defaultFromName,
|
||||
apiKey,
|
||||
})
|
||||
|
||||
await adapter({ payload: mockPayload }).sendEmail({
|
||||
from,
|
||||
to,
|
||||
subject,
|
||||
text,
|
||||
to,
|
||||
})
|
||||
|
||||
// @ts-expect-error
|
||||
@@ -48,16 +50,16 @@ describe('email-resend', () => {
|
||||
expect(request.headers.Authorization).toStrictEqual(`Bearer ${apiKey}`)
|
||||
expect(JSON.parse(request.body)).toMatchObject({
|
||||
from,
|
||||
to,
|
||||
subject,
|
||||
text,
|
||||
to,
|
||||
})
|
||||
})
|
||||
|
||||
it('should throw an error if the email fails to send', async () => {
|
||||
const errorResponse = {
|
||||
message: 'error information',
|
||||
name: 'validation_error',
|
||||
message: 'error information',
|
||||
statusCode: 403,
|
||||
}
|
||||
global.fetch = jest.spyOn(global, 'fetch').mockImplementation(
|
||||
@@ -69,17 +71,17 @@ describe('email-resend', () => {
|
||||
) as jest.Mock
|
||||
|
||||
const adapter = resendAdapter({
|
||||
apiKey,
|
||||
defaultFromAddress,
|
||||
defaultFromName,
|
||||
apiKey,
|
||||
})
|
||||
|
||||
await expect(() =>
|
||||
adapter({ payload: mockPayload }).sendEmail({
|
||||
from,
|
||||
to,
|
||||
subject,
|
||||
text,
|
||||
to,
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
`Error sending email: ${errorResponse.statusCode} ${errorResponse.name} - ${errorResponse.message}`,
|
||||
|
||||
@@ -4,17 +4,20 @@ import jestDom from 'eslint-plugin-jest-dom'
|
||||
import jest from 'eslint-plugin-jest'
|
||||
import { deepMerge } from '../../deepMerge.js'
|
||||
|
||||
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
export const index = deepMerge(
|
||||
jestRules,
|
||||
jestDomRules,
|
||||
{
|
||||
rules: jestRules,
|
||||
},
|
||||
{
|
||||
rules: jestDomRules,
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
jest,
|
||||
'jest-dom': jestDom,
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
export default index
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
export const index = {
|
||||
rules: {
|
||||
'jest-dom/prefer-checked': 'error',
|
||||
'jest-dom/prefer-enabled-disabled': 'error',
|
||||
'jest-dom/prefer-focus': 'error',
|
||||
'jest-dom/prefer-required': 'error',
|
||||
'jest-dom/prefer-to-have-attribute': 'error',
|
||||
},
|
||||
'jest-dom/prefer-checked': 'error',
|
||||
'jest-dom/prefer-enabled-disabled': 'error',
|
||||
'jest-dom/prefer-focus': 'error',
|
||||
'jest-dom/prefer-required': 'error',
|
||||
'jest-dom/prefer-to-have-attribute': 'error',
|
||||
}
|
||||
|
||||
export default index
|
||||
|
||||
@@ -1,40 +1,38 @@
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
export const index = {
|
||||
rules: {
|
||||
'jest/consistent-test-it': ['error', { fn: 'it' }],
|
||||
'jest/expect-expect': 'error',
|
||||
'jest/prefer-lowercase-title': ['error', { ignore: ['describe'] }],
|
||||
'jest/no-alias-methods': 'error',
|
||||
'jest/no-commented-out-tests': 'off',
|
||||
'jest/no-disabled-tests': 'off',
|
||||
'jest/no-duplicate-hooks': 'error',
|
||||
'jest/no-export': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-hooks': 'off',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/no-conditional-in-test': 'error',
|
||||
'jest/no-jasmine-globals': 'error',
|
||||
'jest/no-large-snapshots': 'error',
|
||||
'jest/no-mocks-import': 'error',
|
||||
'jest/no-standalone-expect': 'error',
|
||||
'jest/no-done-callback': 'error',
|
||||
'jest/no-test-prefixes': 'error',
|
||||
'jest/no-test-return-statement': 'error',
|
||||
'jest/prefer-called-with': 'error',
|
||||
'jest/prefer-expect-assertions': 'off',
|
||||
'jest/prefer-hooks-on-top': 'error',
|
||||
'jest/prefer-spy-on': 'error',
|
||||
'jest/prefer-strict-equal': 'error',
|
||||
'jest/prefer-to-contain': 'error',
|
||||
'jest/prefer-to-have-length': 'error',
|
||||
'jest/prefer-todo': 'error',
|
||||
'jest/require-top-level-describe': 'error',
|
||||
'jest/require-to-throw-message': 'error',
|
||||
'jest/valid-describe-callback': 'error',
|
||||
'jest/valid-expect-in-promise': 'error',
|
||||
'jest/valid-expect': 'error',
|
||||
'jest/valid-title': 'error',
|
||||
},
|
||||
'jest/consistent-test-it': ['error', { fn: 'it' }],
|
||||
'jest/expect-expect': 'error',
|
||||
'jest/prefer-lowercase-title': ['error', { ignore: ['describe'] }],
|
||||
'jest/no-alias-methods': 'error',
|
||||
'jest/no-commented-out-tests': 'off',
|
||||
'jest/no-disabled-tests': 'off',
|
||||
'jest/no-duplicate-hooks': 'error',
|
||||
'jest/no-export': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-hooks': 'off',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/no-conditional-in-test': 'warn',
|
||||
'jest/no-jasmine-globals': 'error',
|
||||
'jest/no-large-snapshots': 'error',
|
||||
'jest/no-mocks-import': 'error',
|
||||
'jest/no-standalone-expect': 'error',
|
||||
'jest/no-done-callback': 'error',
|
||||
'jest/no-test-prefixes': 'error',
|
||||
'jest/no-test-return-statement': 'error',
|
||||
'jest/prefer-called-with': 'error',
|
||||
'jest/prefer-expect-assertions': 'off',
|
||||
'jest/prefer-hooks-on-top': 'error',
|
||||
'jest/prefer-spy-on': 'off', // broken in packages/create-payload-app/src/lib/create-project.spec.ts
|
||||
'jest/prefer-strict-equal': 'warn',
|
||||
'jest/prefer-to-contain': 'error',
|
||||
'jest/prefer-to-have-length': 'error',
|
||||
'jest/prefer-todo': 'error',
|
||||
'jest/require-top-level-describe': 'error',
|
||||
'jest/require-to-throw-message': 'error',
|
||||
'jest/valid-describe-callback': 'error',
|
||||
'jest/valid-expect-in-promise': 'error',
|
||||
'jest/valid-expect': 'error',
|
||||
'jest/valid-title': 'error',
|
||||
}
|
||||
|
||||
export default index
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
import reactRules from './rules/react.mjs'
|
||||
import reactA11yRules from './rules/react-a11y.mjs'
|
||||
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
||||
import eslintPluginReactConfig from 'eslint-plugin-react/configs/recommended.js'
|
||||
import eslintPluginReact from 'eslint-plugin-react'
|
||||
import react from '@eslint-react/eslint-plugin'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import globals from 'globals';
|
||||
import { fixupPluginRules } from '@eslint/compat'
|
||||
import globals from 'globals'
|
||||
import { deepMerge } from '../../deepMerge.js'
|
||||
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
export const index = deepMerge(
|
||||
react.configs['recommended-type-checked'],
|
||||
{
|
||||
rules: eslintPluginReact.configs.recommended.rules
|
||||
rules: reactRules,
|
||||
},
|
||||
{
|
||||
rules: eslintPluginReactConfig.rules // Only take rules from the config, not plugins, as plugins there are on the old eslint v8 format => add react-hooks plugin myself below
|
||||
rules: reactA11yRules,
|
||||
},
|
||||
reactRules,
|
||||
reactA11yRules,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
@@ -26,12 +23,11 @@ export const index = deepMerge(
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'jsx-a11y': jsxA11y,
|
||||
react: fixupPluginRules(eslintPluginReact),
|
||||
'react-hooks': reactHooks,
|
||||
},
|
||||
settings: {
|
||||
@@ -39,6 +35,6 @@ export const index = deepMerge(
|
||||
version: 'detect',
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
export default index
|
||||
|
||||
@@ -1,249 +1,246 @@
|
||||
|
||||
// Sourced from https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb/rules/react-a11y.js
|
||||
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
export const index = {
|
||||
rules: {
|
||||
// Enforce that anchors have content
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
|
||||
'jsx-a11y/anchor-has-content': ['error', { components: [] }],
|
||||
// Enforce that anchors have content
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md
|
||||
'jsx-a11y/anchor-has-content': ['error', { components: [] }],
|
||||
|
||||
// Require ARIA roles to be valid and non-abstract
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md
|
||||
'jsx-a11y/aria-role': ['error', { ignoreNonDom: false }],
|
||||
// Require ARIA roles to be valid and non-abstract
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md
|
||||
'jsx-a11y/aria-role': ['error', { ignoreNonDom: false }],
|
||||
|
||||
// Enforce all aria-* props are valid.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md
|
||||
'jsx-a11y/aria-props': 'error',
|
||||
// Enforce all aria-* props are valid.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md
|
||||
'jsx-a11y/aria-props': 'error',
|
||||
|
||||
// Enforce ARIA state and property values are valid.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md
|
||||
'jsx-a11y/aria-proptypes': 'error',
|
||||
// Enforce ARIA state and property values are valid.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md
|
||||
'jsx-a11y/aria-proptypes': 'error',
|
||||
|
||||
// Enforce that elements that do not support ARIA roles, states, and
|
||||
// properties do not have those attributes.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md
|
||||
'jsx-a11y/aria-unsupported-elements': 'error',
|
||||
// Enforce that elements that do not support ARIA roles, states, and
|
||||
// properties do not have those attributes.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md
|
||||
'jsx-a11y/aria-unsupported-elements': 'error',
|
||||
|
||||
// Enforce that all elements that require alternative text have meaningful information
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
|
||||
'jsx-a11y/alt-text': [
|
||||
'error',
|
||||
{
|
||||
elements: ['img', 'object', 'area', 'input[type="image"]'],
|
||||
img: [],
|
||||
object: [],
|
||||
area: [],
|
||||
'input[type="image"]': [],
|
||||
// Enforce that all elements that require alternative text have meaningful information
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
|
||||
'jsx-a11y/alt-text': [
|
||||
'error',
|
||||
{
|
||||
elements: ['img', 'object', 'area', 'input[type="image"]'],
|
||||
img: [],
|
||||
object: [],
|
||||
area: [],
|
||||
'input[type="image"]': [],
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent img alt text from containing redundant words like "image", "picture", or "photo"
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md
|
||||
'jsx-a11y/img-redundant-alt': 'error',
|
||||
|
||||
// require that JSX labels use "htmlFor"
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md
|
||||
// deprecated: replaced by `label-has-associated-control` rule
|
||||
'jsx-a11y/label-has-for': [
|
||||
'off',
|
||||
{
|
||||
components: [],
|
||||
required: {
|
||||
every: ['nesting', 'id'],
|
||||
},
|
||||
],
|
||||
allowChildren: false,
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent img alt text from containing redundant words like "image", "picture", or "photo"
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md
|
||||
'jsx-a11y/img-redundant-alt': 'error',
|
||||
// Enforce that a label tag has a text label and an associated control.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md
|
||||
'jsx-a11y/label-has-associated-control': [
|
||||
'error',
|
||||
{
|
||||
labelComponents: [],
|
||||
labelAttributes: [],
|
||||
controlComponents: [],
|
||||
assert: 'both',
|
||||
depth: 25,
|
||||
},
|
||||
],
|
||||
|
||||
// require that JSX labels use "htmlFor"
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md
|
||||
// deprecated: replaced by `label-has-associated-control` rule
|
||||
'jsx-a11y/label-has-for': [
|
||||
'off',
|
||||
{
|
||||
components: [],
|
||||
required: {
|
||||
every: ['nesting', 'id'],
|
||||
},
|
||||
allowChildren: false,
|
||||
},
|
||||
],
|
||||
// Enforce that a control (an interactive element) has a text label.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md
|
||||
'jsx-a11y/control-has-associated-label': [
|
||||
'error',
|
||||
{
|
||||
labelAttributes: ['label'],
|
||||
controlComponents: [],
|
||||
ignoreElements: ['audio', 'canvas', 'embed', 'input', 'textarea', 'tr', 'video'],
|
||||
ignoreRoles: [
|
||||
'grid',
|
||||
'listbox',
|
||||
'menu',
|
||||
'menubar',
|
||||
'radiogroup',
|
||||
'row',
|
||||
'tablist',
|
||||
'toolbar',
|
||||
'tree',
|
||||
'treegrid',
|
||||
],
|
||||
depth: 5,
|
||||
},
|
||||
],
|
||||
|
||||
// Enforce that a label tag has a text label and an associated control.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md
|
||||
'jsx-a11y/label-has-associated-control': [
|
||||
'error',
|
||||
{
|
||||
labelComponents: [],
|
||||
labelAttributes: [],
|
||||
controlComponents: [],
|
||||
assert: 'both',
|
||||
depth: 25,
|
||||
},
|
||||
],
|
||||
// require that mouseover/out come with focus/blur, for keyboard-only users
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
|
||||
'jsx-a11y/mouse-events-have-key-events': 'error',
|
||||
|
||||
// Enforce that a control (an interactive element) has a text label.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md
|
||||
'jsx-a11y/control-has-associated-label': [
|
||||
'error',
|
||||
{
|
||||
labelAttributes: ['label'],
|
||||
controlComponents: [],
|
||||
ignoreElements: ['audio', 'canvas', 'embed', 'input', 'textarea', 'tr', 'video'],
|
||||
ignoreRoles: [
|
||||
'grid',
|
||||
'listbox',
|
||||
'menu',
|
||||
'menubar',
|
||||
'radiogroup',
|
||||
'row',
|
||||
'tablist',
|
||||
'toolbar',
|
||||
'tree',
|
||||
'treegrid',
|
||||
],
|
||||
depth: 5,
|
||||
},
|
||||
],
|
||||
// Prevent use of `accessKey`
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md
|
||||
'jsx-a11y/no-access-key': 'error',
|
||||
|
||||
// require that mouseover/out come with focus/blur, for keyboard-only users
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
|
||||
'jsx-a11y/mouse-events-have-key-events': 'error',
|
||||
// require onBlur instead of onChange
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md
|
||||
'jsx-a11y/no-onchange': 'off',
|
||||
|
||||
// Prevent use of `accessKey`
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md
|
||||
'jsx-a11y/no-access-key': 'error',
|
||||
// Elements with an interactive role and interaction handlers must be focusable
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md
|
||||
'jsx-a11y/interactive-supports-focus': 'error',
|
||||
|
||||
// require onBlur instead of onChange
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md
|
||||
'jsx-a11y/no-onchange': 'off',
|
||||
// Enforce that elements with ARIA roles must have all required attributes
|
||||
// for that role.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md
|
||||
'jsx-a11y/role-has-required-aria-props': 'error',
|
||||
|
||||
// Elements with an interactive role and interaction handlers must be focusable
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md
|
||||
'jsx-a11y/interactive-supports-focus': 'error',
|
||||
// Enforce that elements with explicit or implicit roles defined contain
|
||||
// only aria-* properties supported by that role.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md
|
||||
'jsx-a11y/role-supports-aria-props': 'error',
|
||||
|
||||
// Enforce that elements with ARIA roles must have all required attributes
|
||||
// for that role.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md
|
||||
'jsx-a11y/role-has-required-aria-props': 'error',
|
||||
// Enforce tabIndex value is not greater than zero.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md
|
||||
'jsx-a11y/tabindex-no-positive': 'error',
|
||||
|
||||
// Enforce that elements with explicit or implicit roles defined contain
|
||||
// only aria-* properties supported by that role.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md
|
||||
'jsx-a11y/role-supports-aria-props': 'error',
|
||||
// ensure <hX> tags have content and are not aria-hidden
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md
|
||||
'jsx-a11y/heading-has-content': ['error', { components: [''] }],
|
||||
|
||||
// Enforce tabIndex value is not greater than zero.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md
|
||||
'jsx-a11y/tabindex-no-positive': 'error',
|
||||
// require HTML elements to have a "lang" prop
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md
|
||||
'jsx-a11y/html-has-lang': 'error',
|
||||
|
||||
// ensure <hX> tags have content and are not aria-hidden
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md
|
||||
'jsx-a11y/heading-has-content': ['error', { components: [''] }],
|
||||
// require HTML element's lang prop to be valid
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md
|
||||
'jsx-a11y/lang': 'error',
|
||||
|
||||
// require HTML elements to have a "lang" prop
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md
|
||||
'jsx-a11y/html-has-lang': 'error',
|
||||
// prevent distracting elements, like <marquee> and <blink>
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md
|
||||
'jsx-a11y/no-distracting-elements': [
|
||||
'error',
|
||||
{
|
||||
elements: ['marquee', 'blink'],
|
||||
},
|
||||
],
|
||||
|
||||
// require HTML element's lang prop to be valid
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md
|
||||
'jsx-a11y/lang': 'error',
|
||||
// only allow <th> to have the "scope" attr
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md
|
||||
'jsx-a11y/scope': 'error',
|
||||
|
||||
// prevent distracting elements, like <marquee> and <blink>
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md
|
||||
'jsx-a11y/no-distracting-elements': [
|
||||
'error',
|
||||
{
|
||||
elements: ['marquee', 'blink'],
|
||||
},
|
||||
],
|
||||
// require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md
|
||||
'jsx-a11y/click-events-have-key-events': 'error',
|
||||
|
||||
// only allow <th> to have the "scope" attr
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md
|
||||
'jsx-a11y/scope': 'error',
|
||||
// Enforce that DOM elements without semantic behavior not have interaction handlers
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md
|
||||
'jsx-a11y/no-static-element-interactions': [
|
||||
'error',
|
||||
{
|
||||
handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
|
||||
},
|
||||
],
|
||||
|
||||
// require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md
|
||||
'jsx-a11y/click-events-have-key-events': 'error',
|
||||
// A non-interactive element does not support event handlers (mouse and key handlers)
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md
|
||||
'jsx-a11y/no-noninteractive-element-interactions': [
|
||||
'error',
|
||||
{
|
||||
handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
|
||||
},
|
||||
],
|
||||
|
||||
// Enforce that DOM elements without semantic behavior not have interaction handlers
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md
|
||||
'jsx-a11y/no-static-element-interactions': [
|
||||
'error',
|
||||
{
|
||||
handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
|
||||
},
|
||||
],
|
||||
// ensure emoji are accessible
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md
|
||||
'jsx-a11y/accessible-emoji': 'error',
|
||||
|
||||
// A non-interactive element does not support event handlers (mouse and key handlers)
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md
|
||||
'jsx-a11y/no-noninteractive-element-interactions': [
|
||||
'error',
|
||||
{
|
||||
handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
|
||||
},
|
||||
],
|
||||
// elements with aria-activedescendant must be tabbable
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md
|
||||
'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
|
||||
|
||||
// ensure emoji are accessible
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md
|
||||
'jsx-a11y/accessible-emoji': 'error',
|
||||
// ensure iframe elements have a unique title
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md
|
||||
'jsx-a11y/iframe-has-title': 'error',
|
||||
|
||||
// elements with aria-activedescendant must be tabbable
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md
|
||||
'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
|
||||
// prohibit autoFocus prop
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md
|
||||
'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }],
|
||||
|
||||
// ensure iframe elements have a unique title
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md
|
||||
'jsx-a11y/iframe-has-title': 'error',
|
||||
// ensure HTML elements do not specify redundant ARIA roles
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md
|
||||
'jsx-a11y/no-redundant-roles': 'error',
|
||||
|
||||
// prohibit autoFocus prop
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md
|
||||
'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }],
|
||||
// media elements must have captions
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md
|
||||
'jsx-a11y/media-has-caption': [
|
||||
'error',
|
||||
{
|
||||
audio: [],
|
||||
video: [],
|
||||
track: [],
|
||||
},
|
||||
],
|
||||
|
||||
// ensure HTML elements do not specify redundant ARIA roles
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md
|
||||
'jsx-a11y/no-redundant-roles': 'error',
|
||||
// WAI-ARIA roles should not be used to convert an interactive element to non-interactive
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md
|
||||
'jsx-a11y/no-interactive-element-to-noninteractive-role': [
|
||||
'error',
|
||||
{
|
||||
tr: ['none', 'presentation'],
|
||||
},
|
||||
],
|
||||
|
||||
// media elements must have captions
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md
|
||||
'jsx-a11y/media-has-caption': [
|
||||
'error',
|
||||
{
|
||||
audio: [],
|
||||
video: [],
|
||||
track: [],
|
||||
},
|
||||
],
|
||||
// WAI-ARIA roles should not be used to convert a non-interactive element to interactive
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md
|
||||
'jsx-a11y/no-noninteractive-element-to-interactive-role': [
|
||||
'error',
|
||||
{
|
||||
ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
|
||||
ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
|
||||
li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
|
||||
table: ['grid'],
|
||||
td: ['gridcell'],
|
||||
},
|
||||
],
|
||||
|
||||
// WAI-ARIA roles should not be used to convert an interactive element to non-interactive
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md
|
||||
'jsx-a11y/no-interactive-element-to-noninteractive-role': [
|
||||
'error',
|
||||
{
|
||||
tr: ['none', 'presentation'],
|
||||
},
|
||||
],
|
||||
// Tab key navigation should be limited to elements on the page that can be interacted with.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md
|
||||
'jsx-a11y/no-noninteractive-tabindex': [
|
||||
'error',
|
||||
{
|
||||
tags: [],
|
||||
roles: ['tabpanel'],
|
||||
},
|
||||
],
|
||||
|
||||
// WAI-ARIA roles should not be used to convert a non-interactive element to interactive
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md
|
||||
'jsx-a11y/no-noninteractive-element-to-interactive-role': [
|
||||
'error',
|
||||
{
|
||||
ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
|
||||
ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
|
||||
li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
|
||||
table: ['grid'],
|
||||
td: ['gridcell'],
|
||||
},
|
||||
],
|
||||
|
||||
// Tab key navigation should be limited to elements on the page that can be interacted with.
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md
|
||||
'jsx-a11y/no-noninteractive-tabindex': [
|
||||
'error',
|
||||
{
|
||||
tags: [],
|
||||
roles: ['tabpanel'],
|
||||
},
|
||||
],
|
||||
|
||||
// ensure <a> tags are valid
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md
|
||||
'jsx-a11y/anchor-is-valid': [
|
||||
'error',
|
||||
{
|
||||
components: ['Link'],
|
||||
specialLink: ['to'],
|
||||
aspects: ['noHref', 'invalidHref', 'preferButton'],
|
||||
},
|
||||
],
|
||||
},
|
||||
// ensure <a> tags are valid
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md
|
||||
'jsx-a11y/anchor-is-valid': [
|
||||
'error',
|
||||
{
|
||||
components: ['Link'],
|
||||
specialLink: ['to'],
|
||||
aspects: ['noHref', 'invalidHref', 'preferButton'],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default index
|
||||
|
||||
@@ -1,549 +1,18 @@
|
||||
/** @type {import('eslint').Linter.FlatConfig} */
|
||||
export const index = {
|
||||
rules: {
|
||||
// View link below for react rules documentation
|
||||
// https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules
|
||||
|
||||
// Specify whether double or single quotes should be used in JSX attributes
|
||||
// https://eslint.org/docs/rules/jsx-quotes
|
||||
'jsx-quotes': ['error', 'prefer-double'],
|
||||
|
||||
'class-methods-use-this': [
|
||||
'error',
|
||||
{
|
||||
exceptMethods: [
|
||||
'render',
|
||||
'getInitialState',
|
||||
'getDefaultProps',
|
||||
'getChildContext',
|
||||
'componentWillMount',
|
||||
'UNSAFE_componentWillMount',
|
||||
'componentDidMount',
|
||||
'componentWillReceiveProps',
|
||||
'UNSAFE_componentWillReceiveProps',
|
||||
'shouldComponentUpdate',
|
||||
'componentWillUpdate',
|
||||
'UNSAFE_componentWillUpdate',
|
||||
'componentDidUpdate',
|
||||
'componentWillUnmount',
|
||||
'componentDidCatch',
|
||||
'getSnapshotBeforeUpdate',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent missing displayName in a React component definition
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
|
||||
'react/display-name': ['off', { ignoreTranspilerName: false }],
|
||||
|
||||
// Forbid certain propTypes (any, array, object)
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-prop-types.md
|
||||
'react/forbid-prop-types': [
|
||||
'error',
|
||||
{
|
||||
forbid: ['any', 'array', 'object'],
|
||||
checkContextTypes: true,
|
||||
checkChildContextTypes: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Forbid certain props on DOM Nodes
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/forbid-dom-props.md
|
||||
'react/forbid-dom-props': ['off', { forbid: [] }],
|
||||
|
||||
// Enforce boolean attributes notation in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md
|
||||
'react/jsx-boolean-value': ['error', 'never', { always: [] }],
|
||||
|
||||
// Validate closing bracket location in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md
|
||||
'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
|
||||
|
||||
// Validate closing tag location in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md
|
||||
'react/jsx-closing-tag-location': 'error',
|
||||
|
||||
// Enforce or disallow spaces inside of curly braces in JSX attributes
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md
|
||||
'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
|
||||
|
||||
// Enforce event handler naming conventions in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-handler-names.md
|
||||
'react/jsx-handler-names': [
|
||||
'off',
|
||||
{
|
||||
eventHandlerPrefix: 'handle',
|
||||
eventHandlerPropPrefix: 'on',
|
||||
},
|
||||
],
|
||||
|
||||
// Validate props indentation in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
|
||||
'react/jsx-indent-props': ['error', 2],
|
||||
|
||||
// Validate JSX has key prop when in array or iterator
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-key.md
|
||||
'react/jsx-key': 'off',
|
||||
|
||||
// Limit maximum of props on a single line in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md
|
||||
'react/jsx-max-props-per-line': ['error', { maximum: 1 }],
|
||||
|
||||
// Prevent usage of .bind() in JSX props
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
|
||||
'react/jsx-no-bind': [
|
||||
'error',
|
||||
{
|
||||
ignoreRefs: true,
|
||||
allowArrowFunctions: true,
|
||||
allowFunctions: false,
|
||||
allowBind: false,
|
||||
ignoreDOMComponents: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent duplicate props in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md
|
||||
'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
|
||||
|
||||
// Prevent usage of unwrapped JSX strings
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-literals.md
|
||||
'react/jsx-no-literals': ['off', { noStrings: true }],
|
||||
|
||||
// Disallow undeclared variables in JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md
|
||||
'react/jsx-no-undef': 'error',
|
||||
|
||||
// Enforce PascalCase for user-defined JSX components
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md
|
||||
'react/jsx-pascal-case': [
|
||||
'error',
|
||||
{
|
||||
allowAllCaps: true,
|
||||
ignore: [],
|
||||
},
|
||||
],
|
||||
|
||||
// Enforce propTypes declarations alphabetical sorting
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-prop-types.md
|
||||
'react/sort-prop-types': [
|
||||
'off',
|
||||
{
|
||||
ignoreCase: true,
|
||||
callbacksLast: false,
|
||||
requiredFirst: false,
|
||||
sortShapeProp: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Deprecated in favor of react/jsx-sort-props
|
||||
'react/jsx-sort-prop-types': 'off',
|
||||
|
||||
// Enforce props alphabetical sorting
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-sort-props.md
|
||||
'react/jsx-sort-props': [
|
||||
'off',
|
||||
{
|
||||
ignoreCase: true,
|
||||
callbacksLast: false,
|
||||
shorthandFirst: false,
|
||||
shorthandLast: false,
|
||||
noSortAlphabetically: false,
|
||||
reservedFirst: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Enforce defaultProps declarations alphabetical sorting
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-sort-default-props.md
|
||||
'react/jsx-sort-default-props': [
|
||||
'off',
|
||||
{
|
||||
ignoreCase: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent React to be incorrectly marked as unused
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md
|
||||
'react/jsx-uses-react': ['error'],
|
||||
|
||||
// Prevent variables used in JSX to be incorrectly marked as unused
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md
|
||||
'react/jsx-uses-vars': 'error',
|
||||
|
||||
// Prevent usage of dangerous JSX properties
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md
|
||||
'react/no-danger': 'off',
|
||||
|
||||
// Prevent usage of deprecated methods
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md
|
||||
'react/no-deprecated': ['error'],
|
||||
|
||||
// Prevent usage of setState in componentDidMount
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md
|
||||
// this is necessary for server-rendering
|
||||
'react/no-did-mount-set-state': 'off',
|
||||
|
||||
// Prevent usage of setState in componentDidUpdate
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md
|
||||
'react/no-did-update-set-state': 'off',
|
||||
|
||||
// Prevent usage of setState in componentWillUpdate
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md
|
||||
'react/no-will-update-set-state': 'error',
|
||||
|
||||
// Prevent direct mutation of this.state
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md
|
||||
'react/no-direct-mutation-state': 'off',
|
||||
|
||||
// Prevent usage of isMounted
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
|
||||
'react/no-is-mounted': 'error',
|
||||
|
||||
// Prevent multiple component definition per file
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md
|
||||
'react/no-multi-comp': 'off',
|
||||
|
||||
// Prevent usage of setState
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-set-state.md
|
||||
'react/no-set-state': 'off',
|
||||
|
||||
// Prevent using string references
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md
|
||||
'react/no-string-refs': 'error',
|
||||
|
||||
// Prevent usage of unknown DOM property
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md
|
||||
'react/no-unknown-property': 'error',
|
||||
|
||||
// Require ES6 class declarations over React.createClass
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
|
||||
'react/prefer-es6-class': ['error', 'always'],
|
||||
|
||||
// Require stateless functions when not using lifecycle methods, setState or ref
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
|
||||
'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
|
||||
|
||||
// Prevent missing props validation in a React component definition
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
|
||||
'react/prop-types': [
|
||||
'error',
|
||||
{
|
||||
ignore: [],
|
||||
customValidators: [],
|
||||
skipUndeclared: false,
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent missing React when using JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md
|
||||
'react/react-in-jsx-scope': 'error',
|
||||
|
||||
// Require render() methods to return something
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md
|
||||
'react/require-render-return': 'error',
|
||||
|
||||
// Prevent extra closing tags for components without children
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md
|
||||
'react/self-closing-comp': 'error',
|
||||
|
||||
// Enforce component methods order
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/sort-comp.md
|
||||
'react/sort-comp': [
|
||||
'error',
|
||||
{
|
||||
order: [
|
||||
'static-variables',
|
||||
'static-methods',
|
||||
'instance-variables',
|
||||
'lifecycle',
|
||||
'/^on.+$/',
|
||||
'getters',
|
||||
'setters',
|
||||
'/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
|
||||
'instance-methods',
|
||||
'everything-else',
|
||||
'rendering',
|
||||
],
|
||||
groups: {
|
||||
lifecycle: [
|
||||
'displayName',
|
||||
'propTypes',
|
||||
'contextTypes',
|
||||
'childContextTypes',
|
||||
'mixins',
|
||||
'statics',
|
||||
'defaultProps',
|
||||
'constructor',
|
||||
'getDefaultProps',
|
||||
'getInitialState',
|
||||
'state',
|
||||
'getChildContext',
|
||||
'getDerivedStateFromProps',
|
||||
'componentWillMount',
|
||||
'UNSAFE_componentWillMount',
|
||||
'componentDidMount',
|
||||
'componentWillReceiveProps',
|
||||
'UNSAFE_componentWillReceiveProps',
|
||||
'shouldComponentUpdate',
|
||||
'componentWillUpdate',
|
||||
'UNSAFE_componentWillUpdate',
|
||||
'getSnapshotBeforeUpdate',
|
||||
'componentDidUpdate',
|
||||
'componentDidCatch',
|
||||
'componentWillUnmount',
|
||||
],
|
||||
rendering: ['/^render.+$/', 'render'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
// Prevent missing parentheses around multilines JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-wrap-multilines.md
|
||||
'react/jsx-wrap-multilines': [
|
||||
'error',
|
||||
{
|
||||
declaration: 'parens-new-line',
|
||||
assignment: 'parens-new-line',
|
||||
return: 'parens-new-line',
|
||||
arrow: 'parens-new-line',
|
||||
condition: 'parens-new-line',
|
||||
logical: 'parens-new-line',
|
||||
prop: 'parens-new-line',
|
||||
},
|
||||
],
|
||||
|
||||
// Require that the first prop in a JSX element be on a new line when the element is multiline
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md
|
||||
'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
|
||||
|
||||
// Enforce spacing around jsx equals signs
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md
|
||||
'react/jsx-equals-spacing': ['error', 'never'],
|
||||
|
||||
// Enforce JSX indentation
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md
|
||||
'react/jsx-indent': ['error', 2],
|
||||
|
||||
// Disallow target="_blank" on links
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-no-target-blank.md
|
||||
'react/jsx-no-target-blank': ['error', { enforceDynamicLinks: 'always' }],
|
||||
|
||||
// only .jsx files may have JSX
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md
|
||||
'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
|
||||
|
||||
// prevent accidental JS comments from being injected into JSX as text
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-comment-textnodes.md
|
||||
'react/jsx-no-comment-textnodes': 'error',
|
||||
|
||||
// disallow using React.render/ReactDOM.render's return value
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-render-return-value.md
|
||||
'react/no-render-return-value': 'error',
|
||||
|
||||
// require a shouldComponentUpdate method, or PureRenderMixin
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-optimization.md
|
||||
'react/require-optimization': ['off', { allowDecorators: [] }],
|
||||
|
||||
// warn against using findDOMNode()
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md
|
||||
'react/no-find-dom-node': 'error',
|
||||
|
||||
// Forbid certain props on Components
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-component-props.md
|
||||
'react/forbid-component-props': ['off', { forbid: [] }],
|
||||
|
||||
// Forbid certain elements
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-elements.md
|
||||
'react/forbid-elements': ['off', { forbid: [] }],
|
||||
|
||||
// Prevent problem with children and props.dangerouslySetInnerHTML
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger-with-children.md
|
||||
'react/no-danger-with-children': 'error',
|
||||
|
||||
// Prevent unused propType definitions
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md
|
||||
'react/no-unused-prop-types': [
|
||||
'error',
|
||||
{
|
||||
customValidators: [],
|
||||
skipShapeProps: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Require style prop value be an object or var
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md
|
||||
'react/style-prop-object': 'error',
|
||||
|
||||
// Prevent invalid characters from appearing in markup
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unescaped-entities.md
|
||||
'react/no-unescaped-entities': 'error',
|
||||
|
||||
// Prevent passing of children as props
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-children-prop.md
|
||||
'react/no-children-prop': 'error',
|
||||
|
||||
// Validate whitespace in and around the JSX opening and closing brackets
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-tag-spacing.md
|
||||
'react/jsx-tag-spacing': [
|
||||
'error',
|
||||
{
|
||||
closingSlash: 'never',
|
||||
beforeSelfClosing: 'always',
|
||||
afterOpening: 'never',
|
||||
beforeClosing: 'never',
|
||||
},
|
||||
],
|
||||
|
||||
// Enforce spaces before the closing bracket of self-closing JSX elements
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-space-before-closing.md
|
||||
// Deprecated in favor of jsx-tag-spacing
|
||||
'react/jsx-space-before-closing': ['off', 'always'],
|
||||
|
||||
// Prevent usage of Array index in keys
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md
|
||||
'react/no-array-index-key': 'off',
|
||||
|
||||
// Enforce a defaultProps definition for every prop that is not a required prop
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/require-default-props.md
|
||||
'react/require-default-props': [
|
||||
'error',
|
||||
{
|
||||
forbidDefaultForRequired: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Forbids using non-exported propTypes
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md
|
||||
// this is intentionally set to "warn". it would be "error",
|
||||
// but it's only critical if you're stripping propTypes in production.
|
||||
'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
|
||||
|
||||
// Prevent void DOM elements from receiving children
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md
|
||||
'react/void-dom-elements-no-children': 'error',
|
||||
|
||||
// Enforce all defaultProps have a corresponding non-required PropType
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/default-props-match-prop-types.md
|
||||
'react/default-props-match-prop-types': ['error', { allowRequiredDefaults: false }],
|
||||
|
||||
// Prevent usage of shouldComponentUpdate when extending React.PureComponent
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/9e13ae2c51e44872b45cc15bf1ac3a72105bdd0e/docs/rules/no-redundant-should-component-update.md
|
||||
'react/no-redundant-should-component-update': 'error',
|
||||
|
||||
// Prevent unused state values
|
||||
// https://github.com/yannickcr/eslint-plugin-react/pull/1103/
|
||||
'react/no-unused-state': 'error',
|
||||
|
||||
// Enforces consistent naming for boolean props
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/boolean-prop-naming.md
|
||||
'react/boolean-prop-naming': [
|
||||
'off',
|
||||
{
|
||||
propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
|
||||
rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+',
|
||||
message: '',
|
||||
},
|
||||
],
|
||||
|
||||
// Prevents common casing typos
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/73abadb697034b5ccb514d79fb4689836fe61f91/docs/rules/no-typos.md
|
||||
'react/no-typos': 'error',
|
||||
|
||||
// Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md
|
||||
'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],
|
||||
|
||||
// One JSX Element Per Line
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/jsx-one-expression-per-line.md
|
||||
'react/jsx-one-expression-per-line': ['error', { allow: 'single-child' }],
|
||||
|
||||
// Enforce consistent usage of destructuring assignment of props, state, and context
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/destructuring-assignment.md
|
||||
'react/destructuring-assignment': ['error', 'always'],
|
||||
|
||||
// Prevent using this.state within a this.setState
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-access-state-in-setstate.md
|
||||
'react/no-access-state-in-setstate': 'error',
|
||||
|
||||
// Prevent usage of button elements without an explicit type attribute
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/button-has-type.md
|
||||
'react/button-has-type': [
|
||||
'error',
|
||||
{
|
||||
button: true,
|
||||
submit: true,
|
||||
reset: false,
|
||||
},
|
||||
],
|
||||
|
||||
// Ensures inline tags are not rendered without spaces between them
|
||||
'react/jsx-child-element-spacing': 'off',
|
||||
|
||||
// Prevent this from being used in stateless functional components
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/no-this-in-sfc.md
|
||||
'react/no-this-in-sfc': 'error',
|
||||
|
||||
// Validate JSX maximum depth
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/abe8381c0d6748047224c430ce47f02e40160ed0/docs/rules/jsx-max-depth.md
|
||||
'react/jsx-max-depth': 'off',
|
||||
|
||||
// Disallow multiple spaces between inline JSX props
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/ac102885765be5ff37847a871f239c6703e1c7cc/docs/rules/jsx-props-no-multi-spaces.md
|
||||
'react/jsx-props-no-multi-spaces': 'error',
|
||||
|
||||
// Prevent usage of UNSAFE_ methods
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/157cc932be2cfaa56b3f5b45df6f6d4322a2f660/docs/rules/no-unsafe.md
|
||||
'react/no-unsafe': 'off',
|
||||
|
||||
// Enforce shorthand or standard form for React fragments
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/bc976b837abeab1dffd90ac6168b746a83fc83cc/docs/rules/jsx-fragments.md
|
||||
'react/jsx-fragments': ['error', 'element'],
|
||||
|
||||
// Enforce linebreaks in curly braces in JSX attributes and expressions.
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md
|
||||
'react/jsx-curly-newline': [
|
||||
'error',
|
||||
{
|
||||
multiline: 'consistent',
|
||||
singleline: 'consistent',
|
||||
},
|
||||
],
|
||||
|
||||
// Enforce state initialization style
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/state-in-constructor.md
|
||||
// TODO: set to "never" once babel-preset-airbnb supports public class fields
|
||||
'react/state-in-constructor': ['error', 'always'],
|
||||
|
||||
// Enforces where React component static properties should be positioned
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/static-property-placement.md
|
||||
// TODO: set to "static public field" once babel-preset-airbnb supports public class fields
|
||||
'react/static-property-placement': ['error', 'property assignment'],
|
||||
|
||||
// Disallow JSX props spreading
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md
|
||||
'react/jsx-props-no-spreading': 'off',
|
||||
|
||||
// Enforce that props are read-only
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-read-only-props.md
|
||||
'react/prefer-read-only-props': 'off',
|
||||
},
|
||||
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.json'],
|
||||
},
|
||||
},
|
||||
react: {
|
||||
pragma: 'React',
|
||||
version: 'detect',
|
||||
},
|
||||
propWrapperFunctions: [
|
||||
'forbidExtraProps', // https://www.npmjs.com/package/airbnb-prop-types
|
||||
'exact', // https://www.npmjs.com/package/prop-types-exact
|
||||
'Object.freeze', // https://tc39.github.io/ecma262/#sec-object.freeze
|
||||
],
|
||||
},
|
||||
'@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
|
||||
'@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'off',
|
||||
'@eslint-react/no-unsafe-component-will-mount': 'off',
|
||||
'@eslint-react/no-unsafe-component-will-receive-props': 'off',
|
||||
'@eslint-react/no-unsafe-component-will-update': 'off',
|
||||
'@eslint-react/no-set-state-in-component-did-mount': 'off',
|
||||
'@eslint-react/no-set-state-in-component-did-update': 'off',
|
||||
'@eslint-react/no-set-state-in-component-will-update': 'off',
|
||||
'@eslint-react/no-missing-component-display-name': 'off',
|
||||
'@eslint-react/no-direct-mutation-state': 'off',
|
||||
'@eslint-react/no-array-index-key': 'off',
|
||||
'@eslint-react/no-unstable-default-props': 'off', // TODO: Evaluate enabling this
|
||||
'@eslint-react/no-unstable-context-value': 'off', // TODO: Evaluate enabling this
|
||||
}
|
||||
|
||||
export default index
|
||||
|
||||
@@ -2,11 +2,11 @@ import js from '@eslint/js'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import perfectionistNatural from 'eslint-plugin-perfectionist/configs/recommended-natural'
|
||||
import { configs as regexpPluginConfigs } from 'eslint-plugin-regexp'
|
||||
import eslintConfigPrettier from 'eslint-config-prettier';
|
||||
import eslintConfigPrettier from 'eslint-config-prettier'
|
||||
import payloadPlugin from '@payloadcms/eslint-plugin'
|
||||
import reactExtends from './configs/react/index.mjs'
|
||||
import jestExtends from './configs/jest/index.mjs'
|
||||
import globals from 'globals';
|
||||
import globals from 'globals'
|
||||
import importX from 'eslint-plugin-import-x'
|
||||
import typescriptParser from '@typescript-eslint/parser'
|
||||
import { deepMerge } from './deepMerge.js'
|
||||
@@ -52,12 +52,7 @@ const baseRules = {
|
||||
'payload/no-jsx-import-statements': 'error',
|
||||
}
|
||||
|
||||
const reactRules = {
|
||||
'react/no-unused-prop-types': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'react/require-default-props': 'off',
|
||||
'react/destructuring-assignment': 'warn',
|
||||
'react/no-unescaped-entities': 'warn',
|
||||
const reactA11yRules = {
|
||||
'jsx-a11y/anchor-is-valid': 'warn',
|
||||
'jsx-a11y/control-has-associated-label': 'warn',
|
||||
'jsx-a11y/no-static-element-interactions': 'warn',
|
||||
@@ -107,9 +102,11 @@ const typescriptRules = {
|
||||
let FlatConfig
|
||||
|
||||
/** @type {FlatConfig} */
|
||||
const baseExtends = deepMerge(js.configs.recommended, perfectionistNatural , regexpPluginConfigs['flat/recommended'])
|
||||
|
||||
|
||||
const baseExtends = deepMerge(
|
||||
js.configs.recommended,
|
||||
perfectionistNatural,
|
||||
regexpPluginConfigs['flat/recommended'],
|
||||
)
|
||||
|
||||
/** @type {FlatConfig[]} */
|
||||
export const rootEslintConfig = [
|
||||
@@ -149,7 +146,7 @@ export const rootEslintConfig = [
|
||||
...baseRules,
|
||||
...typescriptRules,
|
||||
},
|
||||
}
|
||||
},
|
||||
),
|
||||
files: ['**/*.ts'],
|
||||
},
|
||||
@@ -169,33 +166,30 @@ export const rootEslintConfig = [
|
||||
rules: {
|
||||
...baseRules,
|
||||
...typescriptRules,
|
||||
...reactRules,
|
||||
...reactA11yRules,
|
||||
},
|
||||
}
|
||||
},
|
||||
),
|
||||
files: ['**/*.tsx'],
|
||||
},
|
||||
{
|
||||
name: 'Unit Tests',
|
||||
...deepMerge(
|
||||
jestExtends,
|
||||
{
|
||||
plugins: {
|
||||
payload: payloadPlugin
|
||||
},
|
||||
rules: {
|
||||
...baseRules,
|
||||
...typescriptRules,
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
},
|
||||
}
|
||||
),
|
||||
...deepMerge(jestExtends, {
|
||||
plugins: {
|
||||
payload: payloadPlugin,
|
||||
},
|
||||
rules: {
|
||||
...baseRules,
|
||||
...typescriptRules,
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
},
|
||||
}),
|
||||
files: ['**/*.spec.ts'],
|
||||
},
|
||||
{
|
||||
name: 'Payload Config',
|
||||
plugins: {
|
||||
payload: payloadPlugin
|
||||
payload: payloadPlugin,
|
||||
},
|
||||
rules: {
|
||||
...baseRules,
|
||||
|
||||
@@ -17,24 +17,23 @@
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/compat": "1.1.0",
|
||||
"@eslint-react/eslint-plugin": "1.5.25-next.4",
|
||||
"@eslint/js": "9.6.0",
|
||||
"@payloadcms/eslint-plugin": "workspace:*",
|
||||
"@types/eslint": "8.56.10",
|
||||
"@types/eslint__js": "8.42.3",
|
||||
"@typescript-eslint/parser": "7.15.0",
|
||||
"@typescript-eslint/parser": "7.16.0",
|
||||
"eslint": "9.6.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-import-x": "0.5.3",
|
||||
"eslint-plugin-import-x": "3.0.0",
|
||||
"eslint-plugin-jest": "28.6.0",
|
||||
"eslint-plugin-jest-dom": "5.4.0",
|
||||
"eslint-plugin-jsx-a11y": "6.9.0",
|
||||
"eslint-plugin-perfectionist": "2.11.0",
|
||||
"eslint-plugin-react": "7.34.3",
|
||||
"eslint-plugin-react-hooks": "5.1.0-rc-f38c22b244-20240704",
|
||||
"eslint-plugin-react-hooks": "5.1.0-rc-85acf2d195-20240711",
|
||||
"eslint-plugin-regexp": "2.6.0",
|
||||
"globals": "15.8.0",
|
||||
"typescript": "5.5.3",
|
||||
"typescript-eslint": "7.15.0"
|
||||
"typescript-eslint": "7.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import noRelativeMonorepoImports from './customRules/no-relative-monorepo-import
|
||||
import noImportsFromExportsDir from './customRules/no-imports-from-exports-dir.js'
|
||||
import noFlakyAssertions from './customRules/no-flaky-assertions.js'
|
||||
|
||||
|
||||
/**
|
||||
* @type {import('eslint').ESLint.Plugin}
|
||||
*/
|
||||
|
||||
@@ -17,23 +17,22 @@
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/compat": "1.1.0",
|
||||
"@eslint-react/eslint-plugin": "1.5.25-next.4",
|
||||
"@eslint/js": "9.6.0",
|
||||
"@types/eslint": "8.56.10",
|
||||
"@types/eslint__js": "8.42.3",
|
||||
"@typescript-eslint/parser": "7.15.0",
|
||||
"@typescript-eslint/parser": "7.16.0",
|
||||
"eslint": "9.6.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-import-x": "0.5.3",
|
||||
"eslint-plugin-import-x": "3.0.0",
|
||||
"eslint-plugin-jest": "28.6.0",
|
||||
"eslint-plugin-jest-dom": "5.4.0",
|
||||
"eslint-plugin-jsx-a11y": "6.9.0",
|
||||
"eslint-plugin-perfectionist": "2.11.0",
|
||||
"eslint-plugin-react": "7.34.3",
|
||||
"eslint-plugin-react-hooks": "5.1.0-rc-f38c22b244-20240704",
|
||||
"eslint-plugin-react-hooks": "5.1.0-rc-85acf2d195-20240711",
|
||||
"eslint-plugin-regexp": "2.6.0",
|
||||
"globals": "15.8.0",
|
||||
"typescript": "5.5.3",
|
||||
"typescript-eslint": "7.15.0"
|
||||
"typescript-eslint": "7.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import type { SanitizedConfig } from 'payload'
|
||||
|
||||
import fs from 'fs'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { OperationArgs } from 'graphql-http'
|
||||
import type { GraphQLInfo, SanitizedConfig } from 'payload'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
|
||||
/**
|
||||
* Created by Ivo Meißner on 28.07.17.
|
||||
|
||||
@@ -16,7 +16,6 @@ function ensureObject(value) {
|
||||
function parseObject(typeName, ast, variables) {
|
||||
const value = Object.create(null)
|
||||
ast.fields.forEach((field) => {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
value[field.name.value] = parseLiteral(typeName, field.value, variables)
|
||||
})
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ export type Resolver = (
|
||||
context: {
|
||||
req: PayloadRequest
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
) => Promise<{ totalDocs: number }>
|
||||
|
||||
export function countResolver(collection: Collection): Resolver {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
import type { GraphQLFieldConfig, GraphQLType } from 'graphql'
|
||||
import type {
|
||||
ArrayField,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import type { Field, FieldAffectingData } from 'payload'
|
||||
|
||||
import { GraphQLInputObjectType, GraphQLList } from 'graphql'
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { GraphQLInfo } from 'payload'
|
||||
import type { Collection, Field, SanitizedCollectionConfig, SanitizedConfig } from 'payload'
|
||||
import type {
|
||||
Collection,
|
||||
Field,
|
||||
GraphQLInfo,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedConfig,
|
||||
} from 'payload'
|
||||
|
||||
import {
|
||||
GraphQLBoolean,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { GraphQLBoolean, GraphQLInt, GraphQLNonNull, GraphQLString } from 'graphql'
|
||||
import pluralize from 'pluralize'
|
||||
const { singular } = pluralize
|
||||
|
||||
@@ -45,19 +45,19 @@ const GeoJSONObject = new GraphQLInputObjectType({
|
||||
})
|
||||
|
||||
type DefaultsType = {
|
||||
[key in staticTypes]: {
|
||||
operators: {
|
||||
name: string
|
||||
type: ((field: FieldAffectingData, parentName: string) => GraphQLType) | GraphQLType
|
||||
}[]
|
||||
}
|
||||
} & {
|
||||
[key in dynamicTypes]: {
|
||||
operators: {
|
||||
name: string
|
||||
type: (field: FieldAffectingData, parentName: string) => GraphQLType
|
||||
}[]
|
||||
}
|
||||
} & {
|
||||
[key in staticTypes]: {
|
||||
operators: {
|
||||
name: string
|
||||
type: ((field: FieldAffectingData, parentName: string) => GraphQLType) | GraphQLType
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
const defaults: DefaultsType = {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import formatName from './formatName'
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ export const mergeData = async <T>(args: {
|
||||
returnNumberOfRequests?: boolean
|
||||
serverURL: string
|
||||
}): Promise<
|
||||
T & {
|
||||
{
|
||||
_numberOfRequests?: number
|
||||
}
|
||||
} & T
|
||||
> => {
|
||||
const {
|
||||
apiRoute,
|
||||
|
||||
@@ -7,7 +7,7 @@ import './index.scss'
|
||||
|
||||
export const baseClass = 'doc-tab'
|
||||
|
||||
export const DocumentTab: React.FC<DocumentTabProps & DocumentTabConfig> = (props) => {
|
||||
export const DocumentTab: React.FC<DocumentTabConfig & DocumentTabProps> = (props) => {
|
||||
const {
|
||||
Pill,
|
||||
apiURL,
|
||||
|
||||
@@ -16,9 +16,9 @@ export type DocumentViewKey = (typeof documentViewKeys)[number]
|
||||
|
||||
export const tabs: Record<
|
||||
DocumentViewKey,
|
||||
DocumentTabConfig & {
|
||||
{
|
||||
order?: number // TODO: expose this to the globalConfig config
|
||||
}
|
||||
} & DocumentTabConfig
|
||||
> = {
|
||||
API: {
|
||||
condition: ({ collectionConfig, globalConfig }) =>
|
||||
|
||||
@@ -109,7 +109,6 @@ export const RootLayout = async ({
|
||||
fallbackLang={clientConfig.i18n.fallbackLanguage}
|
||||
languageCode={languageCode}
|
||||
languageOptions={languageOptions}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
switchLanguageServerAction={switchLanguageServerAction}
|
||||
theme={theme}
|
||||
translations={i18n.translations}
|
||||
|
||||
@@ -50,7 +50,6 @@ const handleError = async (
|
||||
let cached = global._payload_graphql
|
||||
|
||||
if (!cached) {
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
cached = global._payload_graphql = { graphql: null, promise: null }
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'template-default'
|
||||
|
||||
export type DefaultTemplateProps = ServerProps & {
|
||||
export type DefaultTemplateProps = {
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
visibleEntities: VisibleEntities
|
||||
}
|
||||
} & ServerProps
|
||||
|
||||
export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
|
||||
children,
|
||||
|
||||
@@ -10,7 +10,6 @@ let cached: {
|
||||
} = global._payload
|
||||
|
||||
if (!cached) {
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
cached = global._payload = { payload: null, promise: null, reload: false }
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const defaultOpenGraph = {
|
||||
title: 'Payload App',
|
||||
}
|
||||
|
||||
export const meta = async (args: MetaConfig & { serverURL: string }): Promise<any> => {
|
||||
export const meta = async (args: { serverURL: string } & MetaConfig): Promise<any> => {
|
||||
const {
|
||||
defaultOGImageType,
|
||||
description,
|
||||
|
||||
@@ -10,12 +10,12 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'dashboard'
|
||||
|
||||
export type DashboardProps = ServerProps & {
|
||||
export type DashboardProps = {
|
||||
Link: React.ComponentType<any>
|
||||
navGroups?: ReturnType<typeof groupNavItems>
|
||||
permissions: Permissions
|
||||
visibleEntities: VisibleEntities
|
||||
}
|
||||
} & ServerProps
|
||||
|
||||
export const DefaultDashboard: React.FC<DashboardProps> = (props) => {
|
||||
const {
|
||||
|
||||
@@ -12,10 +12,10 @@ import { generateMetadata as versionMeta } from '../Version/meta.js'
|
||||
import { generateMetadata as versionsMeta } from '../Versions/meta.js'
|
||||
|
||||
export type GenerateEditViewMetadata = (
|
||||
args: Parameters<GenerateViewMetadata>[0] & {
|
||||
args: {
|
||||
collectionConfig?: SanitizedCollectionConfig | null
|
||||
globalConfig?: SanitizedGlobalConfig | null
|
||||
},
|
||||
} & Parameters<GenerateViewMetadata>[0],
|
||||
) => Promise<Metadata>
|
||||
|
||||
export const getMetaBySegment: GenerateEditViewMetadata = async ({
|
||||
|
||||
@@ -28,7 +28,7 @@ export const getViewsFromConfig = ({
|
||||
}: {
|
||||
collectionConfig?: SanitizedCollectionConfig
|
||||
config: SanitizedConfig
|
||||
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
||||
|
||||
docPermissions: CollectionPermission | GlobalPermission
|
||||
globalConfig?: SanitizedGlobalConfig
|
||||
routeSegments: string[]
|
||||
|
||||
@@ -8,9 +8,9 @@ import type { GenerateViewMetadata } from '../Root/index.js'
|
||||
import { meta } from '../../utilities/meta.js'
|
||||
|
||||
export const generateListMetadata = async (
|
||||
args: Parameters<GenerateViewMetadata>[0] & {
|
||||
args: {
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
},
|
||||
} & Parameters<GenerateViewMetadata>[0],
|
||||
): Promise<Metadata> => {
|
||||
const { collectionConfig, config, i18n } = args
|
||||
|
||||
|
||||
@@ -56,9 +56,9 @@ const StaticToolbar: React.FC<EditViewProps> = (props) => {
|
||||
}
|
||||
|
||||
export const LivePreviewToolbar: React.FC<
|
||||
EditViewProps & {
|
||||
{
|
||||
draggable?: boolean
|
||||
}
|
||||
} & EditViewProps
|
||||
> = (props) => {
|
||||
const { draggable } = props
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface PopupMessage {
|
||||
|
||||
export const usePopupWindow = (props: {
|
||||
eventType?: string
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
onMessage?: (searchParams: PopupMessage['searchParams']) => Promise<void>
|
||||
url: string
|
||||
}): {
|
||||
|
||||
@@ -10,9 +10,9 @@ const baseClass = 'logout'
|
||||
export { generateLogoutMetadata } from './meta.js'
|
||||
|
||||
export const LogoutView: React.FC<
|
||||
AdminViewProps & {
|
||||
{
|
||||
inactivity?: boolean
|
||||
}
|
||||
} & AdminViewProps
|
||||
> = ({ inactivity, initPageResult, searchParams }) => {
|
||||
const {
|
||||
req: {
|
||||
|
||||
@@ -15,7 +15,6 @@ export const generatePageMetadata = async ({
|
||||
}: {
|
||||
config: Promise<SanitizedConfig> | SanitizedConfig
|
||||
params?: { [key: string]: string | string[] }
|
||||
//eslint-disable-next-line @typescript-eslint/require-await
|
||||
}): Promise<Metadata> => {
|
||||
const config = await configPromise
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ const getTranslatedOptions = (
|
||||
}
|
||||
|
||||
const Select: React.FC<
|
||||
Omit<Props, 'field'> & {
|
||||
{
|
||||
field: MappedField & SelectFieldProps
|
||||
}
|
||||
} & Omit<Props, 'field'>
|
||||
> = ({ comparison, diffMethod, field, i18n, locale, version }) => {
|
||||
let placeholder = ''
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import Nested from '../Nested/index.js'
|
||||
const baseClass = 'tabs-diff'
|
||||
|
||||
const Tabs: React.FC<
|
||||
Omit<Props, 'field'> & {
|
||||
{
|
||||
field: MappedField & TabsFieldProps
|
||||
}
|
||||
} & Omit<Props, 'field'>
|
||||
> = ({ comparison, diffComponents, field, i18n, locale, locales, permissions, version }) => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
|
||||
@@ -15,8 +15,8 @@ export type Props = {
|
||||
version: Record<string, any>
|
||||
}
|
||||
|
||||
export type FieldDiffProps = Props & {
|
||||
export type FieldDiffProps = {
|
||||
diffMethod: DiffMethod
|
||||
field: MappedField
|
||||
isRichText: boolean
|
||||
}
|
||||
} & Props
|
||||
|
||||
@@ -9,13 +9,9 @@ import type { SanitizedGlobalConfig } from '../globals/config/types.js'
|
||||
import type { PayloadRequest, RequestContext } from '../types/index.js'
|
||||
import type { WithServerSidePropsComponentProps } from './elements/WithServerSideProps.js'
|
||||
|
||||
export type RichTextFieldProps<
|
||||
Value extends object,
|
||||
AdapterProps,
|
||||
ExtraFieldProperties = {},
|
||||
> = Omit<RichTextField<Value, AdapterProps, ExtraFieldProperties>, 'type'> & {
|
||||
export type RichTextFieldProps<Value extends object, AdapterProps, ExtraFieldProperties = {}> = {
|
||||
path?: string
|
||||
}
|
||||
} & Omit<RichTextField<Value, AdapterProps, ExtraFieldProperties>, 'type'>
|
||||
|
||||
export type AfterReadRichTextHookArgs<
|
||||
TData extends TypeWithID = any,
|
||||
@@ -146,8 +142,8 @@ export type AfterReadRichTextHook<
|
||||
TValue = any,
|
||||
TSiblingData = any,
|
||||
> = (
|
||||
args: BaseRichTextHookArgs<TData, TValue, TSiblingData> &
|
||||
AfterReadRichTextHookArgs<TData, TValue, TSiblingData>,
|
||||
args: AfterReadRichTextHookArgs<TData, TValue, TSiblingData> &
|
||||
BaseRichTextHookArgs<TData, TValue, TSiblingData>,
|
||||
) => Promise<TValue> | TValue
|
||||
|
||||
export type AfterChangeRichTextHook<
|
||||
@@ -155,8 +151,8 @@ export type AfterChangeRichTextHook<
|
||||
TValue = any,
|
||||
TSiblingData = any,
|
||||
> = (
|
||||
args: BaseRichTextHookArgs<TData, TValue, TSiblingData> &
|
||||
AfterChangeRichTextHookArgs<TData, TValue, TSiblingData>,
|
||||
args: AfterChangeRichTextHookArgs<TData, TValue, TSiblingData> &
|
||||
BaseRichTextHookArgs<TData, TValue, TSiblingData>,
|
||||
) => Promise<TValue> | TValue
|
||||
|
||||
export type BeforeChangeRichTextHook<
|
||||
@@ -252,10 +248,10 @@ export type RichTextAdapter<
|
||||
Value extends object = object,
|
||||
AdapterProps = any,
|
||||
ExtraFieldProperties = {},
|
||||
> = RichTextAdapterBase<Value, AdapterProps, ExtraFieldProperties> & {
|
||||
> = {
|
||||
CellComponent: React.FC<any>
|
||||
FieldComponent: React.FC<RichTextFieldProps<Value, AdapterProps, ExtraFieldProperties>>
|
||||
}
|
||||
} & RichTextAdapterBase<Value, AdapterProps, ExtraFieldProperties>
|
||||
|
||||
export type RichTextAdapterProvider<
|
||||
Value extends object = object,
|
||||
|
||||
@@ -35,11 +35,11 @@ export type CellComponentProps = {
|
||||
schemaPath: string
|
||||
}
|
||||
|
||||
export type DefaultCellComponentProps<T = any> = CellComponentProps & {
|
||||
export type DefaultCellComponentProps<T = any> = {
|
||||
cellData: T
|
||||
customCellContext?: {
|
||||
collectionSlug?: SanitizedCollectionConfig['slug']
|
||||
uploadConfig?: SanitizedCollectionConfig['upload']
|
||||
}
|
||||
rowData: RowData
|
||||
}
|
||||
} & CellComponentProps
|
||||
|
||||
@@ -25,23 +25,23 @@ export type MonthPickerProps = {
|
||||
}
|
||||
|
||||
export type ConditionalDateProps =
|
||||
| (SharedProps &
|
||||
DayPickerProps &
|
||||
TimePickerProps & {
|
||||
pickerAppearance?: 'dayAndTime'
|
||||
})
|
||||
| (SharedProps &
|
||||
DayPickerProps & {
|
||||
pickerAppearance: 'dayOnly'
|
||||
})
|
||||
| (SharedProps &
|
||||
MonthPickerProps & {
|
||||
pickerAppearance: 'monthOnly'
|
||||
})
|
||||
| (SharedProps &
|
||||
TimePickerProps & {
|
||||
pickerAppearance: 'timeOnly'
|
||||
})
|
||||
| (SharedProps & {
|
||||
| ({
|
||||
pickerAppearance: 'dayOnly'
|
||||
} & DayPickerProps &
|
||||
SharedProps)
|
||||
| ({
|
||||
pickerAppearance: 'monthOnly'
|
||||
} & MonthPickerProps &
|
||||
SharedProps)
|
||||
| ({
|
||||
pickerAppearance: 'timeOnly'
|
||||
} & SharedProps &
|
||||
TimePickerProps)
|
||||
| ({
|
||||
pickerAppearance?: 'dayAndTime'
|
||||
} & DayPickerProps &
|
||||
SharedProps &
|
||||
TimePickerProps)
|
||||
| ({
|
||||
pickerAppearance?: 'default'
|
||||
})
|
||||
} & SharedProps)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { CollectionConfig } from '../collections/config/types.js'
|
||||
import type { Field, TabAsField } from '../fields/config/types.js'
|
||||
import type { PayloadRequest } from '../types/index.js'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './types.js'
|
||||
export * from './cookies.js'
|
||||
|
||||
export { extractJWT } from './extractJWT.js'
|
||||
export * from './cookies.js'
|
||||
export * from './types.js'
|
||||
|
||||
@@ -27,7 +27,7 @@ export type Options<TSlug extends CollectionSlug> = {
|
||||
async function localLogin<TSlug extends CollectionSlug>(
|
||||
payload: Payload,
|
||||
options: Options<TSlug>,
|
||||
): Promise<Result & { user: DataFromCollectionSlug<TSlug> }> {
|
||||
): Promise<{ user: DataFromCollectionSlug<TSlug> } & Result> {
|
||||
const {
|
||||
collection: collectionSlug,
|
||||
data,
|
||||
|
||||
@@ -39,7 +39,7 @@ export type Arguments<TSlug extends CollectionSlug> = {
|
||||
|
||||
export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
incomingArgs: Arguments<TSlug>,
|
||||
): Promise<Result & { user: DataFromCollectionSlug<TSlug> }> => {
|
||||
): Promise<{ user: DataFromCollectionSlug<TSlug> } & Result> => {
|
||||
let args = incomingArgs
|
||||
|
||||
try {
|
||||
@@ -253,7 +253,7 @@ export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
})) || user
|
||||
}, Promise.resolve())
|
||||
|
||||
let result: Result & { user: DataFromCollectionSlug<TSlug> } = {
|
||||
let result: { user: DataFromCollectionSlug<TSlug> } & Result = {
|
||||
exp: (jwt.decode(token) as jwt.JwtPayload).exp,
|
||||
token,
|
||||
user,
|
||||
|
||||
@@ -14,8 +14,8 @@ import { killTransaction } from '../../utilities/killTransaction.js'
|
||||
|
||||
export type Arguments<TSlug extends CollectionSlug> = {
|
||||
collection: Collection
|
||||
data: RequiredDataFromCollectionSlug<TSlug> &
|
||||
AuthOperationsFromCollectionSlug<TSlug>['registerFirstUser']
|
||||
data: AuthOperationsFromCollectionSlug<TSlug>['registerFirstUser'] &
|
||||
RequiredDataFromCollectionSlug<TSlug>
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export const JWTAuthentication: AuthStrategyFunction = async ({
|
||||
}) => {
|
||||
try {
|
||||
const token = extractJWT({ headers, payload })
|
||||
const decodedPayload = jwt.verify(token, payload.secret) as jwt.JwtPayload & JWTToken
|
||||
const decodedPayload = jwt.verify(token, payload.secret) as JWTToken & jwt.JwtPayload
|
||||
|
||||
const collection = payload.collections[decodedPayload.collection]
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import scmp from 'scmp'
|
||||
|
||||
import type { TypeWithID } from '../../../collections/config/types.js'
|
||||
|
||||
type Doc = TypeWithID & Record<string, unknown>
|
||||
type Doc = Record<string, unknown> & TypeWithID
|
||||
|
||||
type Args = {
|
||||
doc: Doc
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { PayloadRequest } from '../../../types/index.js'
|
||||
|
||||
type Args = {
|
||||
collection: SanitizedCollectionConfig
|
||||
doc: TypeWithID & Record<string, unknown>
|
||||
doc: Record<string, unknown> & TypeWithID
|
||||
payload: Payload
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { PayloadRequest } from '../../../types/index.js'
|
||||
|
||||
type Args = {
|
||||
collection: SanitizedCollectionConfig
|
||||
doc: TypeWithID & Record<string, unknown>
|
||||
doc: Record<string, unknown> & TypeWithID
|
||||
payload: Payload
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const injectInlineSourceMap = ({
|
||||
export async function compile(
|
||||
sourcecode: string,
|
||||
filename: string,
|
||||
options: ts.CompilerOptions & { fallbackToTs?: (filename: string) => boolean },
|
||||
options: { fallbackToTs?: (filename: string) => boolean } & ts.CompilerOptions,
|
||||
): Promise<string> {
|
||||
if (filename.endsWith('.d.ts')) {
|
||||
return ''
|
||||
|
||||
@@ -10,18 +10,15 @@ export type ServerOnlyCollectionAdminProperties = keyof Pick<
|
||||
'components' | 'hidden' | 'preview'
|
||||
>
|
||||
|
||||
export type ClientCollectionConfig = Omit<
|
||||
SanitizedCollectionConfig,
|
||||
'admin' | 'fields' | ServerOnlyCollectionProperties
|
||||
> & {
|
||||
admin: Omit<
|
||||
export type ClientCollectionConfig = {
|
||||
admin: {
|
||||
livePreview?: Omit<LivePreviewConfig, ServerOnlyLivePreviewProperties>
|
||||
} & Omit<
|
||||
SanitizedCollectionConfig['admin'],
|
||||
'fields' | 'livePreview' | ServerOnlyCollectionAdminProperties
|
||||
> & {
|
||||
livePreview?: Omit<LivePreviewConfig, ServerOnlyLivePreviewProperties>
|
||||
}
|
||||
>
|
||||
fields: ClientFieldConfig[]
|
||||
}
|
||||
} & Omit<SanitizedCollectionConfig, 'admin' | 'fields' | ServerOnlyCollectionProperties>
|
||||
|
||||
import type { TFunction } from '@payloadcms/translations'
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ export const deleteOperation = async <TSlug extends CollectionSlug>(
|
||||
|
||||
const errors = []
|
||||
|
||||
/* eslint-disable no-param-reassign */
|
||||
const promises = docs.map(async (doc) => {
|
||||
let result
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import type { FindOneArgs } from '../../database/types.js'
|
||||
import type { CollectionSlug } from '../../index.js'
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
|
||||
@@ -22,15 +22,15 @@ export type BaseOptions<TSlug extends CollectionSlug> = {
|
||||
user?: Document
|
||||
}
|
||||
|
||||
export type ByIDOptions<TSlug extends CollectionSlug> = BaseOptions<TSlug> & {
|
||||
export type ByIDOptions<TSlug extends CollectionSlug> = {
|
||||
id: number | string
|
||||
where?: never
|
||||
}
|
||||
} & BaseOptions<TSlug>
|
||||
|
||||
export type ManyOptions<TSlug extends CollectionSlug> = BaseOptions<TSlug> & {
|
||||
export type ManyOptions<TSlug extends CollectionSlug> = {
|
||||
id?: never
|
||||
where: Where
|
||||
}
|
||||
} & BaseOptions<TSlug>
|
||||
|
||||
export type Options<TSlug extends CollectionSlug> = ByIDOptions<TSlug> | ManyOptions<TSlug>
|
||||
|
||||
|
||||
@@ -36,15 +36,15 @@ export type BaseOptions<TSlug extends CollectionSlug> = {
|
||||
user?: Document
|
||||
}
|
||||
|
||||
export type ByIDOptions<TSlug extends CollectionSlug> = BaseOptions<TSlug> & {
|
||||
export type ByIDOptions<TSlug extends CollectionSlug> = {
|
||||
id: number | string
|
||||
where?: never
|
||||
}
|
||||
} & BaseOptions<TSlug>
|
||||
|
||||
export type ManyOptions<TSlug extends CollectionSlug> = BaseOptions<TSlug> & {
|
||||
export type ManyOptions<TSlug extends CollectionSlug> = {
|
||||
id?: never
|
||||
where: Where
|
||||
}
|
||||
} & BaseOptions<TSlug>
|
||||
|
||||
export type Options<TSlug extends CollectionSlug> = ByIDOptions<TSlug> | ManyOptions<TSlug>
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
import type { FindOneArgs } from '../../database/types.js'
|
||||
|
||||
@@ -98,7 +98,7 @@ export const buildAfterOperation = async <
|
||||
TOperationGeneric extends CollectionSlug,
|
||||
O extends keyof AfterOperationMap<TOperationGeneric> = keyof AfterOperationMap<TOperationGeneric>,
|
||||
>(
|
||||
operationArgs: Omit<AfterOperationArg<TOperationGeneric>, 'req'> & { operation: O },
|
||||
operationArgs: { operation: O } & Omit<AfterOperationArg<TOperationGeneric>, 'req'>,
|
||||
): Promise<OperationResult<TOperationGeneric, O> | any> => {
|
||||
const { args, collection, operation, result } = operationArgs
|
||||
|
||||
|
||||
@@ -34,17 +34,14 @@ export type ServerOnlyRootProperties = keyof Pick<
|
||||
|
||||
export type ServerOnlyRootAdminProperties = keyof Pick<SanitizedConfig['admin'], 'components'>
|
||||
|
||||
export type ClientConfig = Omit<
|
||||
SanitizedConfig,
|
||||
'admin' | 'collections' | 'globals' | ServerOnlyRootProperties
|
||||
> & {
|
||||
admin: Omit<SanitizedConfig['admin'], ServerOnlyRootAdminProperties & 'livePreview'> & {
|
||||
export type ClientConfig = {
|
||||
admin: {
|
||||
livePreview?: Omit<LivePreviewConfig, ServerOnlyLivePreviewProperties>
|
||||
}
|
||||
} & Omit<SanitizedConfig['admin'], 'livePreview' & ServerOnlyRootAdminProperties>
|
||||
collections: ClientCollectionConfig[]
|
||||
custom?: Record<string, any>
|
||||
globals: ClientGlobalConfig[]
|
||||
}
|
||||
} & Omit<SanitizedConfig, 'admin' | 'collections' | 'globals' | ServerOnlyRootProperties>
|
||||
|
||||
export const createClientConfig = async ({
|
||||
config,
|
||||
|
||||
@@ -73,7 +73,6 @@ export const findConfig = (): string => {
|
||||
? [configPath, outPath, srcPath, rootPath]
|
||||
: [configPath, srcPath, rootPath]
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const searchPath of searchPaths) {
|
||||
if (!searchPath) continue
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ type Prettify<T> = {
|
||||
[K in keyof T]: T[K]
|
||||
} & NonNullable<unknown>
|
||||
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
export type Plugin = (config: Config) => Config | Promise<Config>
|
||||
|
||||
export type LivePreviewConfig = {
|
||||
@@ -347,7 +346,7 @@ export const serverProps: (keyof ServerProps)[] = [
|
||||
]
|
||||
|
||||
export type CustomComponent<TAdditionalProps extends any = any> = React.ComponentType<
|
||||
TAdditionalProps & Partial<ServerProps>
|
||||
Partial<ServerProps> & TAdditionalProps
|
||||
>
|
||||
|
||||
export type Locale = {
|
||||
@@ -382,17 +381,17 @@ export type BaseLocalizationConfig = {
|
||||
}
|
||||
|
||||
export type LocalizationConfigWithNoLabels = Prettify<
|
||||
BaseLocalizationConfig & {
|
||||
{
|
||||
/**
|
||||
* List of supported locales
|
||||
* @example `["en", "es", "fr", "nl", "de", "jp"]`
|
||||
*/
|
||||
locales: string[]
|
||||
}
|
||||
} & BaseLocalizationConfig
|
||||
>
|
||||
|
||||
export type LocalizationConfigWithLabels = Prettify<
|
||||
BaseLocalizationConfig & {
|
||||
{
|
||||
/**
|
||||
* List of supported locales with labels
|
||||
* @example {
|
||||
@@ -402,17 +401,17 @@ export type LocalizationConfigWithLabels = Prettify<
|
||||
* }
|
||||
*/
|
||||
locales: Locale[]
|
||||
}
|
||||
} & BaseLocalizationConfig
|
||||
>
|
||||
|
||||
export type SanitizedLocalizationConfig = Prettify<
|
||||
LocalizationConfigWithLabels & {
|
||||
{
|
||||
/**
|
||||
* List of supported locales
|
||||
* @example `["en", "es", "fr", "nl", "de", "jp"]`
|
||||
*/
|
||||
localeCodes: string[]
|
||||
}
|
||||
} & LocalizationConfigWithLabels
|
||||
>
|
||||
|
||||
/**
|
||||
@@ -547,10 +546,10 @@ export type Config = {
|
||||
dateFormat?: string
|
||||
/** If set to true, the entire Admin panel will be disabled. */
|
||||
disable?: boolean
|
||||
livePreview?: LivePreviewConfig & {
|
||||
livePreview?: {
|
||||
collections?: string[]
|
||||
globals?: string[]
|
||||
}
|
||||
} & LivePreviewConfig
|
||||
/** Base meta data to use for the Admin Panel. Included properties are titleSuffix, ogImage, and favicon. */
|
||||
meta?: MetaConfig
|
||||
routes?: {
|
||||
@@ -758,10 +757,7 @@ export type Config = {
|
||||
upload?: ExpressFileUploadOptions
|
||||
}
|
||||
|
||||
export type SanitizedConfig = Omit<
|
||||
DeepRequired<Config>,
|
||||
'collections' | 'editor' | 'endpoint' | 'globals' | 'i18n' | 'localization' | 'upload'
|
||||
> & {
|
||||
export type SanitizedConfig = {
|
||||
collections: SanitizedCollectionConfig[]
|
||||
/** Default richtext editor to use for richText fields */
|
||||
editor?: RichTextAdapter<any, any, any>
|
||||
@@ -774,13 +770,16 @@ export type SanitizedConfig = Omit<
|
||||
configDir: string
|
||||
rawConfig: string
|
||||
}
|
||||
upload: ExpressFileUploadOptions & {
|
||||
upload: {
|
||||
/**
|
||||
* Deduped list of adapters used in the project
|
||||
*/
|
||||
adapters: string[]
|
||||
}
|
||||
}
|
||||
} & ExpressFileUploadOptions
|
||||
} & Omit<
|
||||
DeepRequired<Config>,
|
||||
'collections' | 'editor' | 'endpoint' | 'globals' | 'i18n' | 'localization' | 'upload'
|
||||
>
|
||||
|
||||
export type EditConfig =
|
||||
| (
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type {
|
||||
|
||||
@@ -129,7 +129,6 @@ export async function getLocalizedPaths({
|
||||
if (nestedPathToQuery) {
|
||||
const relatedCollection = payload.collections[matchedField.relationTo].config
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const remainingPaths = await getLocalizedPaths({
|
||||
collectionSlug: relatedCollection.slug,
|
||||
fields: relatedCollection.fields,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import fs from 'fs'
|
||||
|
||||
import type { CreateMigration } from '../types.js'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
import type { BaseDatabaseAdapter } from '../types.js'
|
||||
|
||||
@@ -23,7 +22,7 @@ export async function migrate(this: BaseDatabaseAdapter): Promise<void> {
|
||||
|
||||
// Run migration if not found in database
|
||||
if (existingMigration) {
|
||||
continue // eslint-disable-line no-continue
|
||||
continue
|
||||
}
|
||||
|
||||
const start = Date.now()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
import type { BaseDatabaseAdapter } from '../types.js'
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
import type { BaseDatabaseAdapter } from '../types.js'
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
import type { BaseDatabaseAdapter } from '../types.js'
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function migrateStatus(this: BaseDatabaseAdapter): Promise<void> {
|
||||
const existingMigration = existingMigrations.find((m) => m.name === migration.name)
|
||||
return {
|
||||
Name: migration.name,
|
||||
// eslint-disable-next-line perfectionist/sort-objects
|
||||
|
||||
Batch: existingMigration?.batch,
|
||||
Ran: existingMigration ? 'Yes' : 'No',
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
import type { SanitizedCollectionConfig } from '../../collections/config/types.js'
|
||||
import type { Field, FieldAffectingData } from '../../fields/config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../globals/config/types.js'
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import type { Operator, PayloadRequest, Where, WhereField } from '../../types/index.js'
|
||||
import type { EntityPolicies } from './types.js'
|
||||
|
||||
|
||||
@@ -51,10 +51,8 @@ export async function validateSearchParam({
|
||||
const { slug } = collectionConfig || globalConfig
|
||||
|
||||
if (globalConfig && !policies.globals[slug]) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
globalConfig.fields = fields
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
policies.globals[slug] = await getEntityPolicies({
|
||||
type: 'global',
|
||||
entity: globalConfig,
|
||||
@@ -85,7 +83,6 @@ export async function validateSearchParam({
|
||||
if (!overrideAccess && fieldAffectsData(field)) {
|
||||
if (collectionSlug) {
|
||||
if (!policies.collections[collectionSlug]) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
policies.collections[collectionSlug] = await getEntityPolicies({
|
||||
type: 'collection',
|
||||
entity: req.payload.collections[collectionSlug].config,
|
||||
|
||||
@@ -222,17 +222,17 @@ type BaseVersionArgs = {
|
||||
where?: Where
|
||||
}
|
||||
|
||||
export type FindVersionsArgs = BaseVersionArgs & {
|
||||
export type FindVersionsArgs = {
|
||||
collection: string
|
||||
}
|
||||
} & BaseVersionArgs
|
||||
|
||||
export type FindVersions = <T = TypeWithID>(
|
||||
args: FindVersionsArgs,
|
||||
) => Promise<PaginatedDocs<TypeWithVersion<T>>>
|
||||
|
||||
export type FindGlobalVersionsArgs = BaseVersionArgs & {
|
||||
export type FindGlobalVersionsArgs = {
|
||||
global: string
|
||||
}
|
||||
} & BaseVersionArgs
|
||||
|
||||
export type FindGlobalArgs = {
|
||||
locale?: string
|
||||
@@ -395,10 +395,10 @@ export type DeleteManyArgs = {
|
||||
|
||||
export type DeleteMany = (args: DeleteManyArgs) => Promise<void>
|
||||
|
||||
export type Migration = MigrationData & {
|
||||
export type Migration = {
|
||||
down: ({ payload, req }: { payload: Payload; req: PayloadRequest }) => Promise<boolean>
|
||||
up: ({ payload, req }: { payload: Payload; req: PayloadRequest }) => Promise<boolean>
|
||||
}
|
||||
} & MigrationData
|
||||
|
||||
export type MigrationData = {
|
||||
batch?: number
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
class ExtendableError<TData extends object = { [key: string]: unknown }> extends Error {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
export * from '../fields/validations.js'
|
||||
export { defaults as collectionDefaults } from '../collections/config/defaults.js'
|
||||
export { serverProps } from '../config/types.js'
|
||||
|
||||
export {
|
||||
fieldAffectsData,
|
||||
fieldHasMaxDepth,
|
||||
@@ -19,6 +17,8 @@ export {
|
||||
valueIsValueWithRelation,
|
||||
} from '../fields/config/types.js'
|
||||
|
||||
export * from '../fields/validations.js'
|
||||
|
||||
export { validOperators } from '../types/constants.js'
|
||||
export { formatFilesize } from '../uploads/formatFilesize.js'
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Config } from '../../config/types.js'
|
||||
import { InvalidFieldName, InvalidFieldRelationship, MissingFieldType } from '../../errors/index.js'
|
||||
import { sanitizeFields } from './sanitize.js'
|
||||
import type { Config } from '../../config/types.js'
|
||||
import type {
|
||||
ArrayField,
|
||||
Block,
|
||||
@@ -11,14 +9,17 @@ import type {
|
||||
TextField,
|
||||
} from './types.js'
|
||||
|
||||
import { InvalidFieldName, InvalidFieldRelationship, MissingFieldType } from '../../errors/index.js'
|
||||
import { sanitizeFields } from './sanitize.js'
|
||||
|
||||
describe('sanitizeFields', () => {
|
||||
const config = {} as Config
|
||||
it('should throw on missing type field', async () => {
|
||||
const fields: Field[] = [
|
||||
// @ts-expect-error
|
||||
{
|
||||
label: 'some-collection',
|
||||
name: 'Some Collection',
|
||||
label: 'some-collection',
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -32,9 +33,9 @@ describe('sanitizeFields', () => {
|
||||
it('should throw on invalid field name', async () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: 'some.collection',
|
||||
name: 'some.collection',
|
||||
type: 'text',
|
||||
label: 'some.collection',
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -68,9 +69,9 @@ describe('sanitizeFields', () => {
|
||||
it('should allow auto-label override', async () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: 'Do not label',
|
||||
name: 'someField',
|
||||
type: 'text',
|
||||
label: 'Do not label',
|
||||
},
|
||||
]
|
||||
const sanitizedField = (
|
||||
@@ -89,9 +90,9 @@ describe('sanitizeFields', () => {
|
||||
it('should allow label opt-out', async () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: false,
|
||||
name: 'someField',
|
||||
type: 'text',
|
||||
label: false,
|
||||
},
|
||||
]
|
||||
const sanitizedField = (
|
||||
@@ -108,6 +109,8 @@ describe('sanitizeFields', () => {
|
||||
|
||||
it('should allow label opt-out for arrays', async () => {
|
||||
const arrayField: ArrayField = {
|
||||
name: 'items',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'itemName',
|
||||
@@ -115,8 +118,6 @@ describe('sanitizeFields', () => {
|
||||
},
|
||||
],
|
||||
label: false,
|
||||
name: 'items',
|
||||
type: 'array',
|
||||
}
|
||||
const sanitizedField = (
|
||||
await sanitizeFields({
|
||||
@@ -133,20 +134,20 @@ describe('sanitizeFields', () => {
|
||||
it('should allow label opt-out for blocks', async () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
name: 'noLabelBlock',
|
||||
type: 'blocks',
|
||||
blocks: [
|
||||
{
|
||||
slug: 'number',
|
||||
fields: [
|
||||
{
|
||||
name: 'testNumber',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
slug: 'number',
|
||||
},
|
||||
],
|
||||
label: false,
|
||||
name: 'noLabelBlock',
|
||||
type: 'blocks',
|
||||
},
|
||||
]
|
||||
const sanitizedField = (
|
||||
@@ -166,14 +167,14 @@ describe('sanitizeFields', () => {
|
||||
it('should label arrays with plural and singular', async () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
name: 'items',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'itemName',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
name: 'items',
|
||||
type: 'array',
|
||||
},
|
||||
]
|
||||
const sanitizedField = (
|
||||
@@ -192,14 +193,14 @@ describe('sanitizeFields', () => {
|
||||
it('should label blocks with plural and singular', async () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
blocks: [
|
||||
{
|
||||
fields: [{ name: 'testNumber', type: 'number' }],
|
||||
slug: 'number',
|
||||
},
|
||||
],
|
||||
name: 'specialBlock',
|
||||
type: 'blocks',
|
||||
blocks: [
|
||||
{
|
||||
slug: 'number',
|
||||
fields: [{ name: 'testNumber', type: 'number' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
const sanitizedField = (
|
||||
@@ -225,10 +226,10 @@ describe('sanitizeFields', () => {
|
||||
const validRelationships = ['some-collection']
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: 'my-relationship',
|
||||
name: 'My Relationship',
|
||||
relationTo: 'some-collection',
|
||||
type: 'relationship',
|
||||
label: 'my-relationship',
|
||||
relationTo: 'some-collection',
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -240,10 +241,10 @@ describe('sanitizeFields', () => {
|
||||
const validRelationships = ['some-collection', 'another-collection']
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: 'my-relationship',
|
||||
name: 'My Relationship',
|
||||
relationTo: ['some-collection', 'another-collection'],
|
||||
type: 'relationship',
|
||||
label: 'my-relationship',
|
||||
relationTo: ['some-collection', 'another-collection'],
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -254,22 +255,22 @@ describe('sanitizeFields', () => {
|
||||
it('should not throw on valid relationship inside blocks', async () => {
|
||||
const validRelationships = ['some-collection']
|
||||
const relationshipBlock: Block = {
|
||||
slug: 'relationshipBlock',
|
||||
fields: [
|
||||
{
|
||||
label: 'my-relationship',
|
||||
name: 'My Relationship',
|
||||
relationTo: 'some-collection',
|
||||
type: 'relationship',
|
||||
label: 'my-relationship',
|
||||
relationTo: 'some-collection',
|
||||
},
|
||||
],
|
||||
slug: 'relationshipBlock',
|
||||
}
|
||||
const fields: Field[] = [
|
||||
{
|
||||
blocks: [relationshipBlock],
|
||||
label: 'Layout Blocks',
|
||||
name: 'layout',
|
||||
type: 'blocks',
|
||||
blocks: [relationshipBlock],
|
||||
label: 'Layout Blocks',
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -281,10 +282,10 @@ describe('sanitizeFields', () => {
|
||||
const validRelationships = ['some-collection']
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: 'my-relationship',
|
||||
name: 'My Relationship',
|
||||
relationTo: 'not-valid',
|
||||
type: 'relationship',
|
||||
label: 'my-relationship',
|
||||
relationTo: 'not-valid',
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -296,10 +297,10 @@ describe('sanitizeFields', () => {
|
||||
const validRelationships = ['some-collection', 'another-collection']
|
||||
const fields: Field[] = [
|
||||
{
|
||||
label: 'my-relationship',
|
||||
name: 'My Relationship',
|
||||
relationTo: ['some-collection', 'not-valid'],
|
||||
type: 'relationship',
|
||||
label: 'my-relationship',
|
||||
relationTo: ['some-collection', 'not-valid'],
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -310,22 +311,22 @@ describe('sanitizeFields', () => {
|
||||
it('should throw on invalid relationship inside blocks', async () => {
|
||||
const validRelationships = ['some-collection']
|
||||
const relationshipBlock: Block = {
|
||||
slug: 'relationshipBlock',
|
||||
fields: [
|
||||
{
|
||||
label: 'my-relationship',
|
||||
name: 'My Relationship',
|
||||
relationTo: 'not-valid',
|
||||
type: 'relationship',
|
||||
label: 'my-relationship',
|
||||
relationTo: 'not-valid',
|
||||
},
|
||||
],
|
||||
slug: 'relationshipBlock',
|
||||
}
|
||||
const fields: Field[] = [
|
||||
{
|
||||
blocks: [relationshipBlock],
|
||||
label: 'Layout Blocks',
|
||||
name: 'layout',
|
||||
type: 'blocks',
|
||||
blocks: [relationshipBlock],
|
||||
label: 'Layout Blocks',
|
||||
},
|
||||
]
|
||||
await expect(async () => {
|
||||
@@ -337,8 +338,8 @@ describe('sanitizeFields', () => {
|
||||
const fields: Field[] = [
|
||||
{
|
||||
name: 'My Checkbox',
|
||||
required: true,
|
||||
type: 'checkbox',
|
||||
required: true,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable no-use-before-define */
|
||||
|
||||
import type { EditorProps } from '@monaco-editor/react'
|
||||
import type { CSSProperties } from 'react'
|
||||
|
||||
@@ -241,8 +241,8 @@ export interface FieldBase {
|
||||
validate?: Validate
|
||||
}
|
||||
|
||||
export type NumberField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type NumberField = {
|
||||
admin?: {
|
||||
/** Set this property to a string that will be used for browser autocomplete. */
|
||||
autoComplete?: string
|
||||
components?: {
|
||||
@@ -255,33 +255,34 @@ export type NumberField = FieldBase & {
|
||||
placeholder?: Record<string, string> | string
|
||||
/** Set a value for the number field to increment / decrement using browser controls. */
|
||||
step?: number
|
||||
}
|
||||
} & Admin
|
||||
/** Maximum value accepted. Used in the default `validation` function. */
|
||||
max?: number
|
||||
/** Minimum value accepted. Used in the default `validation` function. */
|
||||
min?: number
|
||||
type: 'number'
|
||||
} & (
|
||||
| {
|
||||
/** Makes this field an ordered array of numbers instead of just a single number. */
|
||||
hasMany: true
|
||||
/** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
maxRows?: number
|
||||
/** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
minRows?: number
|
||||
}
|
||||
| {
|
||||
/** Makes this field an ordered array of numbers instead of just a single number. */
|
||||
hasMany?: false | undefined
|
||||
/** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
maxRows?: undefined
|
||||
/** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
minRows?: undefined
|
||||
}
|
||||
)
|
||||
| {
|
||||
/** Makes this field an ordered array of numbers instead of just a single number. */
|
||||
hasMany: true
|
||||
/** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
maxRows?: number
|
||||
/** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
minRows?: number
|
||||
}
|
||||
| {
|
||||
/** Makes this field an ordered array of numbers instead of just a single number. */
|
||||
hasMany?: false | undefined
|
||||
/** Maximum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
maxRows?: undefined
|
||||
/** Minimum number of numbers in the numbers array, if `hasMany` is set to true. */
|
||||
minRows?: undefined
|
||||
}
|
||||
) &
|
||||
FieldBase
|
||||
|
||||
export type TextField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type TextField = {
|
||||
admin?: {
|
||||
autoComplete?: string
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
@@ -291,31 +292,32 @@ export type TextField = FieldBase & {
|
||||
}
|
||||
placeholder?: Record<string, string> | string
|
||||
rtl?: boolean
|
||||
}
|
||||
} & Admin
|
||||
maxLength?: number
|
||||
minLength?: number
|
||||
type: 'text'
|
||||
} & (
|
||||
| {
|
||||
/** Makes this field an ordered array of strings instead of just a single string. */
|
||||
hasMany: true
|
||||
/** Maximum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
maxRows?: number
|
||||
/** Minimum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
minRows?: number
|
||||
}
|
||||
| {
|
||||
/** Makes this field an ordered array of strings instead of just a single string. */
|
||||
hasMany?: false | undefined
|
||||
/** Maximum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
maxRows?: undefined
|
||||
/** Minimum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
minRows?: undefined
|
||||
}
|
||||
)
|
||||
| {
|
||||
/** Makes this field an ordered array of strings instead of just a single string. */
|
||||
hasMany: true
|
||||
/** Maximum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
maxRows?: number
|
||||
/** Minimum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
minRows?: number
|
||||
}
|
||||
| {
|
||||
/** Makes this field an ordered array of strings instead of just a single string. */
|
||||
hasMany?: false | undefined
|
||||
/** Maximum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
maxRows?: undefined
|
||||
/** Minimum number of strings in the strings array, if `hasMany` is set to true. */
|
||||
minRows?: undefined
|
||||
}
|
||||
) &
|
||||
FieldBase
|
||||
|
||||
export type EmailField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type EmailField = {
|
||||
admin?: {
|
||||
autoComplete?: string
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
@@ -324,12 +326,12 @@ export type EmailField = FieldBase & {
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
placeholder?: Record<string, string> | string
|
||||
}
|
||||
} & Admin
|
||||
type: 'email'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type TextareaField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type TextareaField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
@@ -339,26 +341,26 @@ export type TextareaField = FieldBase & {
|
||||
placeholder?: Record<string, string> | string
|
||||
rows?: number
|
||||
rtl?: boolean
|
||||
}
|
||||
} & Admin
|
||||
maxLength?: number
|
||||
minLength?: number
|
||||
type: 'textarea'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type CheckboxField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type CheckboxField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
}
|
||||
} & Admin
|
||||
type: 'checkbox'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type DateField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type DateField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
@@ -367,14 +369,14 @@ export type DateField = FieldBase & {
|
||||
}
|
||||
date?: ConditionalDateProps
|
||||
placeholder?: Record<string, string> | string
|
||||
}
|
||||
} & Admin
|
||||
type: 'date'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type GroupField = Omit<FieldBase, 'required' | 'validation'> & {
|
||||
admin?: Admin & {
|
||||
export type GroupField = {
|
||||
admin?: {
|
||||
hideGutter?: boolean
|
||||
}
|
||||
} & Admin
|
||||
fields: Field[]
|
||||
/** Customize generated GraphQL and Typescript schema names.
|
||||
* By default, it is bound to the collection.
|
||||
@@ -384,47 +386,48 @@ export type GroupField = Omit<FieldBase, 'required' | 'validation'> & {
|
||||
*/
|
||||
interfaceName?: string
|
||||
type: 'group'
|
||||
}
|
||||
} & Omit<FieldBase, 'required' | 'validation'>
|
||||
|
||||
export type RowAdmin = Omit<Admin, 'description'>
|
||||
|
||||
export type RowField = Omit<FieldBase, 'admin' | 'label' | 'name'> & {
|
||||
export type RowField = {
|
||||
admin?: RowAdmin
|
||||
fields: Field[]
|
||||
type: 'row'
|
||||
}
|
||||
} & Omit<FieldBase, 'admin' | 'label' | 'name'>
|
||||
|
||||
export type CollapsibleField = Omit<FieldBase, 'label' | 'name'> & {
|
||||
export type CollapsibleField = {
|
||||
fields: Field[]
|
||||
type: 'collapsible'
|
||||
} & (
|
||||
| {
|
||||
admin: Admin & {
|
||||
components: {
|
||||
RowLabel: RowLabelComponent
|
||||
} & Admin['components']
|
||||
initCollapsed?: boolean
|
||||
}
|
||||
label?: Required<FieldBase['label']>
|
||||
}
|
||||
| {
|
||||
admin?: Admin & {
|
||||
initCollapsed?: boolean
|
||||
}
|
||||
label: Required<FieldBase['label']>
|
||||
}
|
||||
)
|
||||
| {
|
||||
admin: {
|
||||
components: {
|
||||
RowLabel: RowLabelComponent
|
||||
} & Admin['components']
|
||||
initCollapsed?: boolean
|
||||
} & Admin
|
||||
label?: Required<FieldBase['label']>
|
||||
}
|
||||
| {
|
||||
admin?: {
|
||||
initCollapsed?: boolean
|
||||
} & Admin
|
||||
label: Required<FieldBase['label']>
|
||||
}
|
||||
) &
|
||||
Omit<FieldBase, 'label' | 'name'>
|
||||
|
||||
export type TabsAdmin = Omit<Admin, 'description'>
|
||||
|
||||
type TabBase = Omit<FieldBase, 'required' | 'validation'> & {
|
||||
type TabBase = {
|
||||
description?: Description
|
||||
fields: Field[]
|
||||
interfaceName?: string
|
||||
saveToJWT?: boolean | string
|
||||
}
|
||||
} & Omit<FieldBase, 'required' | 'validation'>
|
||||
|
||||
export type NamedTab = TabBase & {
|
||||
export type NamedTab = {
|
||||
/** Customize generated GraphQL and Typescript schema names.
|
||||
* The slug is used by default.
|
||||
*
|
||||
@@ -432,9 +435,9 @@ export type NamedTab = TabBase & {
|
||||
* **Note**: Top level types can collide, ensure they are unique amongst collections, arrays, groups, blocks, tabs.
|
||||
*/
|
||||
interfaceName?: string
|
||||
}
|
||||
} & TabBase
|
||||
|
||||
export type UnnamedTab = Omit<TabBase, 'name'> & {
|
||||
export type UnnamedTab = {
|
||||
interfaceName?: never
|
||||
/**
|
||||
* Can be either:
|
||||
@@ -448,20 +451,20 @@ export type UnnamedTab = Omit<TabBase, 'name'> & {
|
||||
| LabelFunction
|
||||
| string
|
||||
localized?: never
|
||||
}
|
||||
} & Omit<TabBase, 'name'>
|
||||
|
||||
export type Tab = NamedTab | UnnamedTab
|
||||
|
||||
export type TabsField = Omit<FieldBase, 'admin' | 'localized' | 'name' | 'saveToJWT'> & {
|
||||
export type TabsField = {
|
||||
admin?: TabsAdmin
|
||||
tabs: Tab[]
|
||||
type: 'tabs'
|
||||
}
|
||||
} & Omit<FieldBase, 'admin' | 'localized' | 'name' | 'saveToJWT'>
|
||||
|
||||
export type TabAsField = Tab & {
|
||||
export type TabAsField = {
|
||||
name?: string
|
||||
type: 'tab'
|
||||
}
|
||||
} & Tab
|
||||
|
||||
export type UIField = {
|
||||
admin: {
|
||||
@@ -492,7 +495,7 @@ export type UIField = {
|
||||
type: 'ui'
|
||||
}
|
||||
|
||||
export type UploadField = FieldBase & {
|
||||
export type UploadField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
@@ -508,33 +511,33 @@ export type UploadField = FieldBase & {
|
||||
maxDepth?: number
|
||||
relationTo: CollectionSlug
|
||||
type: 'upload'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
type CodeAdmin = Admin & {
|
||||
type CodeAdmin = {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
editorOptions?: EditorProps['options']
|
||||
language?: string
|
||||
}
|
||||
} & Admin
|
||||
|
||||
export type CodeField = Omit<FieldBase, 'admin'> & {
|
||||
export type CodeField = {
|
||||
admin?: CodeAdmin
|
||||
maxLength?: number
|
||||
minLength?: number
|
||||
type: 'code'
|
||||
}
|
||||
} & Omit<FieldBase, 'admin'>
|
||||
|
||||
type JSONAdmin = Admin & {
|
||||
type JSONAdmin = {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
editorOptions?: EditorProps['options']
|
||||
}
|
||||
} & Admin
|
||||
|
||||
export type JSONField = Omit<FieldBase, 'admin'> & {
|
||||
export type JSONField = {
|
||||
admin?: JSONAdmin
|
||||
jsonSchema?: {
|
||||
fileMatch: string[]
|
||||
@@ -542,17 +545,17 @@ export type JSONField = Omit<FieldBase, 'admin'> & {
|
||||
uri: string
|
||||
}
|
||||
type: 'json'
|
||||
}
|
||||
} & Omit<FieldBase, 'admin'>
|
||||
|
||||
export type SelectField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type SelectField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
isClearable?: boolean
|
||||
isSortable?: boolean
|
||||
}
|
||||
} & Admin
|
||||
/**
|
||||
* Customize the SQL table name
|
||||
*/
|
||||
@@ -564,9 +567,9 @@ export type SelectField = FieldBase & {
|
||||
hasMany?: boolean
|
||||
options: Option[]
|
||||
type: 'select'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
type SharedRelationshipProperties = FieldBase & {
|
||||
type SharedRelationshipProperties = {
|
||||
filterOptions?: FilterOptions
|
||||
hasMany?: boolean
|
||||
/**
|
||||
@@ -577,54 +580,55 @@ type SharedRelationshipProperties = FieldBase & {
|
||||
maxDepth?: number
|
||||
type: 'relationship'
|
||||
} & (
|
||||
| {
|
||||
hasMany: true
|
||||
/**
|
||||
* @deprecated Use 'maxRows' instead
|
||||
*/
|
||||
max?: number
|
||||
maxRows?: number
|
||||
/**
|
||||
* @deprecated Use 'minRows' instead
|
||||
*/
|
||||
min?: number
|
||||
minRows?: number
|
||||
}
|
||||
| {
|
||||
hasMany?: false | undefined
|
||||
/**
|
||||
* @deprecated Use 'maxRows' instead
|
||||
*/
|
||||
max?: undefined
|
||||
maxRows?: undefined
|
||||
/**
|
||||
* @deprecated Use 'minRows' instead
|
||||
*/
|
||||
min?: undefined
|
||||
minRows?: undefined
|
||||
}
|
||||
)
|
||||
| {
|
||||
hasMany: true
|
||||
/**
|
||||
* @deprecated Use 'maxRows' instead
|
||||
*/
|
||||
max?: number
|
||||
maxRows?: number
|
||||
/**
|
||||
* @deprecated Use 'minRows' instead
|
||||
*/
|
||||
min?: number
|
||||
minRows?: number
|
||||
}
|
||||
| {
|
||||
hasMany?: false | undefined
|
||||
/**
|
||||
* @deprecated Use 'maxRows' instead
|
||||
*/
|
||||
max?: undefined
|
||||
maxRows?: undefined
|
||||
/**
|
||||
* @deprecated Use 'minRows' instead
|
||||
*/
|
||||
min?: undefined
|
||||
minRows?: undefined
|
||||
}
|
||||
) &
|
||||
FieldBase
|
||||
|
||||
type RelationshipAdmin = Admin & {
|
||||
type RelationshipAdmin = {
|
||||
allowCreate?: boolean
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
isSortable?: boolean
|
||||
}
|
||||
export type PolymorphicRelationshipField = SharedRelationshipProperties & {
|
||||
admin?: RelationshipAdmin & {
|
||||
} & Admin
|
||||
export type PolymorphicRelationshipField = {
|
||||
admin?: {
|
||||
sortOptions?: { [collectionSlug: CollectionSlug]: string }
|
||||
}
|
||||
} & RelationshipAdmin
|
||||
relationTo: CollectionSlug[]
|
||||
}
|
||||
export type SingleRelationshipField = SharedRelationshipProperties & {
|
||||
admin?: RelationshipAdmin & {
|
||||
} & SharedRelationshipProperties
|
||||
export type SingleRelationshipField = {
|
||||
admin?: {
|
||||
sortOptions?: string
|
||||
}
|
||||
} & RelationshipAdmin
|
||||
relationTo: CollectionSlug
|
||||
}
|
||||
} & SharedRelationshipProperties
|
||||
export type RelationshipField = PolymorphicRelationshipField | SingleRelationshipField
|
||||
|
||||
export type ValueWithRelation = {
|
||||
@@ -646,13 +650,13 @@ export type RichTextField<
|
||||
Value extends object = any,
|
||||
AdapterProps = any,
|
||||
ExtraProperties = object,
|
||||
> = FieldBase & {
|
||||
admin?: Admin & {
|
||||
> = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
}
|
||||
} & Admin
|
||||
editor?:
|
||||
| RichTextAdapter<Value, AdapterProps, AdapterProps>
|
||||
| RichTextAdapterProvider<Value, AdapterProps, AdapterProps>
|
||||
@@ -663,10 +667,11 @@ export type RichTextField<
|
||||
*/
|
||||
maxDepth?: number
|
||||
type: 'richText'
|
||||
} & ExtraProperties
|
||||
} & ExtraProperties &
|
||||
FieldBase
|
||||
|
||||
export type ArrayField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type ArrayField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
RowLabel?: RowLabelComponent
|
||||
} & Admin['components']
|
||||
@@ -675,7 +680,7 @@ export type ArrayField = FieldBase & {
|
||||
* Disable drag and drop sorting
|
||||
*/
|
||||
isSortable?: boolean
|
||||
}
|
||||
} & Admin
|
||||
/**
|
||||
* Customize the SQL table name
|
||||
*/
|
||||
@@ -692,16 +697,16 @@ export type ArrayField = FieldBase & {
|
||||
maxRows?: number
|
||||
minRows?: number
|
||||
type: 'array'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type RadioField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type RadioField = {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
layout?: 'horizontal' | 'vertical'
|
||||
}
|
||||
} & Admin
|
||||
/**
|
||||
* Customize the SQL table name
|
||||
*/
|
||||
@@ -712,7 +717,7 @@ export type RadioField = FieldBase & {
|
||||
enumName?: DBIdentifierName
|
||||
options: Option[]
|
||||
type: 'radio'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type Block = {
|
||||
admin?: {
|
||||
@@ -743,25 +748,25 @@ export type Block = {
|
||||
slug: string
|
||||
}
|
||||
|
||||
export type BlockField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
export type BlockField = {
|
||||
admin?: {
|
||||
initCollapsed?: boolean
|
||||
/**
|
||||
* Disable drag and drop sorting
|
||||
*/
|
||||
isSortable?: boolean
|
||||
}
|
||||
} & Admin
|
||||
blocks: Block[]
|
||||
defaultValue?: unknown
|
||||
labels?: Labels
|
||||
maxRows?: number
|
||||
minRows?: number
|
||||
type: 'blocks'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type PointField = FieldBase & {
|
||||
export type PointField = {
|
||||
type: 'point'
|
||||
}
|
||||
} & FieldBase
|
||||
|
||||
export type Field =
|
||||
| ArrayField
|
||||
@@ -828,9 +833,9 @@ export type NonPresentationalField =
|
||||
| TextareaField
|
||||
| UploadField
|
||||
|
||||
export type FieldWithPath = Field & {
|
||||
export type FieldWithPath = {
|
||||
path?: string
|
||||
}
|
||||
} & Field
|
||||
|
||||
export type FieldWithSubFields = ArrayField | CollapsibleField | GroupField | RowField
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { RichTextAdapter } from '../../../admin/RichText.js'
|
||||
import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../../globals/config/types.js'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { RichTextAdapter } from '../../../admin/RichText.js'
|
||||
import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../../globals/config/types.js'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { RichTextAdapter } from '../../../admin/RichText.js'
|
||||
import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../../globals/config/types.js'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user