* chore(admin): remove punycode dependency
WHATWG URL handles IDN natively on Node >=20, so the punycode call
before `new URL()` is redundant.
Per Node docs (https://nodejs.org/api/url.html#new-urlinput-base):
Unicode characters appearing within the host name of input will be
automatically converted to ASCII using the Punycode algorithm.
const myURL = new URL('https://測試');
// https://xn--g6w251d/
Drops `punycode` and `@types/punycode` from packages/core/admin.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(typescript): guard pathExistsSync against undefined config path
`getConfigPath` may return `undefined` when no tsconfig matches; passing
that into `fse.pathExistsSync` triggers DEP0187 on Node >=22:
[DEP0187] DeprecationWarning: Passing invalid argument types to
fs.existsSync is deprecated
Short-circuit to `false` when the path is not resolved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Ben Irvin <ben.irvin@strapi.io>
* chore(eslint): migrate .eslintrc + .eslintignore to .eslintrc.cjs
Consolidates the per-package ESLint setup into a single typed
`.eslintrc.cjs` file across the monorepo (177 files touched).
Why
- `.eslintignore` is removed in ESLint v9/v10. Folding ignore patterns
into `ignorePatterns` inside the rc file is the supported migration
path and unblocks future ESLint upgrades (which will likely be needed
alongside the in-flight TypeScript 6 migration).
- `.cjs` extension is explicit about module format, so the configs keep
working if any package later adopts `"type": "module"` (no CJS/ESM
surprises).
- Wrapping each config in `// @ts-check` + a `Linter.Config`-typed
`const config` block gives editor autocomplete and catches typos.
Surfaced two real duplicates in
`eslint-config-custom/back/typescript.js`
(`node/no-unsupported-features/es-syntax`,
`node/no-missing-import`), now deduplicated.
- `extends` references switched from the `custom/*` shorthand to the
explicit `eslint-config-custom/*` package name. ESLint resolves both,
but the explicit form makes the source unambiguous.
- Added `coverage/` to `ignorePatterns` so coverage output produced
inside a workspace is not linted.
Misc
- `examples/kitchensink` had ESLint configured but no `lint` script;
added one so the config actually runs.
- `nx.json` hash inputs updated:
- removed `.eslintignore` (no longer exists)
- replaced `{projectRoot}/.eslintrc.js` with
`{projectRoot}/**/.eslintrc.cjs` so nested package configs are also
part of the cache key (the previous glob missed them).
- `packages/utils/upgrade/tsconfig.eslint.json` include path updated
from `.eslintrc.js` to `.eslintrc.cjs`.
Verification
- `eslint --print-config` resolves cleanly on sampled back/front
packages (admin, users-permissions, upload).
- Full `pnpm -r lint` is clean.
* chore(eslint): set tsconfigRootDir for vscode-eslint typed linting
CLI lint resolved tsconfig paths via cwd, but vscode-eslint runs from
the workspace root and could not locate per-package tsconfigs. Set
parserOptions.tsconfigRootDir to __dirname in each package's
.eslintrc.cjs so the editor resolves typed-lint configs correctly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(eslint): self-ignore configs, scope coverage to jest packages
- Replace `env: { es6: true }` workaround with `.eslintrc.cjs` in
ignorePatterns so eslint never lints the config file itself
(root cause of the "const is not a keyword" parse error in es5)
- Add `.eslintrc.cjs` to ignorePatterns across all configs that
were missing it
- Restrict `coverage/` ignorePatterns to workspace roots that
actually run jest; drop from non-test packages and admin/server
subdir configs (tests run from the workspace root)
* feat: strapi dev continue watching on error
* fix(strapi): await TS compile in build and harden develop watcher
Await tsUtils.compile during strapi build so failures are caught and
process still exits with 1. Add ensureWatcher guard to avoid duplicate
chokidar handlers when strapiInstance.start() throws after the watcher
is registered. Wrap cluster reload compile in try/catch with exit on
failure; fail loadStrapi spinner and normalize non-Error throws in the
develop catch path.
---------
Co-authored-by: Ben Irvin <ben@innerdvations.com>
Co-authored-by: Ben Irvin <ben.irvin@strapi.io>