-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
docs: fix incorrect ESM module field info #33451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
|
danielroe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you!
| @@ -0,0 +1,364 @@ | |||
| --- | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you mean to include this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
WalkthroughUpdates documentation in docs/2.guide/2.concepts/7.esm.md. Adds a note that the package.json module field is a bundler convention and not used by Node.js. Revises the Node.js resolution rule in the “What Are Valid Imports in a Node.js Context?” section to state that Node.js checks the exports entry first and falls back to main if exports is absent, replacing prior wording that mentioned exports or module. Retains existing ESM guidance with phrasing adjusted to reflect the new rule. Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🔇 Additional comments (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
examples/standard-schema-validation/package.jsonis excluded by!**/package.jsonpackages/schema/package.jsonis excluded by!**/package.jsonpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml,!pnpm-lock.yaml
📒 Files selected for processing (12)
docs/2.guide/1.concepts/7.esm.md(2 hunks)docs/3.api/2.composables/use-nuxt-standard-schema.md(1 hunks)examples/standard-schema-validation/README.md(1 hunks)examples/standard-schema-validation/modules/example-module.ts(1 hunks)examples/standard-schema-validation/nuxt.config.ts(1 hunks)packages/kit/src/index.ts(1 hunks)packages/kit/src/loader/schema.ts(2 hunks)packages/nuxt/src/core/schema.ts(3 hunks)packages/schema/build.config.ts(1 hunks)packages/schema/src/index.ts(1 hunks)packages/schema/src/types/config.ts(2 hunks)packages/schema/src/utils/standard-schema.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Follow standard TypeScript conventions and best practices
Files:
packages/schema/src/types/config.tspackages/kit/src/index.tspackages/schema/src/utils/standard-schema.tspackages/schema/src/index.tspackages/schema/build.config.tspackages/kit/src/loader/schema.tsexamples/standard-schema-validation/nuxt.config.tspackages/nuxt/src/core/schema.tsexamples/standard-schema-validation/modules/example-module.ts
🧬 Code graph analysis (5)
packages/schema/src/types/config.ts (1)
packages/schema/src/utils/standard-schema.ts (1)
StandardSchemaV1(5-10)
packages/schema/src/utils/standard-schema.ts (2)
packages/schema/src/index.ts (8)
StandardSchemaV1(14-14)isStandardSchema(15-15)ExtendedSchemaDefinition(14-14)SchemaDefinition(4-4)StandardSchemaExtension(14-14)standardSchemaToJsonSchema(15-15)validateWithStandardSchema(15-15)formatStandardSchemaIssue(15-15)packages/schema/src/types/config.ts (1)
SchemaDefinition(14-14)
packages/kit/src/loader/schema.ts (2)
packages/kit/src/index.ts (2)
extendNuxtStandardSchema(9-9)useNuxt(21-21)packages/schema/src/utils/standard-schema.ts (2)
StandardSchemaV1(5-10)StandardSchemaExtension(25-27)
packages/nuxt/src/core/schema.ts (2)
packages/schema/src/utils/standard-schema.ts (6)
StandardSchemaV1(5-10)isStandardSchema(13-19)standardSchemaToJsonSchema(30-43)StandardSchemaExtension(25-27)validateWithStandardSchema(46-68)formatStandardSchemaIssue(71-76)packages/nuxt/src/utils.ts (1)
logger(13-13)
examples/standard-schema-validation/modules/example-module.ts (1)
packages/kit/src/loader/schema.ts (1)
extendNuxtStandardSchema(28-37)
🪛 markdownlint-cli2 (0.18.1)
examples/standard-schema-validation/README.md
279-279: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
docs/3.api/2.composables/use-nuxt-standard-schema.md
364-364: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
| nitroConfig.virtual['#build/example-module-composable'] = ` | ||
| export const useExampleModule = () => { | ||
| return { | ||
| apiEndpoint: '${options.apiEndpoint}', | ||
| timeout: ${options.timeout}, | ||
| retries: ${options.retries}, | ||
| enableDebug: ${options.enableDebug} | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serialise option values before emitting the virtual module
Interpolating options.* directly into the template will break as soon as a value contains a quote or newline (e.g. an endpoint like https://api.example.com/foo'bar), producing invalid generated code and aborting the build. Please serialise each value (e.g. with JSON.stringify) before embedding it in the virtual module payload.
- nuxt.hook('nitro:config', (nitroConfig) => {
+ nuxt.hook('nitro:config', (nitroConfig) => {
nitroConfig.virtual ||= {}
- nitroConfig.virtual['#build/example-module-composable'] = `
+ const { apiEndpoint, timeout, retries, enableDebug } = options
+ nitroConfig.virtual['#build/example-module-composable'] = `
export const useExampleModule = () => {
return {
- apiEndpoint: '${options.apiEndpoint}',
- timeout: ${options.timeout},
- retries: ${options.retries},
- enableDebug: ${options.enableDebug}
+ apiEndpoint: ${JSON.stringify(apiEndpoint)},
+ timeout: ${JSON.stringify(timeout)},
+ retries: ${JSON.stringify(retries)},
+ enableDebug: ${JSON.stringify(enableDebug)}
}
}
`
})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| nitroConfig.virtual['#build/example-module-composable'] = ` | |
| export const useExampleModule = () => { | |
| return { | |
| apiEndpoint: '${options.apiEndpoint}', | |
| timeout: ${options.timeout}, | |
| retries: ${options.retries}, | |
| enableDebug: ${options.enableDebug} | |
| } | |
| } | |
| nitroConfig.virtual ||= {} | |
| const { apiEndpoint, timeout, retries, enableDebug } = options | |
| nitroConfig.virtual['#build/example-module-composable'] = ` | |
| export const useExampleModule = () => { | |
| return { | |
| - apiEndpoint: '${options.apiEndpoint}', | |
| - timeout: ${options.timeout}, | |
| - retries: ${options.retries}, | |
| apiEndpoint: ${JSON.stringify(apiEndpoint)}, | |
| timeout: ${JSON.stringify(timeout)}, | |
| retries: ${JSON.stringify(retries)}, | |
| enableDebug: ${JSON.stringify(enableDebug)} | |
| } | |
| } | |
| ` |
🤖 Prompt for AI Agents
In examples/standard-schema-validation/modules/example-module.ts around lines 51
to 59, the virtual module string interpolates options.* directly which will
produce invalid JS if values contain quotes/newlines; update the template to
serialise each embedded option using JSON.stringify (or equivalent) so
apiEndpoint, timeout, retries and enableDebug are JSON-encoded before insertion
into the template literal, ensuring the generated module is valid even for
strings with quotes or newlines.
packages/nuxt/src/core/schema.ts
Outdated
| nuxt.hooks.addHooks({ | ||
| 'schema:extend': (schemas: (SchemaDefinition | StandardSchemaExtension)[]) => { | ||
| for (const schemaOrExtension of schemas) { | ||
| // Check if this is a Standard Schema extension | ||
| if (typeof schemaOrExtension === 'object' && '$standardSchema' in schemaOrExtension && schemaOrExtension.$standardSchema) { | ||
| const standardSchema = schemaOrExtension.$standardSchema | ||
| // Store for validation later | ||
| const keys = Object.keys(schemaOrExtension).filter(key => key !== '$standardSchema') | ||
| for (const key of keys) { | ||
| moduleStandardSchemas[key] = standardSchema | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| }) | ||
|
|
||
| // Validate configuration against Standard Schemas if any | ||
| if (standardSchemas.length > 0 || Object.keys(moduleStandardSchemas).length > 0) { | ||
| // Validate app-level schemas | ||
| for (const standardSchema of standardSchemas) { | ||
| const validationResult = await validateWithStandardSchema(standardSchema, nuxt.options) | ||
| if (!validationResult.success && validationResult.issues) { | ||
| const errorMessages = validationResult.issues.map(issue => formatStandardSchemaIssue(issue)) | ||
| logger.error('❌ [Nuxt Schema] Standard Schema validation failed:') | ||
| for (const [index, message] of errorMessages.entries()) { | ||
| logger.error(` ${index + 1}. ${message}`) | ||
| } | ||
| throw new Error('Configuration validation failed') | ||
| } | ||
| } | ||
|
|
||
| // Validate module-level schemas | ||
| for (const [configPath, standardSchema] of Object.entries(moduleStandardSchemas)) { | ||
| const configValue = configPath.split('.').reduce((obj, key) => obj?.[key], nuxt.options) | ||
| if (configValue !== undefined) { | ||
| const validationResult = await validateWithStandardSchema(standardSchema, configValue) | ||
| if (!validationResult.success && validationResult.issues) { | ||
| const errorMessages = validationResult.issues.map(issue => formatStandardSchemaIssue(issue)) | ||
| logger.error(`❌ [Nuxt Schema] Standard Schema validation failed for "${configPath}":`) | ||
| for (const [index, message] of errorMessages.entries()) { | ||
| logger.error(` ${index + 1}. ${message}`) | ||
| } | ||
| throw new Error(`Configuration validation failed for "${configPath}"`) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| logger.success('✅ Standard Schema validation passed') | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix Standard Schema hook registration order
moduleStandardSchemas stays empty on the first run because the collector hook is registered after schema:extend has already been fired. As a result, module authors never see their Standard Schema validated (and the new helper is effectively a no-op until a subsequent rebuild). Register the collector before calling schema:extend, invoke it immediately for the current schemaDefs, and reuse the same function for future extensions.
- await nuxt.hooks.callHook('schema:extend', schemaDefs)
-
- // Process any Standard Schemas from modules via the new hook mechanism
- nuxt.hooks.addHooks({
- 'schema:extend': (schemas: (SchemaDefinition | StandardSchemaExtension)[]) => {
- for (const schemaOrExtension of schemas) {
- // Check if this is a Standard Schema extension
- if (typeof schemaOrExtension === 'object' && '$standardSchema' in schemaOrExtension && schemaOrExtension.$standardSchema) {
- const standardSchema = schemaOrExtension.$standardSchema
- // Store for validation later
- const keys = Object.keys(schemaOrExtension).filter(key => key !== '$standardSchema')
- for (const key of keys) {
- moduleStandardSchemas[key] = standardSchema
- }
- }
- }
- },
- })
+ const collectStandardSchemaExtensions = (schemas: (SchemaDefinition | StandardSchemaExtension)[]) => {
+ for (const schemaOrExtension of schemas) {
+ if (schemaOrExtension && typeof schemaOrExtension === 'object' && '$standardSchema' in schemaOrExtension && schemaOrExtension.$standardSchema) {
+ const standardSchema = schemaOrExtension.$standardSchema
+ for (const key of Object.keys(schemaOrExtension)) {
+ if (key !== '$standardSchema') {
+ moduleStandardSchemas[key] = standardSchema
+ }
+ }
+ }
+ }
+ }
+
+ collectStandardSchemaExtensions(schemaDefs)
+ nuxt.hooks.hook('schema:extend', collectStandardSchemaExtensions)
+ await nuxt.hooks.callHook('schema:extend', schemaDefs)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| nuxt.hooks.addHooks({ | |
| 'schema:extend': (schemas: (SchemaDefinition | StandardSchemaExtension)[]) => { | |
| for (const schemaOrExtension of schemas) { | |
| // Check if this is a Standard Schema extension | |
| if (typeof schemaOrExtension === 'object' && '$standardSchema' in schemaOrExtension && schemaOrExtension.$standardSchema) { | |
| const standardSchema = schemaOrExtension.$standardSchema | |
| // Store for validation later | |
| const keys = Object.keys(schemaOrExtension).filter(key => key !== '$standardSchema') | |
| for (const key of keys) { | |
| moduleStandardSchemas[key] = standardSchema | |
| } | |
| } | |
| } | |
| }, | |
| }) | |
| // Validate configuration against Standard Schemas if any | |
| if (standardSchemas.length > 0 || Object.keys(moduleStandardSchemas).length > 0) { | |
| // Validate app-level schemas | |
| for (const standardSchema of standardSchemas) { | |
| const validationResult = await validateWithStandardSchema(standardSchema, nuxt.options) | |
| if (!validationResult.success && validationResult.issues) { | |
| const errorMessages = validationResult.issues.map(issue => formatStandardSchemaIssue(issue)) | |
| logger.error('❌ [Nuxt Schema] Standard Schema validation failed:') | |
| for (const [index, message] of errorMessages.entries()) { | |
| logger.error(` ${index + 1}. ${message}`) | |
| } | |
| throw new Error('Configuration validation failed') | |
| } | |
| } | |
| // Validate module-level schemas | |
| for (const [configPath, standardSchema] of Object.entries(moduleStandardSchemas)) { | |
| const configValue = configPath.split('.').reduce((obj, key) => obj?.[key], nuxt.options) | |
| if (configValue !== undefined) { | |
| const validationResult = await validateWithStandardSchema(standardSchema, configValue) | |
| if (!validationResult.success && validationResult.issues) { | |
| const errorMessages = validationResult.issues.map(issue => formatStandardSchemaIssue(issue)) | |
| logger.error(`❌ [Nuxt Schema] Standard Schema validation failed for "${configPath}":`) | |
| for (const [index, message] of errorMessages.entries()) { | |
| logger.error(` ${index + 1}. ${message}`) | |
| } | |
| throw new Error(`Configuration validation failed for "${configPath}"`) | |
| } | |
| } | |
| } | |
| logger.success('✅ Standard Schema validation passed') | |
| } | |
| const collectStandardSchemaExtensions = (schemas: (SchemaDefinition | StandardSchemaExtension)[]) => { | |
| for (const schemaOrExtension of schemas) { | |
| if ( | |
| schemaOrExtension && | |
| typeof schemaOrExtension === 'object' && | |
| '$standardSchema' in schemaOrExtension && | |
| schemaOrExtension.$standardSchema | |
| ) { | |
| const standardSchema = schemaOrExtension.$standardSchema | |
| for (const key of Object.keys(schemaOrExtension)) { | |
| if (key !== '$standardSchema') { | |
| moduleStandardSchemas[key] = standardSchema | |
| } | |
| } | |
| } | |
| } | |
| } | |
| collectStandardSchemaExtensions(schemaDefs) | |
| nuxt.hooks.hook('schema:extend', collectStandardSchemaExtensions) | |
| await nuxt.hooks.callHook('schema:extend', schemaDefs) | |
| // Validate configuration against Standard Schemas if any | |
| if (standardSchemas.length > 0 || Object.keys(moduleStandardSchemas).length > 0) { | |
| // Validate app-level schemas | |
| for (const standardSchema of standardSchemas) { | |
| const validationResult = await validateWithStandardSchema(standardSchema, nuxt.options) | |
| if (!validationResult.success && validationResult.issues) { | |
| const errorMessages = validationResult.issues.map(issue => formatStandardSchemaIssue(issue)) | |
| logger.error('❌ [Nuxt Schema] Standard Schema validation failed:') | |
| for (const [index, message] of errorMessages.entries()) { | |
| logger.error(` ${index + 1}. ${message}`) | |
| } | |
| throw new Error('Configuration validation failed') | |
| } | |
| } | |
| // Validate module-level schemas | |
| for (const [configPath, standardSchema] of Object.entries(moduleStandardSchemas)) { | |
| const configValue = configPath.split('.').reduce((obj, key) => obj?.[key], nuxt.options) | |
| if (configValue !== undefined) { | |
| const validationResult = await validateWithStandardSchema(standardSchema, configValue) | |
| if (!validationResult.success && validationResult.issues) { | |
| const errorMessages = validationResult.issues.map(issue => formatStandardSchemaIssue(issue)) | |
| logger.error(`❌ [Nuxt Schema] Standard Schema validation failed for "${configPath}":`) | |
| for (const [index, message] of errorMessages.entries()) { | |
| logger.error(` ${index + 1}. ${message}`) | |
| } | |
| throw new Error(`Configuration validation failed for "${configPath}"`) | |
| } | |
| } | |
| } | |
| logger.success('✅ Standard Schema validation passed') | |
| } |
🤖 Prompt for AI Agents
packages/nuxt/src/core/schema.ts lines 149-197: the moduleStandardSchemas
collector is registered after the 'schema:extend' hook fires, so it misses the
initial schemaDefs; move registration so the collector function is defined and
invoked before calling nuxt.hooks.addHooks('schema:extend'), call the collector
immediately with the current schemaDefs to populate moduleStandardSchemas for
the first run, and keep a reference to that same collector function to register
as the hook handler for future 'schema:extend' events.
|
Closing to recreate from correct base branch |
244b6de to
1fa1f15
Compare
1fa1f15 to
714c1b8
Compare
|
Linter is not happy Should I remove the links? |
|
you can ignore that error. I need to investigate |
Fixes #33009
Corrected the documentation to reflect that Node.js only uses
exportsandmainfields for module resolution, not themodulefield (which is a bundler-only convention).Changes:
modulefieldmoduleis bundler-only with links to official Node.js docs