Skip to content

Commit 8f7afd1

Browse files
committed
Add ESLint rule for no process.env and no import.meta.env outside of specified files
1 parent a3db9f9 commit 8f7afd1

32 files changed

Lines changed: 1207 additions & 465 deletions

‎eslint.config.ts‎

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,23 @@ export default [
6767
'@typescript-eslint/no-non-null-assertion': 'off',
6868
'@typescript-eslint/no-unsafe-assignment': 'off',
6969
'@typescript-eslint/no-unsafe-call': 'off',
70+
'@typescript-eslint/no-unsafe-function-type': level,
7071
'@typescript-eslint/no-unsafe-member-access': 'off',
7172
'@typescript-eslint/no-unsafe-return': 'off',
7273
'@typescript-eslint/no-unused-vars': [
7374
level,
7475
{ varsIgnorePattern: '^_', argsIgnorePattern: '^_|^this$' },
7576
],
77+
'@typescript-eslint/no-empty-object-type': level,
7678
'@typescript-eslint/no-var-requires': level,
7779
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
80+
'@typescript-eslint/no-wrapper-object-types': level,
7881
'@typescript-eslint/restrict-template-expressions': 'off',
7982
'@typescript-eslint/triple-slash-reference': 'off',
83+
/** Issue with Prettier https://github.com/prettier/eslint-plugin-prettier/issues/65: */
8084
'arrow-body-style': 'off',
81-
camelcase: [level],
82-
curly: 'off',
85+
'camelcase': [level],
86+
'curly': 'off',
8387
'import/no-unresolved': [
8488
level,
8589
{
@@ -105,14 +109,36 @@ export default [
105109
'svg': 'always',
106110
},
107111
],
112+
'import/no-restricted-paths': [
113+
level,
114+
{
115+
zones: [
116+
{
117+
target: 'src/components/',
118+
from: 'src/lib/',
119+
message: 'The src/lib directory is for build-time code only.',
120+
},
121+
{
122+
target: 'src/layouts/',
123+
from: 'src/lib/',
124+
message: 'The src/lib directory is for build-time code only.',
125+
},
126+
{
127+
target: 'src/pages/',
128+
from: 'src/lib/',
129+
message: 'The src/lib directory is for build-time code only.',
130+
},
131+
],
132+
},
133+
],
108134
'import/order': 'off',
109135
'jsdoc/check-indentation': level,
110136
'jsdoc/check-line-alignment': level,
111137
'jsdoc/check-syntax': level,
112138
'jsdoc/check-tag-names': [
113139
level,
114140
{
115-
definedTags: ['NOTE:', 'jest-environment', 'jest-environment-options'],
141+
definedTags: ['NOTE:', 'jest-environment'],
116142
jsxTags: true,
117143
},
118144
],
@@ -131,6 +157,7 @@ export default [
131157
'jsdoc/valid-types': 'off',
132158
'new-cap': [level, { newIsCap: true, capIsNew: false }],
133159
'no-new': level,
160+
'no-process-env': level,
134161
'no-restricted-globals': ['error'].concat(restrictedGlobals),
135162
'no-restricted-imports': [
136163
'error', {
@@ -150,13 +177,14 @@ export default [
150177
'no-unused-expressions': [level, { allowShortCircuit: true, allowTernary: true }],
151178
'no-unused-vars': [level, { varsIgnorePattern: '^_', argsIgnorePattern: '^_|^this$' }],
152179
'no-useless-escape': 'off',
180+
/** Issue with Prettier https://github.com/prettier/eslint-plugin-prettier/issues/65: */
153181
'prefer-arrow-callback': 'off',
154182
'prefer-object-spread': level,
155183
'prefer-spread': level,
156184
'security/detect-non-literal-fs-filename': 'off',
157185
'security/detect-object-injection': 'off',
158186
'security/detect-unsafe-regex': 'off',
159-
semi: ['error', 'never'],
187+
'semi': ['error', 'never'],
160188
},
161189
},
162190
{
@@ -202,4 +230,49 @@ export default [
202230
camelcase: 'off',
203231
},
204232
},
233+
{
234+
files: [
235+
'.eslintrc.js',
236+
'astro.config.ts',
237+
'playwright.config.ts',
238+
'vitest.setup.ts',
239+
'scripts/build/**/*'
240+
],
241+
rules: {
242+
// All files except Astro config should use import.meta.env.ENV_VAR
243+
'no-process-env': 'off',
244+
},
245+
},
246+
{
247+
files: [
248+
'src/components/**/*',
249+
'src/layouts/**/*',
250+
'src/pages/**/*',
251+
],
252+
rules: {
253+
'no-restricted-syntax': [
254+
level,
255+
{
256+
'selector': 'MetaProperty[meta.name="import"][property.name="meta"]',
257+
'message': 'Do not use import.meta.env directly. Use methods in src/components/scripts/utils like isCI(), isDev(), etc.'
258+
}
259+
],
260+
},
261+
},
262+
{
263+
files: [
264+
'src/lib/config/environmentServer.ts',
265+
'src/lib/config/siteUrlServer.ts',
266+
'src/components/scripts/utils/environmentClient.ts',
267+
'src/components/scripts/utils/siteUrlClient.ts',
268+
],
269+
rules: {
270+
'no-restricted-syntax': [
271+
'off',
272+
{
273+
'selector': 'MetaProperty[meta.name="import"][property.name="meta"]',
274+
}
275+
],
276+
},
277+
},
205278
]

‎package-lock.json‎

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
"not IE 11"
2727
],
2828
"scripts": {
29-
"build": "NODE_ENV=production npm run build:favicons && npx astro build",
30-
"build:dev": "NODE_ENV=development npm run build:favicons && npx astro build",
29+
"build": "cross-env NODE_ENV=production npm run build:favicons && npx astro build",
30+
"build:dev": "cross-env NODE_ENV=development npm run build:favicons && npx astro build",
3131
"build:favicons": "npx ts-node ./scripts/build/favicon.ts",
3232
"check": "npx astro check",
3333
"clean": "npx rimraf dist && npx rimraf .astro",
34-
"dev": "npm run sync && npm run build:favicons && NODE_ENV=development npx astro dev",
34+
"dev": "npm run sync && npm run build:favicons && cross-env NODE_ENV=development npx astro dev",
3535
"format": "npm run format:json && npm run format:code && npm run format:style",
3636
"format:code": "npx prettier --write \"@types/**/*.{js,ts}\" \"scripts/**/*.{js,ts}\" \"src/**/*.{js,ts,tsx,astro}\" --plugin=prettier-plugin-astro",
3737
"format:json": "npx prettier --write '**/*.json' --cache --ignore-path .gitignore",
@@ -42,10 +42,10 @@
4242
"lint:style": "npx stylelint \"src/**/*.{css,astro}\"",
4343
"preview": "npm run build:favicons && npx astro build && astro preview",
4444
"sync": "npx astro sync",
45-
"test": "NODE_ENV=test npm run test:unit && npm run test:e2e",
46-
"test:coverage": "NODE_ENV=test npx vitest run --coverage",
47-
"test:e2e": "NODE_ENV=test npx playwright test",
48-
"test:unit": "NODE_ENV=test npx vitest run",
45+
"test": "cross-env NODE_ENV=test npm run test:unit && npm run test:e2e",
46+
"test:coverage": "cross-env NODE_ENV=test npx vitest run --coverage",
47+
"test:e2e": "cross-env NODE_ENV=test npx playwright test",
48+
"test:unit": "cross-env NODE_ENV=test npx vitest run",
4949
"upgrade": "npx @astrojs/upgrade",
5050
"prepare": "husky"
5151
},
@@ -75,7 +75,9 @@
7575
"astro": "5.15.5",
7676
"astro-icon": "^1.1.5",
7777
"astro-vtbot": "^2.1.9",
78+
"cross-env": "^10.1.0",
7879
"dotenv": "17.2.3",
80+
"email-validator": "^2.0.4",
7981
"embla-carousel": "^8.6.0",
8082
"embla-carousel-autoplay": "^8.6.0",
8183
"focus-trap": "7.6.6",
@@ -108,6 +110,7 @@
108110
"zod": "4.1.12"
109111
},
110112
"devDependencies": {
113+
"@eslint-community/eslint-plugin-eslint-comments": "^4.5.0",
111114
"@eslint/js": "9.39.1",
112115
"@playwright/test": "1.56.1",
113116
"@testing-library/dom": "10.4.1",

‎src/components/Avatar/__tests__/server.spec.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe('AvatarManager', () => {
5959

6060
// Constructor should only run once (if in development mode)
6161
// In production, console.log won't be called
62-
if (process.env['NODE_ENV'] === 'development') {
62+
if (import.meta.env.DEV) {
6363
expect(consoleLogSpy).toHaveBeenCalledTimes(1)
6464
}
6565
})

‎src/components/Avatar/server.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ class AvatarManagerClass {
6060
if (filename && imageData) {
6161
// Deep freeze the image metadata to prevent modifications
6262
map[filename] = Object.freeze({ ...imageData })
63-
} else if (process.env['NODE_ENV'] === 'development') {
63+
} else if (import.meta.env.DEV) {
6464
console.warn(`[AvatarManager] Failed to process avatar at path: ${path}`)
6565
}
6666
}
6767

6868
// Freeze the map to prevent modifications
6969
this.avatarMap = Object.freeze(map)
7070

71-
if (process.env['NODE_ENV'] === 'development') {
71+
if (import.meta.env.DEV) {
7272
console.log(`[AvatarManager] Initialized with ${Object.keys(this.avatarMap).length} avatars`)
7373
}
7474
}

0 commit comments

Comments
 (0)