@geoql/oxlint-plugin-nuxt-doctor 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,7 +31,7 @@ Nuxt 4 only (the `app/` directory layout with `compatibilityVersion: 4`). Severi
31
31
 
32
32
  ## Architecture
33
33
 
34
- See [`docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md) for how the JS plugin co-loads with oxlint's native `vue` plugin and why script, template, and cross-file rules live in different passes.
34
+ See [`docs/SPEC.md`](../../docs/SPEC.md) §10 for how the JS plugin co-loads with oxlint's native `vue` plugin and why script, template, and cross-file rules live in different passes.
35
35
 
36
36
  ## License
37
37
 
package/dist/index.d.ts CHANGED
@@ -14,9 +14,19 @@ interface AstNode {
14
14
  loc?: SourceLocation;
15
15
  [key: string]: unknown;
16
16
  }
17
+ interface Fix {
18
+ range: [number, number];
19
+ text: string;
20
+ node?: AstNode;
21
+ }
22
+ interface Fixer {
23
+ replaceText: (node: AstNode, text: string) => Fix;
24
+ }
25
+ type FixFn = (fixer: Fixer) => Fix;
17
26
  interface ReportDescriptor {
18
27
  node: AstNode;
19
28
  message: string;
29
+ fix?: FixFn;
20
30
  }
21
31
  interface RuleContext {
22
32
  report: (descriptor: ReportDescriptor) => void;
@@ -26,8 +36,14 @@ interface RuleContext {
26
36
  capabilities?: Set<string>;
27
37
  }
28
38
  type RuleVisitor = (node: AstNode) => void;
39
+ interface RuleMeta {
40
+ name?: string;
41
+ fixable?: 'code' | 'whitespace';
42
+ }
29
43
  interface Rule {
44
+ meta?: RuleMeta;
30
45
  create: (context: RuleContext) => Record<string, RuleVisitor>;
46
+ fix?: (node: AstNode) => string | null;
31
47
  }
32
48
  interface Plugin {
33
49
  meta: {
package/dist/index.js CHANGED
@@ -1,6 +1,31 @@
1
1
  //#region src/define-rule.ts
2
2
  function defineRule(rule) {
3
- return rule;
3
+ const userFix = rule.fix;
4
+ if (!userFix) return rule;
5
+ return {
6
+ ...rule,
7
+ meta: {
8
+ ...rule.meta,
9
+ fixable: "code"
10
+ },
11
+ create(context) {
12
+ const wrapped = {
13
+ ...context,
14
+ report(descriptor) {
15
+ const replacement = userFix(descriptor.node);
16
+ if (replacement === null) {
17
+ context.report(descriptor);
18
+ return;
19
+ }
20
+ context.report({
21
+ ...descriptor,
22
+ fix: (fixer) => fixer.replaceText(descriptor.node, replacement)
23
+ });
24
+ }
25
+ };
26
+ return rule.create(wrapped);
27
+ }
28
+ };
4
29
  }
5
30
  //#endregion
6
31
  //#region src/rules/ai-slop/no-process-client-server.ts
@@ -10,20 +35,32 @@ const LEGACY_PROPS = new Set([
10
35
  "browser"
11
36
  ]);
12
37
  const MESSAGE$8 = `Use import.meta.client / import.meta.server / import.meta.browser instead of process.client / process.server / process.browser (Nuxt 4). See https://nuxt.com/docs/4.x/guide/concepts/auto-imports`;
13
- const noProcessClientServer = defineRule({ create(context) {
14
- return { MemberExpression(node) {
38
+ const noProcessClientServer = defineRule({
39
+ create(context) {
40
+ return { MemberExpression(node) {
41
+ const object = node.object;
42
+ if (object?.type !== "Identifier") return;
43
+ if (object.name !== "process") return;
44
+ const property = node.property;
45
+ if (property?.type !== "Identifier") return;
46
+ if (!LEGACY_PROPS.has(property.name)) return;
47
+ context.report({
48
+ node,
49
+ message: MESSAGE$8
50
+ });
51
+ } };
52
+ },
53
+ fix(node) {
15
54
  const object = node.object;
16
- if (object?.type !== "Identifier") return;
17
- if (object.name !== "process") return;
55
+ if (object?.type !== "Identifier") return null;
56
+ if (object.name !== "process") return null;
18
57
  const property = node.property;
19
- if (property?.type !== "Identifier") return;
20
- if (!LEGACY_PROPS.has(property.name)) return;
21
- context.report({
22
- node,
23
- message: MESSAGE$8
24
- });
25
- } };
26
- } });
58
+ if (property?.type !== "Identifier") return null;
59
+ const name = property.name;
60
+ if (!LEGACY_PROPS.has(name)) return null;
61
+ return `import.meta.${name}`;
62
+ }
63
+ });
27
64
  //#endregion
28
65
  //#region src/shared/nuxt-auto-imported-symbols.ts
29
66
  const NUXT_AUTO_IMPORTED = new Set([
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE"],"sources":["../src/define-rule.ts","../src/rules/ai-slop/no-process-client-server.ts","../src/shared/nuxt-auto-imported-symbols.ts","../src/rules/ai-slop/no-explicit-imports-of-auto-imported.ts","../src/rules/ai-slop/no-useState-for-server-data.ts","../src/rules/ai-slop/no-fetch-in-setup.ts","../src/rules/data-fetching/useAsyncData-key-required-in-loop.ts","../src/rules/server-routes/defineEventHandler-typed.ts","../src/rules/server-routes/validate-body-with-h3-v2.ts","../src/rules/server-routes/createError-on-failure.ts","../src/rules/hydration/no-document-in-setup.ts","../src/rules/hydration/clientOnly-for-browser-apis.ts","../src/plugin.ts","../src/index.ts"],"sourcesContent":["import type { Rule } from './rule-types.js';\n\nexport function defineRule(rule: Rule): Rule {\n return rule;\n}\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst LEGACY_PROPS = new Set(['client', 'server', 'browser']);\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/concepts/auto-imports';\nconst MESSAGE = `Use import.meta.client / import.meta.server / import.meta.browser instead of process.client / process.server / process.browser (Nuxt 4). See ${DOCS_URL}`;\n\nexport const noProcessClientServer = defineRule({\n create(context: RuleContext) {\n return {\n MemberExpression(node: AstNode) {\n const object = node.object as AstNode | undefined;\n if (object?.type !== 'Identifier') return;\n if ((object as AstNode & { name: string }).name !== 'process') return;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return;\n if (!LEGACY_PROPS.has(property.name as string)) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","export const NUXT_AUTO_IMPORTED: ReadonlySet<string> = new Set([\n // Vue reactivity auto-imported in Nuxt\n 'ref',\n 'shallowRef',\n 'computed',\n 'reactive',\n 'shallowReactive',\n 'readonly',\n 'shallowReadonly',\n 'toRef',\n 'toRefs',\n 'isRef',\n 'isReactive',\n 'isReadonly',\n 'isProxy',\n 'unref',\n 'triggerRef',\n 'customRef',\n 'markRaw',\n 'toRaw',\n 'watch',\n 'watchEffect',\n 'watchPostEffect',\n 'watchSyncEffect',\n 'effectScope',\n 'getCurrentScope',\n 'onScopeDispose',\n 'onMounted',\n 'onUpdated',\n 'onUnmounted',\n 'onBeforeMount',\n 'onBeforeUpdate',\n 'onBeforeUnmount',\n 'onErrorCaptured',\n 'onRenderTracked',\n 'onRenderTriggered',\n 'onActivated',\n 'onDeactivated',\n 'onServerPrefetch',\n 'provide',\n 'inject',\n 'hasInjectionContext',\n 'getCurrentInstance',\n 'nextTick',\n 'defineComponent',\n 'defineAsyncComponent',\n 'useTemplateRef',\n 'useId',\n 'useModel',\n // Nuxt auto-imports\n 'useRoute',\n 'useRouter',\n 'useFetch',\n 'useAsyncData',\n 'useState',\n 'useRuntimeConfig',\n 'useNuxtApp',\n 'navigateTo',\n 'definePageMeta',\n 'useSeoMeta',\n 'useHead',\n]);\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\nimport { NUXT_AUTO_IMPORTED } from '../../shared/nuxt-auto-imported-symbols.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/concepts/auto-imports';\nconst WHOLE_MESSAGE = `These symbols are auto-imported in Nuxt projects. Remove the import entirely. See ${DOCS_URL}`;\nconst SPECIFIER_MESSAGE = `This symbol is auto-imported in Nuxt projects. Remove it from the import — it is dead weight. See ${DOCS_URL}`;\n\nconst AUTO_IMPORT_SOURCES = new Set(['vue', '#imports', 'vue-router', '#app']);\n\nfunction isAutoImportedValueSpecifier(spec: AstNode): boolean {\n if (spec.importKind === 'type') return false;\n const imported = spec.imported as AstNode;\n return NUXT_AUTO_IMPORTED.has(imported.name as string);\n}\n\nexport const noExplicitImportsOfAutoImported = defineRule({\n create(context: RuleContext) {\n return {\n ImportDeclaration(node: AstNode) {\n if (node.importKind === 'type') return;\n const source = node.source as AstNode;\n if (!AUTO_IMPORT_SOURCES.has(source.value as string)) return;\n const specifiers = node.specifiers as AstNode[];\n const named = specifiers.filter((s) => s.type === 'ImportSpecifier');\n if (named.length === 0) return;\n const offending = named.filter(isAutoImportedValueSpecifier);\n if (offending.length === 0) return;\n if (\n offending.length === named.length &&\n specifiers.length === named.length\n ) {\n context.report({ node, message: WHOLE_MESSAGE });\n return;\n }\n for (const spec of offending) {\n context.report({ node: spec, message: SPECIFIER_MESSAGE });\n }\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `useState with a fetch/await initializer suggests useFetch or useAsyncData for automatic SSR hydration and request deduplication. See ${DOCS_URL}`;\n\nfunction containsFetchOrAwait(\n node: AstNode | undefined,\n visited: Set<unknown>,\n): boolean {\n if (!node || visited.has(node)) return false;\n visited.add(node);\n if (node.type === 'AwaitExpression') return true;\n if (node.type === 'CallExpression') {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type === 'Identifier') {\n const name = callee.name as string;\n if (name === '$fetch' || name === 'fetch') return true;\n }\n }\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'loc' || key === 'range') continue;\n const value = (node as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (child && typeof child === 'object' && 'type' in child) {\n if (containsFetchOrAwait(child as AstNode, visited)) return true;\n }\n }\n } else if (value && typeof value === 'object' && 'type' in value) {\n if (containsFetchOrAwait(value as AstNode, visited)) return true;\n }\n }\n return false;\n}\n\nexport const noUseStateForServerData = defineRule({\n create(context: RuleContext) {\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if ((callee as AstNode & { name: string }).name !== 'useState') return;\n const args = node.arguments as AstNode[];\n if (args.length < 2) return;\n const initFn = args[1];\n if (\n initFn.type !== 'ArrowFunctionExpression' &&\n initFn.type !== 'FunctionExpression'\n )\n return;\n if (!containsFetchOrAwait(initFn.body as AstNode, new Set())) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `Bare $fetch/fetch at the top level of <script setup> runs on both server and client without SSR deduplication. Use useFetch for automatic request deduplication and SSR hydration. See ${DOCS_URL}`;\n\nfunction isFetchCall(node: AstNode | undefined): boolean {\n if (!node || node.type !== 'CallExpression') return false;\n const callee = node.callee as AstNode | undefined;\n if (callee?.type === 'Identifier') {\n const name = callee.name as string;\n return name === '$fetch' || name === 'fetch';\n }\n return false;\n}\n\nexport const noFetchInSetup = defineRule({\n create(context: RuleContext) {\n const functionDepthStack: number[] = [];\n\n return {\n ArrowFunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'ArrowFunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionDeclaration() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionDeclaration:exit'() {\n functionDepthStack.pop();\n },\n CallExpression(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (!isFetchCall(node)) return;\n const parent = (node as Record<string, unknown>)['parent'] as\n | AstNode\n | undefined;\n if (parent?.type === 'AwaitExpression') return;\n context.report({ node, message: MESSAGE });\n },\n AwaitExpression(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (!isFetchCall(node.argument as AstNode | undefined)) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `useAsyncData/useFetch without an explicit string key inside a loop causes duplicate requests and cache fragmentation. Pass a unique string key as the first argument. See ${DOCS_URL}`;\n\nconst DATA_FETCHERS = new Set(['useAsyncData', 'useFetch']);\n\nfunction isMapCall(node: AstNode): boolean {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type === 'Identifier') return callee.name === 'map';\n if (callee?.type === 'MemberExpression') {\n const prop = (callee as AstNode & { property?: AstNode }).property as\n | AstNode\n | undefined;\n return (\n prop?.type === 'Identifier' &&\n (prop as AstNode & { name: string }).name === 'map'\n );\n }\n return false;\n}\n\nexport const useAsyncDataKeyRequiredInLoop = defineRule({\n create(context: RuleContext) {\n let loopDepth = 0;\n\n return {\n ForStatement() {\n loopDepth++;\n },\n 'ForStatement:exit'() {\n loopDepth--;\n },\n ForOfStatement() {\n loopDepth++;\n },\n 'ForOfStatement:exit'() {\n loopDepth--;\n },\n ForInStatement() {\n loopDepth++;\n },\n 'ForInStatement:exit'() {\n loopDepth--;\n },\n WhileStatement() {\n loopDepth++;\n },\n 'WhileStatement:exit'() {\n loopDepth--;\n },\n CallExpression(node: AstNode) {\n if (isMapCall(node)) {\n loopDepth++;\n return;\n }\n if (loopDepth === 0) return;\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (!DATA_FETCHERS.has(callee.name as string)) return;\n const args = node.arguments as AstNode[];\n if (args.length === 0) return;\n const firstArg = args[0];\n if (firstArg.type === 'Literal' && typeof firstArg.value === 'string')\n return;\n context.report({ node, message: MESSAGE });\n },\n 'CallExpression:exit'(node: AstNode) {\n if (isMapCall(node)) {\n loopDepth--;\n }\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://h3.unjs.io/guide/typed';\nconst MESSAGE = `defineEventHandler handler param event lacks a type annotation. Add a generic: defineEventHandler<H3Event>(...) or type the event parameter explicitly. See ${DOCS_URL}`;\n\nfunction isFunction(node: AstNode | undefined): boolean {\n return (\n node?.type === 'ArrowFunctionExpression' ||\n node?.type === 'FunctionExpression'\n );\n}\n\nexport const defineEventHandlerTyped = defineRule({\n create(context: RuleContext) {\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (\n (callee as AstNode & { name: string }).name !== 'defineEventHandler'\n )\n return;\n if (node.typeArguments) return;\n const args = node.arguments as AstNode[];\n if (args.length === 0) return;\n const handler = args[0];\n if (!isFunction(handler)) return;\n const params = (handler as AstNode & { params: AstNode[] }).params;\n if (!params || params.length === 0) return;\n const eventParam = params[0] as AstNode;\n if (eventParam.typeAnnotation) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `readBody() is the legacy H3 reader. In Nuxt 4 with h3 v2, use readValidatedBody to parse and validate the request body in one step. See ${DOCS_URL}`;\n\nexport const validateBodyWithH3V2 = defineRule({\n create(context: RuleContext) {\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if ((callee as AstNode & { name: string }).name !== 'readBody') return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://h3.unjs.io/guide/throw';\nconst MESSAGE = `throw new Error() leaks the call stack and exposes internal details. Use throw createError() from h3 for proper HTTP errors with no stack leak. See ${DOCS_URL}`;\n\nexport const createErrorOnFailure = defineRule({\n create(context: RuleContext) {\n let handlerDepth = 0;\n\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (\n (callee as AstNode & { name: string }).name !== 'defineEventHandler'\n )\n return;\n handlerDepth++;\n },\n 'CallExpression:exit'(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (\n (callee as AstNode & { name: string }).name !== 'defineEventHandler'\n )\n return;\n handlerDepth--;\n },\n ThrowStatement(node: AstNode) {\n if (handlerDepth === 0) return;\n const arg = node.argument as AstNode | undefined;\n if (!arg || arg.type !== 'NewExpression') return;\n const ctor = arg.callee as AstNode | undefined;\n if (ctor?.type !== 'Identifier') return;\n if ((ctor as AstNode & { name: string }).name !== 'Error') return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/components';\nconst MESSAGE = `Accessing document/window/navigator/localStorage at the top level of <script setup> causes a server-side crash (SSR). These browser globals are undefined on the server. Move access inside onMounted or guard with import.meta.client. See ${DOCS_URL}`;\n\nconst SSR_UNSAFE_GLOBALS = new Set([\n 'document',\n 'window',\n 'navigator',\n 'localStorage',\n 'sessionStorage',\n]);\n\nexport const noDocumentInSetup = defineRule({\n create(context: RuleContext) {\n const functionDepthStack: number[] = [];\n\n return {\n ArrowFunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'ArrowFunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionDeclaration() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionDeclaration:exit'() {\n functionDepthStack.pop();\n },\n Identifier(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (SSR_UNSAFE_GLOBALS.has(node.name as string)) {\n context.report({ node, message: MESSAGE });\n }\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/components';\nconst MESSAGE = `Accessing window./document./navigator./localStorage./sessionStorage. without an import.meta.client or process.client guard causes SSR failures. Wrap with if (import.meta.client) { ... } or move to onMounted. See ${DOCS_URL}`;\n\nconst BROWSER_GLOBALS = new Set([\n 'window',\n 'document',\n 'navigator',\n 'localStorage',\n 'sessionStorage',\n]);\n\nfunction isImportMetaClientGuard(node: AstNode | undefined): boolean {\n if (!node || node.type !== 'MemberExpression') return false;\n const obj = node.object as AstNode | undefined;\n if (obj?.type !== 'MetaProperty') return false;\n const meta = obj.meta as AstNode | undefined;\n const prop = obj.property as AstNode | undefined;\n if (meta?.type !== 'Identifier') return false;\n if ((meta as AstNode & { name: string }).name !== 'import') return false;\n if (prop?.type !== 'Identifier') return false;\n if ((prop as AstNode & { name: string }).name !== 'meta') return false;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return false;\n return (property as AstNode & { name: string }).name === 'client';\n}\n\nfunction isProcessClientGuard(node: AstNode | undefined): boolean {\n if (!node || node.type !== 'MemberExpression') return false;\n const obj = node.object as AstNode | undefined;\n if (obj?.type !== 'Identifier') return false;\n if ((obj as AstNode & { name: string }).name !== 'process') return false;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return false;\n return (property as AstNode & { name: string }).name === 'client';\n}\n\nexport const clientOnlyForBrowserApis = defineRule({\n create(context: RuleContext) {\n const functionDepthStack: number[] = [];\n let isGuarded = false;\n\n return {\n ArrowFunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'ArrowFunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionDeclaration() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionDeclaration:exit'() {\n functionDepthStack.pop();\n },\n IfStatement(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n const test = node.test as AstNode | undefined;\n if (isImportMetaClientGuard(test) || isProcessClientGuard(test)) {\n isGuarded = true;\n }\n },\n 'IfStatement:exit'(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n const test = node.test as AstNode | undefined;\n if (isImportMetaClientGuard(test) || isProcessClientGuard(test)) {\n isGuarded = false;\n }\n },\n MemberExpression(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (isGuarded) return;\n const obj = node.object as AstNode | undefined;\n if (obj?.type !== 'Identifier') return;\n if (!BROWSER_GLOBALS.has(obj.name as string)) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import type { Plugin } from './rule-types.js';\nimport { noProcessClientServer } from './rules/ai-slop/no-process-client-server.js';\nimport { noExplicitImportsOfAutoImported } from './rules/ai-slop/no-explicit-imports-of-auto-imported.js';\nimport { noUseStateForServerData } from './rules/ai-slop/no-useState-for-server-data.js';\nimport { noFetchInSetup } from './rules/ai-slop/no-fetch-in-setup.js';\nimport { useAsyncDataKeyRequiredInLoop } from './rules/data-fetching/useAsyncData-key-required-in-loop.js';\nimport { defineEventHandlerTyped } from './rules/server-routes/defineEventHandler-typed.js';\nimport { validateBodyWithH3V2 } from './rules/server-routes/validate-body-with-h3-v2.js';\nimport { createErrorOnFailure } from './rules/server-routes/createError-on-failure.js';\nimport { noDocumentInSetup } from './rules/hydration/no-document-in-setup.js';\nimport { clientOnlyForBrowserApis } from './rules/hydration/clientOnly-for-browser-apis.js';\n\nexport const plugin: Plugin = {\n meta: { name: 'nuxt-doctor' },\n rules: {\n 'ai-slop/no-process-client-server': noProcessClientServer,\n 'ai-slop/no-explicit-imports-of-auto-imported':\n noExplicitImportsOfAutoImported,\n 'ai-slop/no-useState-for-server-data': noUseStateForServerData,\n 'ai-slop/no-fetch-in-setup': noFetchInSetup,\n 'data-fetching/useAsyncData-key-required-in-loop':\n useAsyncDataKeyRequiredInLoop,\n 'server-routes/defineEventHandler-typed': defineEventHandlerTyped,\n 'server-routes/validate-body-with-h3-v2': validateBodyWithH3V2,\n 'server-routes/createError-on-failure': createErrorOnFailure,\n 'hydration/no-document-in-setup': noDocumentInSetup,\n 'hydration/clientOnly-for-browser-apis': clientOnlyForBrowserApis,\n },\n};\n","import { plugin } from './plugin.js';\n\nexport default plugin;\nexport { plugin };\nexport { NUXT_AUTO_IMPORTED } from './shared/nuxt-auto-imported-symbols.js';\nexport type { Rule, RuleContext } from './rule-types.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE","MESSAGE"],"sources":["../src/define-rule.ts","../src/rules/ai-slop/no-process-client-server.ts","../src/shared/nuxt-auto-imported-symbols.ts","../src/rules/ai-slop/no-explicit-imports-of-auto-imported.ts","../src/rules/ai-slop/no-useState-for-server-data.ts","../src/rules/ai-slop/no-fetch-in-setup.ts","../src/rules/data-fetching/useAsyncData-key-required-in-loop.ts","../src/rules/server-routes/defineEventHandler-typed.ts","../src/rules/server-routes/validate-body-with-h3-v2.ts","../src/rules/server-routes/createError-on-failure.ts","../src/rules/hydration/no-document-in-setup.ts","../src/rules/hydration/clientOnly-for-browser-apis.ts","../src/plugin.ts","../src/index.ts"],"sourcesContent":["import type { Rule, RuleContext } from './rule-types.js';\n\nexport function defineRule(rule: Rule): Rule {\n const userFix = rule.fix;\n if (!userFix) return rule;\n return {\n ...rule,\n meta: { ...rule.meta, fixable: 'code' },\n create(context: RuleContext) {\n const wrapped: RuleContext = {\n ...context,\n report(descriptor) {\n const replacement = userFix(descriptor.node);\n if (replacement === null) {\n context.report(descriptor);\n return;\n }\n context.report({\n ...descriptor,\n fix: (fixer) => fixer.replaceText(descriptor.node, replacement),\n });\n },\n };\n return rule.create(wrapped);\n },\n };\n}\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst LEGACY_PROPS = new Set(['client', 'server', 'browser']);\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/concepts/auto-imports';\nconst MESSAGE = `Use import.meta.client / import.meta.server / import.meta.browser instead of process.client / process.server / process.browser (Nuxt 4). See ${DOCS_URL}`;\n\nexport const noProcessClientServer = defineRule({\n create(context: RuleContext) {\n return {\n MemberExpression(node: AstNode) {\n const object = node.object as AstNode | undefined;\n if (object?.type !== 'Identifier') return;\n if ((object as AstNode & { name: string }).name !== 'process') return;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return;\n if (!LEGACY_PROPS.has(property.name as string)) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n fix(node: AstNode) {\n const object = node.object as AstNode | undefined;\n if (object?.type !== 'Identifier') return null;\n if ((object as AstNode & { name: string }).name !== 'process') return null;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return null;\n const name = property.name as string;\n if (!LEGACY_PROPS.has(name)) return null;\n return `import.meta.${name}`;\n },\n});\n","export const NUXT_AUTO_IMPORTED: ReadonlySet<string> = new Set([\n // Vue reactivity auto-imported in Nuxt\n 'ref',\n 'shallowRef',\n 'computed',\n 'reactive',\n 'shallowReactive',\n 'readonly',\n 'shallowReadonly',\n 'toRef',\n 'toRefs',\n 'isRef',\n 'isReactive',\n 'isReadonly',\n 'isProxy',\n 'unref',\n 'triggerRef',\n 'customRef',\n 'markRaw',\n 'toRaw',\n 'watch',\n 'watchEffect',\n 'watchPostEffect',\n 'watchSyncEffect',\n 'effectScope',\n 'getCurrentScope',\n 'onScopeDispose',\n 'onMounted',\n 'onUpdated',\n 'onUnmounted',\n 'onBeforeMount',\n 'onBeforeUpdate',\n 'onBeforeUnmount',\n 'onErrorCaptured',\n 'onRenderTracked',\n 'onRenderTriggered',\n 'onActivated',\n 'onDeactivated',\n 'onServerPrefetch',\n 'provide',\n 'inject',\n 'hasInjectionContext',\n 'getCurrentInstance',\n 'nextTick',\n 'defineComponent',\n 'defineAsyncComponent',\n 'useTemplateRef',\n 'useId',\n 'useModel',\n // Nuxt auto-imports\n 'useRoute',\n 'useRouter',\n 'useFetch',\n 'useAsyncData',\n 'useState',\n 'useRuntimeConfig',\n 'useNuxtApp',\n 'navigateTo',\n 'definePageMeta',\n 'useSeoMeta',\n 'useHead',\n]);\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\nimport { NUXT_AUTO_IMPORTED } from '../../shared/nuxt-auto-imported-symbols.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/concepts/auto-imports';\nconst WHOLE_MESSAGE = `These symbols are auto-imported in Nuxt projects. Remove the import entirely. See ${DOCS_URL}`;\nconst SPECIFIER_MESSAGE = `This symbol is auto-imported in Nuxt projects. Remove it from the import — it is dead weight. See ${DOCS_URL}`;\n\nconst AUTO_IMPORT_SOURCES = new Set(['vue', '#imports', 'vue-router', '#app']);\n\nfunction isAutoImportedValueSpecifier(spec: AstNode): boolean {\n if (spec.importKind === 'type') return false;\n const imported = spec.imported as AstNode;\n return NUXT_AUTO_IMPORTED.has(imported.name as string);\n}\n\nexport const noExplicitImportsOfAutoImported = defineRule({\n create(context: RuleContext) {\n return {\n ImportDeclaration(node: AstNode) {\n if (node.importKind === 'type') return;\n const source = node.source as AstNode;\n if (!AUTO_IMPORT_SOURCES.has(source.value as string)) return;\n const specifiers = node.specifiers as AstNode[];\n const named = specifiers.filter((s) => s.type === 'ImportSpecifier');\n if (named.length === 0) return;\n const offending = named.filter(isAutoImportedValueSpecifier);\n if (offending.length === 0) return;\n if (\n offending.length === named.length &&\n specifiers.length === named.length\n ) {\n context.report({ node, message: WHOLE_MESSAGE });\n return;\n }\n for (const spec of offending) {\n context.report({ node: spec, message: SPECIFIER_MESSAGE });\n }\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `useState with a fetch/await initializer suggests useFetch or useAsyncData for automatic SSR hydration and request deduplication. See ${DOCS_URL}`;\n\nfunction containsFetchOrAwait(\n node: AstNode | undefined,\n visited: Set<unknown>,\n): boolean {\n if (!node || visited.has(node)) return false;\n visited.add(node);\n if (node.type === 'AwaitExpression') return true;\n if (node.type === 'CallExpression') {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type === 'Identifier') {\n const name = callee.name as string;\n if (name === '$fetch' || name === 'fetch') return true;\n }\n }\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'loc' || key === 'range') continue;\n const value = (node as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (child && typeof child === 'object' && 'type' in child) {\n if (containsFetchOrAwait(child as AstNode, visited)) return true;\n }\n }\n } else if (value && typeof value === 'object' && 'type' in value) {\n if (containsFetchOrAwait(value as AstNode, visited)) return true;\n }\n }\n return false;\n}\n\nexport const noUseStateForServerData = defineRule({\n create(context: RuleContext) {\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if ((callee as AstNode & { name: string }).name !== 'useState') return;\n const args = node.arguments as AstNode[];\n if (args.length < 2) return;\n const initFn = args[1];\n if (\n initFn.type !== 'ArrowFunctionExpression' &&\n initFn.type !== 'FunctionExpression'\n )\n return;\n if (!containsFetchOrAwait(initFn.body as AstNode, new Set())) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `Bare $fetch/fetch at the top level of <script setup> runs on both server and client without SSR deduplication. Use useFetch for automatic request deduplication and SSR hydration. See ${DOCS_URL}`;\n\nfunction isFetchCall(node: AstNode | undefined): boolean {\n if (!node || node.type !== 'CallExpression') return false;\n const callee = node.callee as AstNode | undefined;\n if (callee?.type === 'Identifier') {\n const name = callee.name as string;\n return name === '$fetch' || name === 'fetch';\n }\n return false;\n}\n\nexport const noFetchInSetup = defineRule({\n create(context: RuleContext) {\n const functionDepthStack: number[] = [];\n\n return {\n ArrowFunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'ArrowFunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionDeclaration() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionDeclaration:exit'() {\n functionDepthStack.pop();\n },\n CallExpression(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (!isFetchCall(node)) return;\n const parent = (node as Record<string, unknown>)['parent'] as\n | AstNode\n | undefined;\n if (parent?.type === 'AwaitExpression') return;\n context.report({ node, message: MESSAGE });\n },\n AwaitExpression(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (!isFetchCall(node.argument as AstNode | undefined)) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `useAsyncData/useFetch without an explicit string key inside a loop causes duplicate requests and cache fragmentation. Pass a unique string key as the first argument. See ${DOCS_URL}`;\n\nconst DATA_FETCHERS = new Set(['useAsyncData', 'useFetch']);\n\nfunction isMapCall(node: AstNode): boolean {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type === 'Identifier') return callee.name === 'map';\n if (callee?.type === 'MemberExpression') {\n const prop = (callee as AstNode & { property?: AstNode }).property as\n | AstNode\n | undefined;\n return (\n prop?.type === 'Identifier' &&\n (prop as AstNode & { name: string }).name === 'map'\n );\n }\n return false;\n}\n\nexport const useAsyncDataKeyRequiredInLoop = defineRule({\n create(context: RuleContext) {\n let loopDepth = 0;\n\n return {\n ForStatement() {\n loopDepth++;\n },\n 'ForStatement:exit'() {\n loopDepth--;\n },\n ForOfStatement() {\n loopDepth++;\n },\n 'ForOfStatement:exit'() {\n loopDepth--;\n },\n ForInStatement() {\n loopDepth++;\n },\n 'ForInStatement:exit'() {\n loopDepth--;\n },\n WhileStatement() {\n loopDepth++;\n },\n 'WhileStatement:exit'() {\n loopDepth--;\n },\n CallExpression(node: AstNode) {\n if (isMapCall(node)) {\n loopDepth++;\n return;\n }\n if (loopDepth === 0) return;\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (!DATA_FETCHERS.has(callee.name as string)) return;\n const args = node.arguments as AstNode[];\n if (args.length === 0) return;\n const firstArg = args[0];\n if (firstArg.type === 'Literal' && typeof firstArg.value === 'string')\n return;\n context.report({ node, message: MESSAGE });\n },\n 'CallExpression:exit'(node: AstNode) {\n if (isMapCall(node)) {\n loopDepth--;\n }\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://h3.unjs.io/guide/typed';\nconst MESSAGE = `defineEventHandler handler param event lacks a type annotation. Add a generic: defineEventHandler<H3Event>(...) or type the event parameter explicitly. See ${DOCS_URL}`;\n\nfunction isFunction(node: AstNode | undefined): boolean {\n return (\n node?.type === 'ArrowFunctionExpression' ||\n node?.type === 'FunctionExpression'\n );\n}\n\nexport const defineEventHandlerTyped = defineRule({\n create(context: RuleContext) {\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (\n (callee as AstNode & { name: string }).name !== 'defineEventHandler'\n )\n return;\n if (node.typeArguments) return;\n const args = node.arguments as AstNode[];\n if (args.length === 0) return;\n const handler = args[0];\n if (!isFunction(handler)) return;\n const params = (handler as AstNode & { params: AstNode[] }).params;\n if (!params || params.length === 0) return;\n const eventParam = params[0] as AstNode;\n if (eventParam.typeAnnotation) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/data-fetching';\nconst MESSAGE = `readBody() is the legacy H3 reader. In Nuxt 4 with h3 v2, use readValidatedBody to parse and validate the request body in one step. See ${DOCS_URL}`;\n\nexport const validateBodyWithH3V2 = defineRule({\n create(context: RuleContext) {\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if ((callee as AstNode & { name: string }).name !== 'readBody') return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://h3.unjs.io/guide/throw';\nconst MESSAGE = `throw new Error() leaks the call stack and exposes internal details. Use throw createError() from h3 for proper HTTP errors with no stack leak. See ${DOCS_URL}`;\n\nexport const createErrorOnFailure = defineRule({\n create(context: RuleContext) {\n let handlerDepth = 0;\n\n return {\n CallExpression(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (\n (callee as AstNode & { name: string }).name !== 'defineEventHandler'\n )\n return;\n handlerDepth++;\n },\n 'CallExpression:exit'(node: AstNode) {\n const callee = node.callee as AstNode | undefined;\n if (callee?.type !== 'Identifier') return;\n if (\n (callee as AstNode & { name: string }).name !== 'defineEventHandler'\n )\n return;\n handlerDepth--;\n },\n ThrowStatement(node: AstNode) {\n if (handlerDepth === 0) return;\n const arg = node.argument as AstNode | undefined;\n if (!arg || arg.type !== 'NewExpression') return;\n const ctor = arg.callee as AstNode | undefined;\n if (ctor?.type !== 'Identifier') return;\n if ((ctor as AstNode & { name: string }).name !== 'Error') return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/components';\nconst MESSAGE = `Accessing document/window/navigator/localStorage at the top level of <script setup> causes a server-side crash (SSR). These browser globals are undefined on the server. Move access inside onMounted or guard with import.meta.client. See ${DOCS_URL}`;\n\nconst SSR_UNSAFE_GLOBALS = new Set([\n 'document',\n 'window',\n 'navigator',\n 'localStorage',\n 'sessionStorage',\n]);\n\nexport const noDocumentInSetup = defineRule({\n create(context: RuleContext) {\n const functionDepthStack: number[] = [];\n\n return {\n ArrowFunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'ArrowFunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionDeclaration() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionDeclaration:exit'() {\n functionDepthStack.pop();\n },\n Identifier(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (SSR_UNSAFE_GLOBALS.has(node.name as string)) {\n context.report({ node, message: MESSAGE });\n }\n },\n };\n },\n});\n","import { defineRule } from '../../define-rule.js';\nimport type { AstNode, RuleContext } from '../../rule-types.js';\n\nconst DOCS_URL = 'https://nuxt.com/docs/4.x/guide/components';\nconst MESSAGE = `Accessing window./document./navigator./localStorage./sessionStorage. without an import.meta.client or process.client guard causes SSR failures. Wrap with if (import.meta.client) { ... } or move to onMounted. See ${DOCS_URL}`;\n\nconst BROWSER_GLOBALS = new Set([\n 'window',\n 'document',\n 'navigator',\n 'localStorage',\n 'sessionStorage',\n]);\n\nfunction isImportMetaClientGuard(node: AstNode | undefined): boolean {\n if (!node || node.type !== 'MemberExpression') return false;\n const obj = node.object as AstNode | undefined;\n if (obj?.type !== 'MetaProperty') return false;\n const meta = obj.meta as AstNode | undefined;\n const prop = obj.property as AstNode | undefined;\n if (meta?.type !== 'Identifier') return false;\n if ((meta as AstNode & { name: string }).name !== 'import') return false;\n if (prop?.type !== 'Identifier') return false;\n if ((prop as AstNode & { name: string }).name !== 'meta') return false;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return false;\n return (property as AstNode & { name: string }).name === 'client';\n}\n\nfunction isProcessClientGuard(node: AstNode | undefined): boolean {\n if (!node || node.type !== 'MemberExpression') return false;\n const obj = node.object as AstNode | undefined;\n if (obj?.type !== 'Identifier') return false;\n if ((obj as AstNode & { name: string }).name !== 'process') return false;\n const property = node.property as AstNode | undefined;\n if (property?.type !== 'Identifier') return false;\n return (property as AstNode & { name: string }).name === 'client';\n}\n\nexport const clientOnlyForBrowserApis = defineRule({\n create(context: RuleContext) {\n const functionDepthStack: number[] = [];\n let isGuarded = false;\n\n return {\n ArrowFunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'ArrowFunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionExpression() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionExpression:exit'() {\n functionDepthStack.pop();\n },\n FunctionDeclaration() {\n functionDepthStack.push(\n functionDepthStack.length > 0\n ? functionDepthStack[functionDepthStack.length - 1]! + 1\n : 1,\n );\n },\n 'FunctionDeclaration:exit'() {\n functionDepthStack.pop();\n },\n IfStatement(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n const test = node.test as AstNode | undefined;\n if (isImportMetaClientGuard(test) || isProcessClientGuard(test)) {\n isGuarded = true;\n }\n },\n 'IfStatement:exit'(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n const test = node.test as AstNode | undefined;\n if (isImportMetaClientGuard(test) || isProcessClientGuard(test)) {\n isGuarded = false;\n }\n },\n MemberExpression(node: AstNode) {\n if (functionDepthStack.length > 0) return;\n if (isGuarded) return;\n const obj = node.object as AstNode | undefined;\n if (obj?.type !== 'Identifier') return;\n if (!BROWSER_GLOBALS.has(obj.name as string)) return;\n context.report({ node, message: MESSAGE });\n },\n };\n },\n});\n","import type { Plugin } from './rule-types.js';\nimport { noProcessClientServer } from './rules/ai-slop/no-process-client-server.js';\nimport { noExplicitImportsOfAutoImported } from './rules/ai-slop/no-explicit-imports-of-auto-imported.js';\nimport { noUseStateForServerData } from './rules/ai-slop/no-useState-for-server-data.js';\nimport { noFetchInSetup } from './rules/ai-slop/no-fetch-in-setup.js';\nimport { useAsyncDataKeyRequiredInLoop } from './rules/data-fetching/useAsyncData-key-required-in-loop.js';\nimport { defineEventHandlerTyped } from './rules/server-routes/defineEventHandler-typed.js';\nimport { validateBodyWithH3V2 } from './rules/server-routes/validate-body-with-h3-v2.js';\nimport { createErrorOnFailure } from './rules/server-routes/createError-on-failure.js';\nimport { noDocumentInSetup } from './rules/hydration/no-document-in-setup.js';\nimport { clientOnlyForBrowserApis } from './rules/hydration/clientOnly-for-browser-apis.js';\n\nexport const plugin: Plugin = {\n meta: { name: 'nuxt-doctor' },\n rules: {\n 'ai-slop/no-process-client-server': noProcessClientServer,\n 'ai-slop/no-explicit-imports-of-auto-imported':\n noExplicitImportsOfAutoImported,\n 'ai-slop/no-useState-for-server-data': noUseStateForServerData,\n 'ai-slop/no-fetch-in-setup': noFetchInSetup,\n 'data-fetching/useAsyncData-key-required-in-loop':\n useAsyncDataKeyRequiredInLoop,\n 'server-routes/defineEventHandler-typed': defineEventHandlerTyped,\n 'server-routes/validate-body-with-h3-v2': validateBodyWithH3V2,\n 'server-routes/createError-on-failure': createErrorOnFailure,\n 'hydration/no-document-in-setup': noDocumentInSetup,\n 'hydration/clientOnly-for-browser-apis': clientOnlyForBrowserApis,\n },\n};\n","import { plugin } from './plugin.js';\n\nexport default plugin;\nexport { plugin };\nexport { NUXT_AUTO_IMPORTED } from './shared/nuxt-auto-imported-symbols.js';\nexport type { Rule, RuleContext } from './rule-types.js';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geoql/oxlint-plugin-nuxt-doctor",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "description": "oxlint JS plugin for Nuxt 4 anti-patterns and AI-slop detection. Pairs with oxlint's built-in vue plugin via jsPlugins. TypeScript, ESM.",
6
6
  "keywords": [