typescript-eslint/naming-conventions function not being applied? - eslint

Given my .eslintrc.js file:
module.exports = {
root: true,
parser: '#typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
tsconfigRootDir: __dirname,
createDefaultProgram: true,
},
plugins: ['#typescript-eslint'],
settings: {
'import/resolver': {
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
node: {},
typescript: {},
},
'import/parsers': {
'#typescript-eslint/parser': ['.ts', '.tsx'],
},
},
rules: {
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/naming-convention.md
'#typescript-eslint/naming-convention': [
'error',
{
selector: 'default',
format: ['camelCase'],
},
// destructured variables come from other places so no format is enforced
{
selector: 'variable',
modifiers: ['destructured'],
format: null,
},
// functions defined as constants must be constants (not var/let)
{
selector: 'variable',
types: ['function'],
modifiers: ['const'],
format: ['camelCase', 'PascalCase'],
},
// Constants can also be camelCase apart from UPPER_CASE
{
selector: 'variable',
modifiers: ['const'],
format: ['UPPER_CASE', 'camelCase'],
},
// functions can be:
// - regular functions (camelCase)
// - functional components (PascalCase)
{
selector: 'function',
format: ['camelCase', 'PascalCase'],
},
// type definitions (class, interface, typeAlias, enum, typeParameter)
// should be PascalCase
{
selector: 'typeLike',
format: ['PascalCase'],
},
// each member of an enum (const-like) should be UPPER_CASE
{
selector: 'enumMember',
format: ['UPPER_CASE'],
},
{
// Ignore properties that require quotes
selector: [
'classProperty',
'objectLiteralProperty',
'typeProperty',
'classMethod',
'objectLiteralMethod',
'typeMethod',
'accessor',
'enumMember',
],
format: null,
modifiers: ['requiresQuotes'],
},
],
},
};
I think it should detect as errors UPPER_CASE named functions, but it doesn't
function FUNCTION1() {
// this function name should be an error but it isn't
}
const FUNCTION2 = () => {}; // this should be an error too
const function3 = () => {}; // this should be ok
function4() {} // this should be ok too
Am I missing anything in this config?

One of those is easy, in const FUNCTION2 = () => {};, FUNCTION2 is actually a variable, and const.
Helpful tip: you can use error messages to your advantage by forcing a failure condition to see which one it's matching. Adding custom: { regex: 'FUNCTION2', match: false} to that rule adds the caveat "but it can't match FUNCTION2" to it, which will turn that line into the error:
Variable name FUNCTION2 must not match the RegExp: /FUNCTION2/u
which exposes that it's a variable.
Doing that one rule at a time for FUNCTION1 will at least tell you which rule it's matching.

Related

ESLint: types for `eslintrc.js`

I want my eslintrc.js to be typechecked, and to have all the type definitions of allowed rules builtin.
i.e. like:
module.exports = defineESLint({
rules: {
// intellisence: Enforce the consistent use of either backticks, double, or single quotes
// quotes?: 'off' | 'warn' | 'error'
// | ['warn' | 'error', 'single' | 'double', { avoidEscape?: true }]
quotes: ["warn", 'single', {avoidEscape: true}],
}
})
And I generally want this to work with all my eslint extensions
Currently all I can do is
{
"$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/eslintrc.json",
"rules": {
"quotes": [
"warn",
"single",
{
"avoidEscape": true
}
]
}
}
in json, but it barely works
npm:eslint-define-config
usage:
.eslintrc.js
// #ts-check
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
root: true,
rules: {
// rules...
},
});
Improve your eslint configuration experience with:
auto-suggestions
type checking (Use // #ts-check at the first line in your .eslintrc.js)
documentation
deprecation warnings

How to wrap Vite build in IIFE and still have all the dependencies bundled into a single file?

I'm building a chrome extension using Vite as my build tool. The main problem is during minification and mangling there are a lot of global variables created. After injecting my script to the page they conflict with already defined variables on window object.
I imagine the perfect solution would be to have my entire script wrapped in IIFE. I tried using esbuild.format = 'iife'. The resulting build is in fact wrapped in IIFE, however all the imports are not inlined. Instead resulting script is like 15 lines long with a bunch of require statements, which obviously does not work in the browser.
This is my config file:
export default defineConfig({
plugins: [
vue(),
],
esbuild: {
format: 'iife',
},
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, './src/web/index.ts'),
output: {
dir: resolve(__dirname, './dist'),
entryFileNames: 'web.js',
assetFileNames: 'style.css',
},
},
},
resolve: {
alias: {
'#': resolve(__dirname, './src'),
},
},
});
I'm currently using this hack so to say to wrap my build in IIFE (for this I removed the esbuild.format option).
Hey I am doing the exact same thing! And I also noticed the unminified variables and functions can clash with random code in a webpage.
From what I researched myself on this topic, you shouldn't change esbuild build options with Vite as that will prevent Rollup from transforming the output. Instead, you should use format: 'iife' in the rollupOptions of your vite.config. However, in my case (and yours I believe), I have to output multiple bundles since the extension code can't share modules amongst each other. Which will crash when you set the format to 'iife' due to:
Invalid value for option "output.inlineDynamicImports" - multiple inputs are not supported when "output.inlineDynamicImports" is true.
The only solution in my case seems to be to either use multiple vite.configs (I already have two) for each of my bundle with single input entry point and format as 'iife'. Or, as you did, just write the self-invoking function yourself with some hacky script. Seems though there aren't any perfect solutions as of now.
EDIT: Okay, got it working. This is my vite.config.ts (the project):
import { defineConfig } from 'vite'
import { svelte } from '#sveltejs/vite-plugin-svelte'
import tsconfigPaths from 'vite-tsconfig-paths'
import path from 'path'
/** #type {import('vite').UserConfig} */
export default defineConfig({
plugins: [svelte({}), tsconfigPaths()],
build: {
minify: false,
rollupOptions: {
output: {
chunkFileNames: '[name].js',
entryFileNames: '[name].js'
},
input: {
inject: path.resolve('./src/inject.ts'),
proxy: path.resolve('./src/proxy.ts'),
'pop-up': path.resolve('./pop-up.html')
},
plugins: [
{
name: 'wrap-in-iife',
generateBundle(outputOptions, bundle) {
Object.keys(bundle).forEach((fileName) => {
const file = bundle[fileName]
if (fileName.slice(-3) === '.js' && 'code' in file) {
file.code = `(() => {\n${file.code}})()`
}
})
}
}
]
}
}
})
Okay, I made it working with this config:
export default defineConfig({
plugins: [
vue(),
],
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, './src/web/index.ts'),
output: {
format: 'iife',
dir: resolve(__dirname, './dist'),
entryFileNames: 'web.js',
assetFileNames: 'style.css',
},
},
},
resolve: {
alias: {
'#': resolve(__dirname, './src'),
},
},
});
They key part is format: 'iife' inside build.rollupOptions.output.

Next JS advanced feature Content Security policy format

I am adding security Policy headers to my application using Security headers advanced feature of next.js
Reference :https://nextjs.org/docs/advanced-features/security-headers
I am quiet clear of how to add the security policies to the next application except the Content Security policy,It does not show any format of the policy in the Documentation :
Taking help of next and developer.mozilla org I have some code in place,that I am attaching herewith. Can anybody help me with the correct format to define content-security policy in Next.JS
Code in Next.config.js
const cspPolicy = "default-src 'self';connect-src 'self','preview.contentful.com','*.flippenterprise.net', 'aq.flippenterprise.net','https://www.google-analytics.com','dpm.demdex.net','stats.g.doubleclick.net','lcljoefresh.sc.omtrdc.net','sfml.flippback.com','p.flipp.com','https://sentry.io/',";
const securityHeaders = [
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
},
{
key: 'Content-Security-Policy',
value: cspPolicy
}
];
const headers = {
async headers() {
return [
{
// Apply these headers to all routes in your application.
source: '/(.*)',
headers: securityHeaders,
},
]
},
}
const nextConfig = {
env: {
search_key: process.env.search_key,
appDynamicsKey: process.env.appDynamicsKey,
ENVIRONMENT: process.env.ENVIRONMENT,
},
webpack5:false,
// https://nextjs.org/docs#customizing-webpack-config
webpack: (webpackConfig) => {
const { module = {} } = webpackConfig;
return {
...webpackConfig,
module: {
...module,
rules: [
...(module.rules || []),
{
test: /\.(txt|png|woff|woff2|eot|ttf|gif|jpg|ico|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]',
publicPath: '/_next/static/files',
outputPath: 'static/files',
},
},
},
{
test: /\.spec.jsx$/,
loader: 'ignore-loader',
},
],
},
};
},
};
const sassOptions = {
sassLoaderOptions: {
outputStyle: 'compressed',
},
};
module.exports = withPlugins(
[[withSass, sassOptions], [withFonts], [withCSS], [withBundleAnalyzer]],
nextConfig,
headers,
);

Apollo GraphQL Server - Access query params from cache plugin

I have an Apollo GraphQL server using the apollo-server-plugin-response-cache plugin and I need to determine whether or not I'm going to write to the cache based on incoming parameters. I have the plugin set up and I'm using the shouldWriteToCache hook. I can print out the GraphQLRequestContext object that gets passed into the hook, and I can see the full request source, but request.variables is empty. Other than parsing the query itself, how can I access the actual params for the resolver in this hook? (In the example below, I need the value of param2.)
Apollo Server:
new ApolloServer({
introspection: true,
playground: true,
subscriptions: false,
typeDefs,
resolvers,
cacheControl: {
defaultMaxAge: 60
},
plugins: [
apolloServerPluginResponseCache({
cache, // This is a "apollo-server-cache-redis" instance
shouldWriteToCache: (requestContext) => {
// I get a lot of info here, including the source query, but not the
// parsed out query variables
console.log(requestContext.request);
// What I want to do here is:
return !context.request.variables.param2
// but `variables` is empty, and I can't see that value parsed anywhere else
}
})
]
})
Here is my resolver:
export async function exapi(variables, context) {
// in here I use context.param1 and context.param2
// ...
}
I have also tried:
export async function exapi(variables, { param1, param2 }) {
// ...
}
Here is what I get logged out from the code above:
{
query: '{\n' +
' exapi(param1: "value1", param2: true) {\n' +
' records\n' +
' }\n' +
'}\n',
operationName: null,
variables: {}, // <-- this is empty?! How can I get param2's value??
extensions: undefined,
http: Request {
size: 0,
timeout: 0,
follow: 20,
compress: true,
counter: 0,
agent: undefined,
[Symbol(Body internals)]: { body: null, disturbed: false, error: null },
[Symbol(Request internals)]: {
method: 'POST',
redirect: 'follow',
headers: [Headers],
parsedURL: [Url],
signal: null
}
}
}
If you didn't provide variables for GraphQL query, you could get the arguments from the GraphQL query string via ArgumentNode of AST
If you provide variables for GraphQL query, you will get them from requestContext.request.variables.
E.g.
server.js:
import apolloServerPluginResponseCache from 'apollo-server-plugin-response-cache';
import { ApolloServer, gql } from 'apollo-server';
import { RedisCache } from 'apollo-server-cache-redis';
const typeDefs = gql`
type Query {
exapi(param1: String, param2: Boolean): String
}
`;
const resolvers = {
Query: {
exapi: (_, { param1, param2 }) => 'teresa teng',
},
};
const cache = new RedisCache({ host: 'localhost', port: 6379 });
const server = new ApolloServer({
introspection: true,
playground: true,
subscriptions: false,
typeDefs,
resolvers,
cacheControl: {
defaultMaxAge: 60,
},
plugins: [
apolloServerPluginResponseCache({
cache,
shouldWriteToCache: (requestContext) => {
console.log(requestContext.document.definitions[0].selectionSet.selections[0].arguments);
return true;
},
}),
],
});
server.listen().then(({ url }) => console.log(`🚀 Server ready at ${url}`));
GraphQL query:
query{
exapi(param1: "value1", param2: true)
}
Server logs print param1 and param2 arguments:
🚀 Server ready at http://localhost:4000/
[]
[ { kind: 'Argument',
name: { kind: 'Name', value: 'param1', loc: [Object] },
value:
{ kind: 'StringValue',
value: 'value1',
block: false,
loc: [Object] },
loc: { start: 15, end: 31 } },
{ kind: 'Argument',
name: { kind: 'Name', value: 'param2', loc: [Object] },
value: { kind: 'BooleanValue', value: true, loc: [Object] },
loc: { start: 33, end: 45 } } ]

How to disable warn about some unused params, but keep "#typescript-eslint/no-unused-vars" rule

I want to disable no unused params warning in some cases but keep "unused vars" rule.
For example here I would want to leave arguments in place to see what is passed to resolver:
const Query = objectType({
name: 'Query',
definition(t) {
t.field('test', {
type: 'Test',
resolve: (root, args, ctx) => {
const x = 1
return { id: 1, time: new Date().toString() }
},
})
},
})
I get warnings:
26:17 warning 'root' is defined but never used #typescript-eslint/no-unused-vars
26:23 warning 'args' is defined but never used #typescript-eslint/no-unused-vars
26:29 warning 'ctx' is defined but never used #typescript-eslint/no-unused-vars
27:15 warning 'x' is assigned a value but never used #typescript-eslint/no-unused-vars
ESLint config:
module.exports = {
root: true,
parser: '#typescript-eslint/parser',
parserOptions: { ecmaVersion: 2020, ecmaFeatures: { jsx: true } },
env: {
browser: true,
node: true,
},
extends: ['plugin:react-hooks/recommended', 'eslint:recommended', 'plugin:#typescript-eslint/recommended', 'plugin:react/recommended'],
settings: {
react: {
version: 'detect',
},
},
rules: {
'#typescript-eslint/no-empty-function': 'off',
'react/react-in-jsx-scope': 'off',
'#typescript-eslint/no-explicit-any': 'off',
'react/prop-types': 'off',
'#typescript-eslint/no-var-requires': 'off',
'#typescript-eslint/explicit-module-boundary-types': 'off',
'no-unused-vars': 'off',
'#typescript-eslint/no-unused-vars': ['off'],
},
ignorePatterns: ['**/generated/*'],
}
I was trying to disable it somehow, but found only this option that disables everything:
'no-unused-vars': 'off',
'#typescript-eslint/no-unused-vars': ['off'],
Only way that I found is to use ignore pattern argsIgnorePattern in rule options. If your variable is unused, just add underscore _ctx and ESLint will ignore it, but no-unused-vars rule will still work for other values. After you will need to use this value, just remove underscore ctx.
// note you must disable the base rule as it can report incorrect errors
"no-unused-vars": "off",
"#typescript-eslint/no-unused-vars": [
"warn", // or "error"
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
],
You can change this pattern ^_ as you like using RegExp.
Example:
const _a = 'unused, no warning'
const b = 'unused, warning'

Resources