cvx-kit 0.1.13 → 0.1.14
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/AGENTS.md +47 -0
- package/CHANGELOG.md +20 -0
- package/README.md +144 -0
- package/dist/auth.d.mts +3 -1
- package/dist/auth.mjs +1 -1
- package/dist/auth.mjs.map +1 -1
- package/dist/index.d.mts +5 -2
- package/dist/index.mjs +1 -1
- package/dist/modules/effect/api-zod.d.mts +1 -1
- package/dist/oxlint/architecture.d.mts +2 -0
- package/dist/oxlint/architecture.mjs +1 -1
- package/dist/oxlint/architecture.mjs.map +1 -1
- package/dist/oxlint/ast.d.mts +10 -1
- package/dist/oxlint/ast.mjs +1 -1
- package/dist/oxlint/ast.mjs.map +1 -1
- package/dist/oxlint.d.mts +1 -1
- package/dist/oxlint.mjs +1 -1
- package/dist/oxlint.mjs.map +1 -1
- package/dist/querying/cursors.d.mts +45 -0
- package/dist/querying/cursors.mjs +2 -0
- package/dist/querying/cursors.mjs.map +1 -0
- package/dist/querying/execution.d.mts +30 -0
- package/dist/querying/execution.mjs +2 -0
- package/dist/querying/execution.mjs.map +1 -0
- package/dist/querying/filters.d.mts +136 -0
- package/dist/querying/filters.mjs +2 -0
- package/dist/querying/filters.mjs.map +1 -0
- package/dist/querying/planner.d.mts +50 -0
- package/dist/querying/planner.mjs +2 -0
- package/dist/querying/planner.mjs.map +1 -0
- package/dist/querying/relationships.d.mts +41 -0
- package/dist/querying/relationships.mjs +2 -0
- package/dist/querying/relationships.mjs.map +1 -0
- package/dist/querying/security.d.mts +107 -0
- package/dist/querying/security.mjs +2 -0
- package/dist/querying/security.mjs.map +1 -0
- package/dist/querying.d.mts +39 -0
- package/dist/querying.mjs +2 -0
- package/dist/querying.mjs.map +1 -0
- package/dist/relations-public.d.mts +2 -0
- package/dist/relations-public.mjs +1 -0
- package/dist/relations.d.mts +155 -0
- package/dist/relations.mjs +2 -0
- package/dist/relations.mjs.map +1 -0
- package/dist/zod-convex.d.mts +10 -0
- package/dist/zod-convex.mjs +2 -0
- package/dist/zod-convex.mjs.map +1 -0
- package/dist/zod-registration.d.mts +10 -0
- package/dist/zod-registration.mjs +2 -0
- package/dist/zod-registration.mjs.map +1 -0
- package/dist/zod-table.d.mts +63 -8
- package/dist/zod-table.mjs +1 -1
- package/dist/zod-table.mjs.map +1 -1
- package/docs/conventions.md +12 -0
- package/docs/llms.md +15 -5
- package/docs/oxlint.md +129 -25
- package/docs/querying.md +293 -0
- package/docs/zod-table.md +93 -13
- package/package.json +11 -1
- package/scripts/owned-process.mjs +140 -0
- package/scripts/owned-process.test.mjs +107 -0
- package/scripts/smoke-packed-querying.mjs +296 -0
- package/scripts/test-packed-effect.mjs +8 -1
- package/scripts/test-packed-oxlint.mjs +5 -1
- package/scripts/test-packed-querying.mjs +185 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"architecture.mjs","names":["inspectArchitecture","requestedRoot","resolve","options","root","existsSync","realpathSync","diagnostics","files","sourceFiles","required","tested","graph","dependencies","resolver","createResolver","file","filename","parsed","parseSync","readFileSync","testFile","dirname","hasRunnableTest","executable","owner","moduleOwner","targets","source","runtimeImports","target","resolveImport","targetFile","relative","sep","targetOwner","edges","directory","sharedOwnership","cycle","cycles","a","b","ResolverFactory","architectureAnchor","allowed","scan","entry","readdirSync","path","program","declaration","statement","names","item","specifier","calls","Visitor","node","skipped","parts","testCallee","part","argument","property","skip","name","base","imports","s","completed","stack","found","visit","index","dependency","consumers","visited","owners","next"],"sources":["../../src/oxlint/architecture.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport { parseSync, Visitor, type Program, type Node, type CallExpression } from 'oxc-parser'\nimport { ResolverFactory } from 'oxc-resolver'\n\nexport interface ArchitectureOptions {\n\tcwd?: string\n\tconvexDir?: string\n}\nexport interface ArchitectureDiagnostic {\n\tcode:\n\t\t| 'missing-root'\n\t\t| 'root-directory'\n\t\t| 'tests'\n\t\t| 'test-location'\n\t\t| 'parse'\n\t\t| 'cycle'\n\t\t| 'symlink'\n\t\t| 'domain-entry'\n\t\t| 'shared-owner'\n\tfile: string\n\tmessage: string\n}\n\n/** Full-project checks, independent of the consumer's test runner. No persistent cache. */\nexport function inspectArchitecture(options: ArchitectureOptions = {}): ArchitectureDiagnostic[] {\n\tconst requestedRoot = resolve(options.cwd ?? process.cwd(), options.convexDir ?? 'convex')\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst diagnostics: ArchitectureDiagnostic[] = []\n\tif (!existsSync(root))\n\t\treturn [\n\t\t\t{ code: 'missing-root', file: '.', message: `Convex directory does not exist: ${root}` },\n\t\t]\n\tconst files = sourceFiles(root, diagnostics)\n\tconst required = new Set<string>()\n\tconst tested = new Set<string>()\n\tconst graph = new Map<string, Set<string>>()\n\tconst dependencies = new Map<string, Set<string>>()\n\tconst resolver = createResolver()\n\tfor (const file of files) {\n\t\tconst filename = resolve(root, file)\n\t\tconst parsed = parseSync(filename, readFileSync(filename, 'utf8'))\n\t\tif (parsed.errors.length) {\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'parse',\n\t\t\t\tfile,\n\t\t\t\tmessage: `Cannot validate ${file}: ${parsed.errors[0].message}`,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif (testFile(file)) {\n\t\t\tif (!file.includes('__tests__/'))\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tcode: 'test-location',\n\t\t\t\t\tfile,\n\t\t\t\t\tmessage: 'Place tests in a sibling __tests__/ directory.',\n\t\t\t\t})\n\t\t\telse if (dirname(file).endsWith('__tests__') && hasRunnableTest(parsed.program))\n\t\t\t\ttested.add(dirname(dirname(file)))\n\t\t\tcontinue\n\t\t}\n\t\tif (file.split('/').includes('__tests__')) continue\n\t\tif (/^domain\\/[^/]+$/.test(file) && file !== 'domain/table.ts')\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'domain-entry',\n\t\t\t\tfile,\n\t\t\t\tmessage:\n\t\t\t\t\t'Domain source belongs in domain/<module>/ or domain/shared/. Only domain/table.ts assembles module tables.',\n\t\t\t})\n\t\tif (executable(parsed.program) && file !== 'domain/table.ts') required.add(dirname(file))\n\t\tconst owner = moduleOwner(file) ?? ''\n\t\tconst targets = new Set<string>()\n\t\tdependencies.set(file, targets)\n\t\tfor (const source of runtimeImports(parsed.program)) {\n\t\t\tconst target = resolveImport(resolver, filename, source)\n\t\t\tif (!target) continue\n\t\t\tconst targetFile = relative(root, target).split(sep).join('/')\n\t\t\ttargets.add(targetFile)\n\t\t\tconst targetOwner = moduleOwner(targetFile)\n\t\t\tif (owner && targetOwner && owner !== targetOwner) {\n\t\t\t\tconst edges = graph.get(owner) ?? new Set<string>()\n\t\t\t\tgraph.set(owner, edges)\n\t\t\t\tedges.add(targetOwner)\n\t\t\t}\n\t\t}\n\t}\n\tfor (const directory of required) {\n\t\tif (!tested.has(directory))\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'tests',\n\t\t\t\tfile: directory,\n\t\t\t\tmessage: `${directory}/__tests__/ must contain a .test or .spec file with a nonempty, non-skipped test. Parent or child suites do not count.`,\n\t\t\t})\n\t}\n\tdiagnostics.push(...sharedOwnership(dependencies))\n\tfor (const cycle of cycles(graph))\n\t\tdiagnostics.push({\n\t\t\tcode: 'cycle',\n\t\t\tfile: cycle[0],\n\t\t\tmessage: `Module dependency cycle: ${cycle.join(' → ')}.`,\n\t\t})\n\treturn diagnostics.sort((a, b) => a.file.localeCompare(b.file) || a.code.localeCompare(b.code))\n}\n\nexport function createResolver() {\n\treturn new ResolverFactory({\n\t\ttsconfig: 'auto',\n\t\textensions: ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs', '.json'],\n\t\textensionAlias: {\n\t\t\t'.js': ['.ts', '.tsx', '.js'],\n\t\t\t'.mjs': ['.mts', '.mjs'],\n\t\t\t'.cjs': ['.cts', '.cjs'],\n\t\t},\n\t\tconditionNames: ['types', 'import', 'node', 'default'],\n\t\tsymlinks: true,\n\t})\n}\n\nexport function resolveImport(resolver: ResolverFactory, filename: string, source: string) {\n\tconst found = resolver.resolveFileSync(filename, source).path\n\tif (found) return found\n\t// Keep path checks useful in unsaved/editor fixtures and before Convex codegen.\n\treturn source.startsWith('.') ? resolve(dirname(filename), source) : null\n}\n\n/** The lint rule runs the project scan on one deterministic source file. */\nexport function architectureAnchor(root: string) {\n\tif (!existsSync(root)) return null\n\tif (existsSync(resolve(root, 'convex.config.ts')))\n\t\treturn realpathSync(resolve(root, 'convex.config.ts'))\n\troot = realpathSync(root)\n\tfor (const file of sourceFiles(root, []))\n\t\tif (!file.includes('__tests__/') && !testFile(file)) return resolve(root, file)\n\treturn null\n}\n\nfunction* sourceFiles(root: string, diagnostics: ArchitectureDiagnostic[]): Generator<string> {\n\tconst allowed = new Set([\n\t\t'_generated',\n\t\t'__tests__',\n\t\t'api',\n\t\t'domain',\n\t\t'application',\n\t\t'migrations',\n\t\t'components',\n\t])\n\tfunction* scan(directory: string): Generator<string> {\n\t\tfor (const entry of readdirSync(directory, { withFileTypes: true }).sort((a, b) =>\n\t\t\ta.name.localeCompare(b.name),\n\t\t)) {\n\t\t\tconst path = resolve(directory, entry.name)\n\t\t\tconst file = relative(root, path).split(sep).join('/')\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tcode: 'symlink',\n\t\t\t\t\tfile,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'Keep application source inside its owning directory; symlinked files and folders are not allowed.',\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (directory === root && !allowed.has(entry.name))\n\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\tcode: 'root-directory',\n\t\t\t\t\t\tfile,\n\t\t\t\t\t\tmessage: `Root folder ${entry.name}/ is not allowed. Use api/, domain/, application/, migrations/, components/, __tests__/, or _generated/.`,\n\t\t\t\t\t})\n\t\t\t\tif (\n\t\t\t\t\tentry.name !== '_generated' &&\n\t\t\t\t\tentry.name !== 'node_modules' &&\n\t\t\t\t\t!entry.name.startsWith('.')\n\t\t\t\t)\n\t\t\t\t\tyield* scan(path)\n\t\t\t} else if (/\\.[cm]?[jt]sx?$/.test(entry.name) && !/\\.d\\.[cm]?ts$/.test(entry.name)) yield file\n\t\t}\n\t}\n\tyield* scan(root)\n}\n\nfunction testFile(file: string) {\n\treturn /\\.(?:test|spec)\\.[cm]?[jt]sx?$/.test(file)\n}\n\nfunction executable(program: Program) {\n\treturn program.body.some((statement) => {\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration && 'declare' in declaration && declaration.declare) return false\n\t\tif (statement.type === 'ImportDeclaration' || statement.type === 'EmptyStatement') return false\n\t\tif (statement.type === 'ExportNamedDeclaration') {\n\t\t\tif (statement.exportKind === 'type' || !statement.declaration) return false\n\t\t\treturn !['TSInterfaceDeclaration', 'TSTypeAliasDeclaration', 'TSDeclareFunction'].includes(\n\t\t\t\tstatement.declaration.type,\n\t\t\t)\n\t\t}\n\t\treturn ![\n\t\t\t'TSInterfaceDeclaration',\n\t\t\t'TSTypeAliasDeclaration',\n\t\t\t'TSDeclareFunction',\n\t\t\t'ExportAllDeclaration',\n\t\t].includes(statement.type)\n\t})\n}\n\nfunction hasRunnableTest(program: Program) {\n\tconst names = new Map([\n\t\t['test', 'test'],\n\t\t['it', 'it'],\n\t\t['describe', 'describe'],\n\t\t['suite', 'suite'],\n\t])\n\tfor (const statement of program.body) {\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration?.type === 'FunctionDeclaration' && declaration.id)\n\t\t\tnames.delete(declaration.id.name)\n\t\tif (declaration?.type === 'VariableDeclaration')\n\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\tif (item.id.type === 'Identifier') names.delete(item.id.name)\n\t\t\t}\n\t\tif (statement.type !== 'ImportDeclaration') continue\n\t\tfor (const specifier of statement.specifiers) {\n\t\t\tnames.delete(specifier.local.name)\n\t\t\tif (\n\t\t\t\t!['vitest', 'vite-plus/test', 'bun:test', 'node:test', '@jest/globals'].includes(\n\t\t\t\t\tstatement.source.value,\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tcontinue\n\t\t\tif (specifier.type === 'ImportNamespaceSpecifier') names.set(specifier.local.name, '*')\n\t\t\telse if (specifier.type === 'ImportDefaultSpecifier') names.set(specifier.local.name, 'test')\n\t\t\telse if (specifier.imported.type === 'Identifier')\n\t\t\t\tnames.set(specifier.local.name, specifier.imported.name)\n\t\t}\n\t}\n\tconst calls: CallExpression[] = []\n\tnew Visitor({\n\t\tCallExpression(node) {\n\t\t\tcalls.push(node)\n\t\t},\n\t}).visit(program)\n\tconst skipped = calls.filter((node) => {\n\t\tconst parts = testCallee(node.callee, names)\n\t\treturn (\n\t\t\t['test', 'it', 'describe', 'suite'].includes(parts[0]) &&\n\t\t\t(parts.some((part) => ['skip', 'todo', 'skipIf', 'runIf'].includes(part)) ||\n\t\t\t\tnode.arguments.some(\n\t\t\t\t\t(argument) =>\n\t\t\t\t\t\targument.type === 'ObjectExpression' &&\n\t\t\t\t\t\targument.properties.some(\n\t\t\t\t\t\t\t(property) =>\n\t\t\t\t\t\t\t\tproperty.type === 'Property' &&\n\t\t\t\t\t\t\t\t['skip', 'todo'].includes(\n\t\t\t\t\t\t\t\t\tproperty.key.type === 'Identifier'\n\t\t\t\t\t\t\t\t\t\t? property.key.name\n\t\t\t\t\t\t\t\t\t\t: property.key.type === 'Literal'\n\t\t\t\t\t\t\t\t\t\t\t? String(property.key.value)\n\t\t\t\t\t\t\t\t\t\t\t: '',\n\t\t\t\t\t\t\t\t) &&\n\t\t\t\t\t\t\t\t!(property.value.type === 'Literal' && property.value.value === false),\n\t\t\t\t\t\t),\n\t\t\t\t))\n\t\t)\n\t})\n\treturn calls.some((node) => {\n\t\tconst parts = testCallee(node.callee, names)\n\t\tif (\n\t\t\t!['test', 'it'].includes(parts[0]) ||\n\t\t\tskipped.some((skip) => node.start >= skip.start && node.end <= skip.end)\n\t\t)\n\t\t\treturn false\n\t\t// each(...) is a factory; only the outer call has the test callback.\n\t\treturn node.arguments.some(\n\t\t\t(argument) =>\n\t\t\t\t(argument.type === 'ArrowFunctionExpression' || argument.type === 'FunctionExpression') &&\n\t\t\t\targument.body &&\n\t\t\t\t(argument.body.type !== 'BlockStatement' ||\n\t\t\t\t\targument.body.body.some((statement) => statement.type !== 'EmptyStatement')),\n\t\t)\n\t})\n}\n\nfunction testCallee(node: Node, names: Map<string, string>): string[] {\n\tif (node.type === 'Identifier') {\n\t\tconst name = names.get(node.name)\n\t\treturn name ? [name] : []\n\t}\n\tif (node.type === 'CallExpression') return testCallee(node.callee, names)\n\tif (node.type === 'MemberExpression') {\n\t\tconst base = testCallee(node.object, names)\n\t\tconst property =\n\t\t\t!node.computed && node.property.type === 'Identifier'\n\t\t\t\t? node.property.name\n\t\t\t\t: node.property.type === 'Literal'\n\t\t\t\t\t? String(node.property.value)\n\t\t\t\t\t: ''\n\t\tif (!base.length || !property) return []\n\t\treturn base[0] === '*' ? [property] : [...base, property]\n\t}\n\treturn []\n}\n\nfunction runtimeImports(program: Program) {\n\tconst imports: string[] = []\n\tnew Visitor({\n\t\tImportDeclaration(node) {\n\t\t\tif (\n\t\t\t\tnode.importKind !== 'type' &&\n\t\t\t\t(node.specifiers.length === 0 ||\n\t\t\t\t\tnode.specifiers.some((s) => s.type !== 'ImportSpecifier' || s.importKind !== 'type'))\n\t\t\t)\n\t\t\t\timports.push(node.source.value)\n\t\t},\n\t\tExportNamedDeclaration(node) {\n\t\t\tif (\n\t\t\t\tnode.source &&\n\t\t\t\tnode.exportKind !== 'type' &&\n\t\t\t\tnode.specifiers.some((specifier) => specifier.exportKind !== 'type')\n\t\t\t)\n\t\t\t\timports.push(node.source.value)\n\t\t},\n\t\tExportAllDeclaration(node) {\n\t\t\tif (node.exportKind !== 'type') imports.push(node.source.value)\n\t\t},\n\t\tImportExpression(node) {\n\t\t\tif (node.source.type === 'Literal' && String(node.source.value) === node.source.value)\n\t\t\t\timports.push(String(node.source.value))\n\t\t},\n\t}).visit(program)\n\treturn imports\n}\n\nfunction moduleOwner(file: string) {\n\tconst parts = file.split('/')\n\treturn parts[0] === 'domain' && parts.length >= 3 && parts[1] !== '__tests__'\n\t\t? `domain/${parts[1]}`\n\t\t: null\n}\n\nfunction cycles(graph: Map<string, Set<string>>) {\n\tconst completed = new Set<string>()\n\tconst stack: string[] = []\n\tconst found: string[][] = []\n\tfunction visit(owner: string) {\n\t\tconst index = stack.indexOf(owner)\n\t\tif (index >= 0) {\n\t\t\tfound.push([...stack.slice(index), owner])\n\t\t\treturn\n\t\t}\n\t\tif (completed.has(owner)) return\n\t\tstack.push(owner)\n\t\tfor (const dependency of graph.get(owner) ?? []) visit(dependency)\n\t\tstack.pop()\n\t\tcompleted.add(owner)\n\t}\n\tfor (const owner of graph.keys()) visit(owner)\n\treturn found\n}\n\nfunction sharedOwnership(dependencies: Map<string, Set<string>>): ArchitectureDiagnostic[] {\n\tconst consumers = new Map<string, Set<string>>()\n\tfor (const [file, targets] of dependencies) {\n\t\tconst owner = moduleOwner(file) ?? ''\n\t\tif (!owner || owner === 'domain/shared') continue\n\t\tconst visited = new Set<string>()\n\t\tfunction visit(target: string) {\n\t\t\tif (!target.startsWith('domain/shared/') || visited.has(target)) return\n\t\t\tvisited.add(target)\n\t\t\tconst owners = consumers.get(target) ?? new Set<string>()\n\t\t\towners.add(owner)\n\t\t\tconsumers.set(target, owners)\n\t\t\tfor (const next of dependencies.get(target) ?? []) visit(next)\n\t\t}\n\t\tfor (const target of targets) visit(target)\n\t}\n\tconst diagnostics: ArchitectureDiagnostic[] = []\n\tfor (const [file, owners] of consumers) {\n\t\tif (owners.size === 1)\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'shared-owner',\n\t\t\t\tfile,\n\t\t\t\tmessage: `This shared implementation is used only by ${[...owners][0]}. Move it into that module until another module needs it.`,\n\t\t\t})\n\t}\n\treturn diagnostics\n}\n"],"mappings":"qQAyBA,SAAgBA,EAAoB,EAA+B,CAAC,EAA6B,CAChG,IAAMC,EAAgBC,EAAQC,EAAQ,KAAO,QAAQ,IAAI,EAAGA,EAAQ,WAAa,QAAQ,EACnFC,EAAOC,EAAWJ,CAAa,EAAIK,EAAaL,CAAa,EAAIA,EACjEM,EAAwC,CAAC,EAC/C,GAAI,CAACF,EAAWD,CAAI,EACnB,MAAO,CACN,CAAE,KAAM,eAAgB,KAAM,IAAK,QAAS,oCAAoCA,GAAO,CACxF,EACD,IAAMI,EAAQC,EAAYL,EAAMG,CAAW,EACrCG,kBAAW,IAAI,IACfC,kBAAS,IAAI,IACbC,kBAAQ,IAAI,IACZC,kBAAe,IAAI,IACnBC,EAAWC,EAAe,EAChC,IAAK,IAAMC,KAAQR,EAAO,CACzB,IAAMS,EAAWf,EAAQE,EAAMY,CAAI,EAC7BE,EAASC,EAAUF,EAAUG,EAAaH,EAAU,MAAM,CAAC,EACjE,GAAIC,EAAO,OAAO,OAAQ,CACzBX,EAAY,KAAK,CAChB,KAAM,QACN,OACA,QAAS,mBAAmBS,EAAK,IAAIE,EAAO,OAAO,EAAE,CAAC,SACvD,CAAC,EACD,QACD,CACA,GAAIG,EAASL,CAAI,EAAG,CACdA,EAAK,SAAS,YAAY,EAMtBM,EAAQN,CAAI,CAAC,CAAC,SAAS,WAAW,GAAKO,EAAgBL,EAAO,OAAO,GAC7EP,EAAO,IAAIW,EAAQA,EAAQN,CAAI,CAAC,CAAC,EANjCT,EAAY,KAAK,CAChB,KAAM,gBACN,OACA,QAAS,gDACV,CAAC,EAGF,QACD,CACA,GAAIS,EAAK,MAAM,GAAG,CAAC,CAAC,SAAS,WAAW,EAAG,SACvC,kBAAkB,KAAKA,CAAI,GAAKA,IAAS,mBAC5CT,EAAY,KAAK,CAChB,KAAM,eACN,OACA,QACC,4GACF,CAAC,EACEiB,EAAWN,EAAO,OAAO,GAAKF,IAAS,mBAAmBN,EAAS,IAAIY,EAAQN,CAAI,CAAC,EACxF,IAAMS,EAAQC,EAAYV,CAAI,GAAK,GAC7BW,kBAAU,IAAI,IACpBd,EAAa,IAAIG,EAAMW,CAAO,EAC9B,IAAK,IAAMC,KAAUC,EAAeX,EAAO,OAAO,EAAG,CACpD,IAAMY,EAASC,EAAcjB,EAAUG,EAAUW,CAAM,EACvD,GAAI,CAACE,EAAQ,SACb,IAAME,EAAaC,EAAS7B,EAAM0B,CAAM,CAAC,CAAC,MAAMI,CAAG,CAAC,CAAC,KAAK,GAAG,EAC7DP,EAAQ,IAAIK,CAAU,EACtB,IAAMG,EAAcT,EAAYM,CAAU,EAC1C,GAAIP,GAASU,GAAeV,IAAUU,EAAa,CAClD,IAAMC,EAAQxB,EAAM,IAAIa,CAAK,mBAAK,IAAI,IACtCb,EAAM,IAAIa,EAAOW,CAAK,EACtBA,EAAM,IAAID,CAAW,CACtB,CACD,CACD,CACA,IAAK,IAAME,KAAa3B,EAClBC,EAAO,IAAI0B,CAAS,GACxB9B,EAAY,KAAK,CAChB,KAAM,QACN,KAAM8B,EACN,QAAS,GAAGA,EAAU,uHACvB,CAAC,EAEH9B,EAAY,KAAK,GAAG+B,EAAgBzB,CAAY,CAAC,EACjD,IAAK,IAAM0B,KAASC,EAAO5B,CAAK,EAC/BL,EAAY,KAAK,CAChB,KAAM,QACN,KAAMgC,EAAM,GACZ,QAAS,4BAA4BA,EAAM,KAAK,KAAK,EAAE,EACxD,CAAC,EACF,OAAOhC,EAAY,MAAM,EAAG,IAAMkC,EAAE,KAAK,cAAcC,EAAE,IAAI,GAAKD,EAAE,KAAK,cAAcC,EAAE,IAAI,CAAC,CAC/F,CAEA,SAAgB3B,GAAiB,CAChC,OAAO,IAAI4B,EAAgB,CAC1B,SAAU,OACV,WAAY,CAAC,MAAO,OAAQ,OAAQ,OAAQ,MAAO,OAAQ,OAAQ,OAAQ,OAAO,EAClF,eAAgB,CACf,MAAO,CAAC,MAAO,OAAQ,KAAK,EAC5B,OAAQ,CAAC,OAAQ,MAAM,EACvB,OAAQ,CAAC,OAAQ,MAAM,CACxB,EACA,eAAgB,CAAC,QAAS,SAAU,OAAQ,SAAS,EACrD,SAAU,EACX,CAAC,CACF,CAEA,SAAgBZ,EAAc,EAA2B,EAAkB,EAAgB,CAI1F,OAHcjB,EAAS,gBAAgBG,EAAUW,CAAM,CAAC,CAAC,OAGlDA,EAAO,WAAW,GAAG,EAAI1B,EAAQoB,EAAQL,CAAQ,EAAGW,CAAM,EAAI,KACtE,CAGA,SAAgBgB,EAAmB,EAAc,CAChD,GAAI,CAACvC,EAAWD,CAAI,EAAG,OAAO,KAC9B,GAAIC,EAAWH,EAAQE,EAAM,kBAAkB,CAAC,EAC/C,OAAOE,EAAaJ,EAAQE,EAAM,kBAAkB,CAAC,EACtD,EAAOE,EAAaF,CAAI,EACxB,IAAK,IAAMY,KAAQP,EAAYL,EAAM,CAAC,CAAC,EACtC,GAAI,CAACY,EAAK,SAAS,YAAY,GAAK,CAACK,EAASL,CAAI,EAAG,OAAOd,EAAQE,EAAMY,CAAI,EAC/E,OAAO,IACR,CAEA,SAAUP,EAAY,EAAc,EAA0D,CAC7F,IAAMoC,kBAAU,IAAI,IAAI,CACvB,aACA,YACA,MACA,SACA,cACA,aACA,YACD,CAAC,EACD,SAAUC,EAAK,EAAsC,CACpD,IAAK,IAAMC,KAASC,EAAYX,EAAW,CAAE,cAAe,EAAK,CAAC,CAAC,CAAC,MAAM,EAAG,IAC5EI,EAAE,KAAK,cAAcC,EAAE,IAAI,CAC5B,EAAG,CACF,IAAMO,EAAO/C,EAAQmC,EAAWU,EAAM,IAAI,EACpC/B,EAAOiB,EAAS7B,EAAM6C,CAAI,CAAC,CAAC,MAAMf,CAAG,CAAC,CAAC,KAAK,GAAG,EACrD,GAAIa,EAAM,eAAe,EAAG,CAC3BxC,EAAY,KAAK,CAChB,KAAM,UACN,OACA,QACC,mGACF,CAAC,EACD,QACD,CACIwC,EAAM,YAAY,GACjBV,IAAcjC,GAAQ,CAACyC,EAAQ,IAAIE,EAAM,IAAI,GAChDxC,EAAY,KAAK,CAChB,KAAM,iBACN,OACA,QAAS,eAAewC,EAAM,KAAK,yGACpC,CAAC,EAEDA,EAAM,OAAS,cACfA,EAAM,OAAS,gBACf,CAACA,EAAM,KAAK,WAAW,GAAG,IAE1B,MAAOD,EAAKG,CAAI,IACP,kBAAkB,KAAKF,EAAM,IAAI,GAAK,CAAC,gBAAgB,KAAKA,EAAM,IAAI,IAAG,MAAM/B,EAC3F,CACD,CACA,MAAO8B,EAAK1C,CAAI,CACjB,CAEA,SAASiB,EAAS,EAAc,CAC/B,MAAO,iCAAiC,KAAKL,CAAI,CAClD,CAEA,SAASQ,EAAW,EAAkB,CACrC,OAAO0B,EAAQ,KAAK,KAAM,GAAc,CACvC,IAAMC,EACLC,EAAU,OAAS,yBAA2BA,EAAU,YAAcA,EASvE,OARID,GAAe,YAAaA,GAAeA,EAAY,SACvDC,EAAU,OAAS,qBAAuBA,EAAU,OAAS,iBAAyB,GACtFA,EAAU,OAAS,yBAClBA,EAAU,aAAe,QAAU,CAACA,EAAU,YAAoB,GAC/D,CAAC,CAAC,yBAA0B,yBAA0B,mBAAmB,CAAC,CAAC,SACjFA,EAAU,YAAY,IACvB,EAEM,CAAC,CACP,yBACA,yBACA,oBACA,sBACD,CAAC,CAAC,SAASA,EAAU,IAAI,CAC1B,CAAC,CACF,CAEA,SAAS7B,EAAgB,EAAkB,CAC1C,IAAM8B,kBAAQ,IAAI,IAAI,CACrB,CAAC,OAAQ,MAAM,EACf,CAAC,KAAM,IAAI,EACX,CAAC,WAAY,UAAU,EACvB,CAAC,QAAS,OAAO,CAClB,CAAC,EACD,IAAK,IAAMD,KAAaF,EAAQ,KAAM,CACrC,IAAMC,EACLC,EAAU,OAAS,yBAA2BA,EAAU,YAAcA,EAGvE,GAFID,GAAa,OAAS,uBAAyBA,EAAY,IAC9DE,EAAM,OAAOF,EAAY,GAAG,IAAI,EAC7BA,GAAa,OAAS,sBACpB,IAAA,IAAMG,KAAQH,EAAY,aAC1BG,EAAK,GAAG,OAAS,cAAcD,EAAM,OAAOC,EAAK,GAAG,IAAI,EAE9D,GAAIF,EAAU,OAAS,oBACvB,IAAK,IAAMG,KAAaH,EAAU,WACjCC,EAAM,OAAOE,EAAU,MAAM,IAAI,EAE/B,CAAC,SAAU,iBAAkB,WAAY,YAAa,eAAe,CAAC,CAAC,SACvEH,EAAU,OAAO,KAClB,IAGGG,EAAU,OAAS,2BAA4BF,EAAM,IAAIE,EAAU,MAAM,KAAM,GAAG,EAC7EA,EAAU,OAAS,yBAA0BF,EAAM,IAAIE,EAAU,MAAM,KAAM,MAAM,EACnFA,EAAU,SAAS,OAAS,cACpCF,EAAM,IAAIE,EAAU,MAAM,KAAMA,EAAU,SAAS,IAAI,EAE1D,CACA,IAAMC,EAA0B,CAAC,EACjC,IAAIC,EAAQ,CACX,eAAe,EAAM,CACpBD,EAAM,KAAKE,CAAI,CAChB,CACD,CAAC,CAAC,CAAC,MAAMR,CAAO,EAChB,IAAMS,EAAUH,EAAM,OAAQ,GAAS,CACtC,IAAMI,EAAQC,EAAWH,EAAK,OAAQL,CAAK,EAC3C,MACC,CAAC,OAAQ,KAAM,WAAY,OAAO,CAAC,CAAC,SAASO,EAAM,EAAE,IACpDA,EAAM,KAAM,GAAS,CAAC,OAAQ,OAAQ,SAAU,OAAO,CAAC,CAAC,SAASE,CAAI,CAAC,GACvEJ,EAAK,UAAU,KACb,GACAK,EAAS,OAAS,oBAClBA,EAAS,WAAW,KAClB,GACAC,EAAS,OAAS,YAClB,CAAC,OAAQ,MAAM,CAAC,CAAC,SAChBA,EAAS,IAAI,OAAS,aACnBA,EAAS,IAAI,KACbA,EAAS,IAAI,OAAS,UACrB,OAAOA,EAAS,IAAI,KAAK,EACzB,EACL,IACEA,EAAS,MAAM,OAAS,WAAaA,EAAS,MAAM,QAAU,GAClE,CACF,EAEH,CAAC,EACD,OAAOR,EAAM,KAAM,GAAS,CAC3B,IAAMI,EAAQC,EAAWH,EAAK,OAAQL,CAAK,EAO3C,MALC,CAAC,CAAC,OAAQ,IAAI,CAAC,CAAC,SAASO,EAAM,EAAE,GACjCD,EAAQ,KAAM,GAASD,EAAK,OAASO,EAAK,OAASP,EAAK,KAAOO,EAAK,GAAG,EAEhE,GAEDP,EAAK,UAAU,KACpB,IACCK,EAAS,OAAS,2BAA6BA,EAAS,OAAS,uBAClEA,EAAS,OACRA,EAAS,KAAK,OAAS,kBACvBA,EAAS,KAAK,KAAK,KAAM,GAAcX,EAAU,OAAS,gBAAgB,EAC7E,CACD,CAAC,CACF,CAEA,SAASS,EAAW,EAAY,EAAsC,CACrE,GAAIH,EAAK,OAAS,aAAc,CAC/B,IAAMQ,EAAOb,EAAM,IAAIK,EAAK,IAAI,EAChC,OAAOQ,EAAO,CAACA,CAAI,EAAI,CAAC,CACzB,CACA,GAAIR,EAAK,OAAS,iBAAkB,OAAOG,EAAWH,EAAK,OAAQL,CAAK,EACxE,GAAIK,EAAK,OAAS,mBAAoB,CACrC,IAAMS,EAAON,EAAWH,EAAK,OAAQL,CAAK,EACpCW,EACL,CAACN,EAAK,UAAYA,EAAK,SAAS,OAAS,aACtCA,EAAK,SAAS,KACdA,EAAK,SAAS,OAAS,UACtB,OAAOA,EAAK,SAAS,KAAK,EAC1B,GAEL,MADI,CAACS,EAAK,QAAU,CAACH,EAAiB,CAAC,EAChCG,EAAK,KAAO,IAAM,CAACH,CAAQ,EAAI,CAAC,GAAGG,EAAMH,CAAQ,CACzD,CACA,MAAO,CAAC,CACT,CAEA,SAASnC,EAAe,EAAkB,CACzC,IAAMuC,EAAoB,CAAC,EA0B3B,OAzBA,IAAIX,EAAQ,CACX,kBAAkB,EAAM,CAEtBC,EAAK,aAAe,SACnBA,EAAK,WAAW,SAAW,GAC3BA,EAAK,WAAW,KAAM,GAAMW,EAAE,OAAS,mBAAqBA,EAAE,aAAe,MAAM,IAEpFD,EAAQ,KAAKV,EAAK,OAAO,KAAK,CAChC,EACA,uBAAuB,EAAM,CAE3BA,EAAK,QACLA,EAAK,aAAe,QACpBA,EAAK,WAAW,KAAM,GAAcH,EAAU,aAAe,MAAM,GAEnEa,EAAQ,KAAKV,EAAK,OAAO,KAAK,CAChC,EACA,qBAAqB,EAAM,CACtBA,EAAK,aAAe,QAAQU,EAAQ,KAAKV,EAAK,OAAO,KAAK,CAC/D,EACA,iBAAiB,EAAM,CAClBA,EAAK,OAAO,OAAS,WAAa,OAAOA,EAAK,OAAO,KAAK,IAAMA,EAAK,OAAO,OAC/EU,EAAQ,KAAK,OAAOV,EAAK,OAAO,KAAK,CAAC,CACxC,CACD,CAAC,CAAC,CAAC,MAAMR,CAAO,EACTkB,CACR,CAEA,SAAS1C,EAAY,EAAc,CAClC,IAAMkC,EAAQ5C,EAAK,MAAM,GAAG,EAC5B,OAAO4C,EAAM,KAAO,UAAYA,EAAM,QAAU,GAAKA,EAAM,KAAO,YAC/D,UAAUA,EAAM,KAChB,IACJ,CAEA,SAASpB,EAAO,EAAiC,CAChD,IAAM8B,kBAAY,IAAI,IAChBC,EAAkB,CAAC,EACnBC,EAAoB,CAAC,EAC3B,SAASC,EAAM,EAAe,CAC7B,IAAMC,EAAQH,EAAM,QAAQ9C,CAAK,EACjC,GAAIiD,GAAS,EAAG,CACfF,EAAM,KAAK,CAAC,GAAGD,EAAM,MAAMG,CAAK,EAAGjD,CAAK,CAAC,EACzC,MACD,CACA,GAAI,GAAU,IAAIA,CAAK,EACvB,GAAM,KAAKA,CAAK,EAChB,IAAK,IAAMkD,KAAc/D,EAAM,IAAIa,CAAK,GAAK,CAAC,EAAGgD,EAAME,CAAU,EACjEJ,EAAM,IAAI,EACVD,EAAU,IAAI7C,CAAK,CAHH,CAIjB,CACA,IAAK,IAAMA,KAASb,EAAM,KAAK,EAAG6D,EAAMhD,CAAK,EAC7C,OAAO+C,CACR,CAEA,SAASlC,EAAgB,EAAkE,CAC1F,IAAMsC,kBAAY,IAAI,IACtB,IAAK,GAAM,CAAC5D,EAAMW,KAAYd,EAAc,CAC3C,IAAMY,EAAQC,EAAYV,CAAI,GAAK,GACnC,GAAI,CAACS,GAASA,IAAU,gBAAiB,SACzC,IAAMoD,kBAAU,IAAI,IACpB,SAASJ,EAAM,EAAgB,CAC9B,GAAI,CAAC3C,EAAO,WAAW,gBAAgB,GAAK+C,EAAQ,IAAI/C,CAAM,EAAG,OACjE+C,EAAQ,IAAI/C,CAAM,EAClB,IAAMgD,EAASF,EAAU,IAAI9C,CAAM,mBAAK,IAAI,IAC5CgD,EAAO,IAAIrD,CAAK,EAChBmD,EAAU,IAAI9C,EAAQgD,CAAM,EAC5B,IAAK,IAAMC,KAAQlE,EAAa,IAAIiB,CAAM,GAAK,CAAC,EAAG2C,EAAMM,CAAI,CAC9D,CACA,IAAK,IAAMjD,KAAUH,EAAS8C,EAAM3C,CAAM,CAC3C,CACA,IAAMvB,EAAwC,CAAC,EAC/C,IAAK,GAAM,CAACS,EAAM8D,KAAWF,EACxBE,EAAO,OAAS,GACnBvE,EAAY,KAAK,CAChB,KAAM,eACN,OACA,QAAS,8CAA8C,CAAC,GAAGuE,CAAM,CAAC,CAAC,GAAG,0DACvE,CAAC,EAEH,OAAOvE,CACR"}
|
|
1
|
+
{"version":3,"file":"architecture.mjs","names":["inspectArchitecture","requestedRoot","resolve","options","root","existsSync","realpathSync","diagnostics","files","sourceFiles","required","tested","graph","dependencies","resolver","createResolver","file","filename","parsed","parseSync","readFileSync","testFile","dirname","hasRunnableTest","executable","narrowRootDeclaration","owner","moduleOwner","targets","source","runtimeImports","target","resolveImport","targetFile","relative","sep","targetOwner","edges","directory","sharedOwnership","cycle","cycles","a","b","ResolverFactory","architectureAnchor","factory","imports","aliases","factories","exported","factoryName","node","active","init","declarative","relationParameter","registryCallback","value","property","body","callee","path","argument","statement","specifier","declaration","item","index","allowed","scan","entry","readdirSync","program","names","calls","Visitor","skipped","parts","testCallee","part","skip","name","base","s","completed","stack","found","visit","dependency","consumers","visited","owners","next"],"sources":["../../src/oxlint/architecture.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport { parseSync, Visitor, type Program, type Node, type CallExpression } from 'oxc-parser'\nimport { ResolverFactory } from 'oxc-resolver'\n\nexport interface ArchitectureOptions {\n\tcwd?: string\n\tconvexDir?: string\n}\nexport interface ArchitectureDiagnostic {\n\tcode:\n\t\t| 'missing-root'\n\t\t| 'root-directory'\n\t\t| 'tests'\n\t\t| 'test-location'\n\t\t| 'parse'\n\t\t| 'cycle'\n\t\t| 'symlink'\n\t\t| 'domain-entry'\n\t\t| 'shared-owner'\n\tfile: string\n\tmessage: string\n}\n\n/** Full-project checks, independent of the consumer's test runner. No persistent cache. */\nexport function inspectArchitecture(options: ArchitectureOptions = {}): ArchitectureDiagnostic[] {\n\tconst requestedRoot = resolve(options.cwd ?? process.cwd(), options.convexDir ?? 'convex')\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst diagnostics: ArchitectureDiagnostic[] = []\n\tif (!existsSync(root))\n\t\treturn [\n\t\t\t{ code: 'missing-root', file: '.', message: `Convex directory does not exist: ${root}` },\n\t\t]\n\tconst files = sourceFiles(root, diagnostics)\n\tconst required = new Set<string>()\n\tconst tested = new Set<string>()\n\tconst graph = new Map<string, Set<string>>()\n\tconst dependencies = new Map<string, Set<string>>()\n\tconst resolver = createResolver()\n\tfor (const file of files) {\n\t\tconst filename = resolve(root, file)\n\t\tconst parsed = parseSync(filename, readFileSync(filename, 'utf8'))\n\t\tif (parsed.errors.length) {\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'parse',\n\t\t\t\tfile,\n\t\t\t\tmessage: `Cannot validate ${file}: ${parsed.errors[0].message}`,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif (testFile(file)) {\n\t\t\tif (!file.includes('__tests__/'))\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tcode: 'test-location',\n\t\t\t\t\tfile,\n\t\t\t\t\tmessage: 'Place tests in a sibling __tests__/ directory.',\n\t\t\t\t})\n\t\t\telse if (dirname(file).endsWith('__tests__') && hasRunnableTest(parsed.program))\n\t\t\t\ttested.add(dirname(dirname(file)))\n\t\t\tcontinue\n\t\t}\n\t\tif (file.split('/').includes('__tests__')) continue\n\t\tif (/^domain\\/[^/]+$/.test(file) && file !== 'domain/table.ts')\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'domain-entry',\n\t\t\t\tfile,\n\t\t\t\tmessage:\n\t\t\t\t\t'Domain source belongs in domain/<module>/ or domain/shared/. Only domain/table.ts assembles module tables.',\n\t\t\t})\n\t\tif (\n\t\t\texecutable(parsed.program) &&\n\t\t\tfile !== 'domain/table.ts' &&\n\t\t\t!narrowRootDeclaration(file, readFileSync(filename, 'utf8'))\n\t\t)\n\t\t\trequired.add(dirname(file))\n\t\tconst owner = moduleOwner(file) ?? ''\n\t\tconst targets = new Set<string>()\n\t\tdependencies.set(file, targets)\n\t\tfor (const source of runtimeImports(parsed.program)) {\n\t\t\tconst target = resolveImport(resolver, filename, source)\n\t\t\tif (!target) continue\n\t\t\tconst targetFile = relative(root, target).split(sep).join('/')\n\t\t\ttargets.add(targetFile)\n\t\t\tconst targetOwner = moduleOwner(targetFile)\n\t\t\tif (owner && targetOwner && owner !== targetOwner) {\n\t\t\t\tconst edges = graph.get(owner) ?? new Set<string>()\n\t\t\t\tgraph.set(owner, edges)\n\t\t\t\tedges.add(targetOwner)\n\t\t\t}\n\t\t}\n\t}\n\tfor (const directory of required) {\n\t\tif (!tested.has(directory))\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'tests',\n\t\t\t\tfile: directory,\n\t\t\t\tmessage: `${directory}/__tests__/ must contain a .test or .spec file with a nonempty, non-skipped test. Parent or child suites do not count.`,\n\t\t\t})\n\t}\n\tdiagnostics.push(...sharedOwnership(dependencies))\n\tfor (const cycle of cycles(graph))\n\t\tdiagnostics.push({\n\t\t\tcode: 'cycle',\n\t\t\tfile: cycle[0],\n\t\t\tmessage: `Module dependency cycle: ${cycle.join(' → ')}.`,\n\t\t})\n\treturn diagnostics.sort((a, b) => a.file.localeCompare(b.file) || a.code.localeCompare(b.code))\n}\n\nexport function createResolver() {\n\treturn new ResolverFactory({\n\t\ttsconfig: 'auto',\n\t\textensions: ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs', '.json'],\n\t\textensionAlias: {\n\t\t\t'.js': ['.ts', '.tsx', '.js'],\n\t\t\t'.mjs': ['.mts', '.mjs'],\n\t\t\t'.cjs': ['.cts', '.cjs'],\n\t\t},\n\t\tconditionNames: ['types', 'import', 'node', 'default'],\n\t\tsymlinks: true,\n\t})\n}\n\nexport function resolveImport(resolver: ResolverFactory, filename: string, source: string) {\n\tconst found = resolver.resolveFileSync(filename, source).path\n\tif (found) return found\n\t// Keep path checks useful in unsaved/editor fixtures and before Convex codegen.\n\treturn source.startsWith('.') ? resolve(dirname(filename), source) : null\n}\n\n/** The lint rule runs the project scan on one deterministic source file. */\nexport function architectureAnchor(root: string) {\n\tif (!existsSync(root)) return null\n\tif (existsSync(resolve(root, 'convex.config.ts')))\n\t\treturn realpathSync(resolve(root, 'convex.config.ts'))\n\troot = realpathSync(root)\n\tfor (const file of sourceFiles(root, []))\n\t\tif (!file.includes('__tests__/') && !testFile(file)) return resolve(root, file)\n\treturn null\n}\n\n/** Only these two factory declarations may omit root business ownership. */\nexport function narrowRootDeclaration(file: string, source: string): boolean {\n\tconst factory =\n\t\tfile === 'relations.ts'\n\t\t\t? 'defineRelations'\n\t\t\t: file === 'querying.ts'\n\t\t\t\t? 'createQueryEngine'\n\t\t\t\t: null\n\tif (!factory) return false\n\tconst parsed = parseSync(file, source)\n\tif (parsed.errors.length) return false\n\tconst imports = new Map<string, string>()\n\tconst aliases = new Map<string, Node>()\n\tlet factories = 0\n\tlet exported = false\n\tfunction factoryName(node: Node, active = new Set<string>()): string | null {\n\t\tif (node.type === 'Identifier') {\n\t\t\tif (active.has(node.name)) return null\n\t\t\tconst init = aliases.get(node.name)\n\t\t\treturn init\n\t\t\t\t? factoryName(init, new Set(active).add(node.name))\n\t\t\t\t: (imports.get(node.name) ?? null)\n\t\t}\n\t\tif (\n\t\t\tnode.type === 'MemberExpression' &&\n\t\t\t!node.computed &&\n\t\t\tnode.property.type === 'Identifier' &&\n\t\t\tfactoryName(node.object, active) === '*'\n\t\t)\n\t\t\treturn node.property.name\n\t\treturn null\n\t}\n\tfunction declarative(node: Node, relationParameter?: string, registryCallback = false): boolean {\n\t\tif (node.type === 'Identifier' || node.type === 'Literal') return true\n\t\tif (\n\t\t\tnode.type === 'TSAsExpression' ||\n\t\t\tnode.type === 'TSSatisfiesExpression' ||\n\t\t\tnode.type === 'ParenthesizedExpression'\n\t\t)\n\t\t\treturn declarative(node.expression, relationParameter, registryCallback)\n\t\tif (node.type === 'MemberExpression')\n\t\t\treturn !node.computed && declarative(node.object, relationParameter)\n\t\tif (node.type === 'ArrayExpression')\n\t\t\treturn node.elements.every((value) => value !== null && declarative(value, relationParameter))\n\t\tif (node.type === 'ObjectExpression')\n\t\t\treturn node.properties.every(\n\t\t\t\t(property) =>\n\t\t\t\t\tproperty.type === 'Property' &&\n\t\t\t\t\t!property.computed &&\n\t\t\t\t\tproperty.kind === 'init' &&\n\t\t\t\t\t!property.method &&\n\t\t\t\t\tdeclarative(property.value, relationParameter),\n\t\t\t)\n\t\tif (\n\t\t\tnode.type === 'ArrowFunctionExpression' &&\n\t\t\tregistryCallback &&\n\t\t\t!relationParameter &&\n\t\t\tnode.params.length === 1 &&\n\t\t\tnode.params[0].type === 'Identifier' &&\n\t\t\t!node.async\n\t\t) {\n\t\t\tconst body = node.body.type === 'ParenthesizedExpression' ? node.body.expression : node.body\n\t\t\treturn body.type === 'ObjectExpression' && declarative(body, node.params[0].name)\n\t\t}\n\t\tif (node.type === 'CallExpression' && relationParameter) {\n\t\t\tlet callee: Node = node.callee\n\t\t\tconst path: string[] = []\n\t\t\twhile (\n\t\t\t\tcallee.type === 'MemberExpression' &&\n\t\t\t\t!callee.computed &&\n\t\t\t\tcallee.property.type === 'Identifier'\n\t\t\t) {\n\t\t\t\tpath.unshift(callee.property.name)\n\t\t\t\tcallee = callee.object\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tcallee.type === 'Identifier' &&\n\t\t\t\tcallee.name === relationParameter &&\n\t\t\t\t((path.length === 2 && ['one', 'many'].includes(path[0])) ||\n\t\t\t\t\t(path.length === 3 && path[2] === 'through')) &&\n\t\t\t\tnode.arguments.every((argument) => declarative(argument, relationParameter))\n\t\t\t)\n\t\t}\n\t\treturn false\n\t}\n\tfor (const statement of parsed.program.body) {\n\t\tif (statement.type === 'ImportDeclaration') {\n\t\t\tif (statement.importKind === 'type') continue\n\t\t\tfor (const specifier of statement.specifiers) {\n\t\t\t\tif (specifier.type === 'ImportSpecifier' && specifier.importKind === 'type') continue\n\t\t\t\tif (['cvx-kit', `cvx-kit/${file.slice(0, -3)}`].includes(statement.source.value))\n\t\t\t\t\timports.set(\n\t\t\t\t\t\tspecifier.local.name,\n\t\t\t\t\t\tspecifier.type === 'ImportSpecifier'\n\t\t\t\t\t\t\t? specifier.imported.type === 'Identifier'\n\t\t\t\t\t\t\t\t? specifier.imported.name\n\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t: specifier.type === 'ImportNamespaceSpecifier'\n\t\t\t\t\t\t\t\t? '*'\n\t\t\t\t\t\t\t\t: '',\n\t\t\t\t\t)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif (\n\t\t\tstatement.type === 'EmptyStatement' ||\n\t\t\tstatement.type === 'TSTypeAliasDeclaration' ||\n\t\t\tstatement.type === 'TSInterfaceDeclaration'\n\t\t)\n\t\t\tcontinue\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration?.type !== 'VariableDeclaration' || declaration.kind !== 'const') return false\n\t\tfor (const item of declaration.declarations) {\n\t\t\tif (item.id.type !== 'Identifier' || !item.init) return false\n\t\t\tif (item.init.type === 'CallExpression' && factoryName(item.init.callee) === factory) {\n\t\t\t\tif (\n\t\t\t\t\t!item.init.arguments.every((argument, index) =>\n\t\t\t\t\t\tdeclarative(argument, undefined, factory === 'defineRelations' && index === 1),\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t\t\treturn false\n\t\t\t\tfactories++\n\t\t\t\texported ||= statement.type === 'ExportNamedDeclaration'\n\t\t\t} else if (statement.type === 'ExportNamedDeclaration' || !declarative(item.init))\n\t\t\t\treturn false\n\t\t\taliases.set(item.id.name, item.init)\n\t\t}\n\t}\n\treturn factories === 1 && exported\n}\n\nfunction* sourceFiles(root: string, diagnostics: ArchitectureDiagnostic[]): Generator<string> {\n\tconst allowed = new Set([\n\t\t'_generated',\n\t\t'__tests__',\n\t\t'api',\n\t\t'domain',\n\t\t'application',\n\t\t'migrations',\n\t\t'components',\n\t])\n\tfunction* scan(directory: string): Generator<string> {\n\t\tfor (const entry of readdirSync(directory, { withFileTypes: true }).sort((a, b) =>\n\t\t\ta.name.localeCompare(b.name),\n\t\t)) {\n\t\t\tconst path = resolve(directory, entry.name)\n\t\t\tconst file = relative(root, path).split(sep).join('/')\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tcode: 'symlink',\n\t\t\t\t\tfile,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'Keep application source inside its owning directory; symlinked files and folders are not allowed.',\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (directory === root && !allowed.has(entry.name))\n\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\tcode: 'root-directory',\n\t\t\t\t\t\tfile,\n\t\t\t\t\t\tmessage: `Root folder ${entry.name}/ is not allowed. Use api/, domain/, application/, migrations/, components/, __tests__/, or _generated/.`,\n\t\t\t\t\t})\n\t\t\t\tif (\n\t\t\t\t\tentry.name !== '_generated' &&\n\t\t\t\t\tentry.name !== 'node_modules' &&\n\t\t\t\t\t!entry.name.startsWith('.')\n\t\t\t\t)\n\t\t\t\t\tyield* scan(path)\n\t\t\t} else if (/\\.[cm]?[jt]sx?$/.test(entry.name) && !/\\.d\\.[cm]?ts$/.test(entry.name)) yield file\n\t\t}\n\t}\n\tyield* scan(root)\n}\n\nfunction testFile(file: string) {\n\treturn /\\.(?:test|spec)\\.[cm]?[jt]sx?$/.test(file)\n}\n\nfunction executable(program: Program) {\n\treturn program.body.some((statement) => {\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration && 'declare' in declaration && declaration.declare) return false\n\t\tif (statement.type === 'ImportDeclaration' || statement.type === 'EmptyStatement') return false\n\t\tif (statement.type === 'ExportNamedDeclaration') {\n\t\t\tif (statement.exportKind === 'type' || !statement.declaration) return false\n\t\t\treturn !['TSInterfaceDeclaration', 'TSTypeAliasDeclaration', 'TSDeclareFunction'].includes(\n\t\t\t\tstatement.declaration.type,\n\t\t\t)\n\t\t}\n\t\treturn ![\n\t\t\t'TSInterfaceDeclaration',\n\t\t\t'TSTypeAliasDeclaration',\n\t\t\t'TSDeclareFunction',\n\t\t\t'ExportAllDeclaration',\n\t\t].includes(statement.type)\n\t})\n}\n\nfunction hasRunnableTest(program: Program) {\n\tconst names = new Map([\n\t\t['test', 'test'],\n\t\t['it', 'it'],\n\t\t['describe', 'describe'],\n\t\t['suite', 'suite'],\n\t])\n\tfor (const statement of program.body) {\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration?.type === 'FunctionDeclaration' && declaration.id)\n\t\t\tnames.delete(declaration.id.name)\n\t\tif (declaration?.type === 'VariableDeclaration')\n\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\tif (item.id.type === 'Identifier') names.delete(item.id.name)\n\t\t\t}\n\t\tif (statement.type !== 'ImportDeclaration') continue\n\t\tfor (const specifier of statement.specifiers) {\n\t\t\tnames.delete(specifier.local.name)\n\t\t\tif (\n\t\t\t\t!['vitest', 'vite-plus/test', 'bun:test', 'node:test', '@jest/globals'].includes(\n\t\t\t\t\tstatement.source.value,\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tcontinue\n\t\t\tif (specifier.type === 'ImportNamespaceSpecifier') names.set(specifier.local.name, '*')\n\t\t\telse if (specifier.type === 'ImportDefaultSpecifier') names.set(specifier.local.name, 'test')\n\t\t\telse if (specifier.imported.type === 'Identifier')\n\t\t\t\tnames.set(specifier.local.name, specifier.imported.name)\n\t\t}\n\t}\n\tconst calls: CallExpression[] = []\n\tnew Visitor({\n\t\tCallExpression(node) {\n\t\t\tcalls.push(node)\n\t\t},\n\t}).visit(program)\n\tconst skipped = calls.filter((node) => {\n\t\tconst parts = testCallee(node.callee, names)\n\t\treturn (\n\t\t\t['test', 'it', 'describe', 'suite'].includes(parts[0]) &&\n\t\t\t(parts.some((part) => ['skip', 'todo', 'skipIf', 'runIf'].includes(part)) ||\n\t\t\t\tnode.arguments.some(\n\t\t\t\t\t(argument) =>\n\t\t\t\t\t\targument.type === 'ObjectExpression' &&\n\t\t\t\t\t\targument.properties.some(\n\t\t\t\t\t\t\t(property) =>\n\t\t\t\t\t\t\t\tproperty.type === 'Property' &&\n\t\t\t\t\t\t\t\t['skip', 'todo'].includes(\n\t\t\t\t\t\t\t\t\tproperty.key.type === 'Identifier'\n\t\t\t\t\t\t\t\t\t\t? property.key.name\n\t\t\t\t\t\t\t\t\t\t: property.key.type === 'Literal'\n\t\t\t\t\t\t\t\t\t\t\t? String(property.key.value)\n\t\t\t\t\t\t\t\t\t\t\t: '',\n\t\t\t\t\t\t\t\t) &&\n\t\t\t\t\t\t\t\t!(property.value.type === 'Literal' && property.value.value === false),\n\t\t\t\t\t\t),\n\t\t\t\t))\n\t\t)\n\t})\n\treturn calls.some((node) => {\n\t\tconst parts = testCallee(node.callee, names)\n\t\tif (\n\t\t\t!['test', 'it'].includes(parts[0]) ||\n\t\t\tskipped.some((skip) => node.start >= skip.start && node.end <= skip.end)\n\t\t)\n\t\t\treturn false\n\t\t// each(...) is a factory; only the outer call has the test callback.\n\t\treturn node.arguments.some(\n\t\t\t(argument) =>\n\t\t\t\t(argument.type === 'ArrowFunctionExpression' || argument.type === 'FunctionExpression') &&\n\t\t\t\targument.body &&\n\t\t\t\t(argument.body.type !== 'BlockStatement' ||\n\t\t\t\t\targument.body.body.some((statement) => statement.type !== 'EmptyStatement')),\n\t\t)\n\t})\n}\n\nfunction testCallee(node: Node, names: Map<string, string>): string[] {\n\tif (node.type === 'Identifier') {\n\t\tconst name = names.get(node.name)\n\t\treturn name ? [name] : []\n\t}\n\tif (node.type === 'CallExpression') return testCallee(node.callee, names)\n\tif (node.type === 'MemberExpression') {\n\t\tconst base = testCallee(node.object, names)\n\t\tconst property =\n\t\t\t!node.computed && node.property.type === 'Identifier'\n\t\t\t\t? node.property.name\n\t\t\t\t: node.property.type === 'Literal'\n\t\t\t\t\t? String(node.property.value)\n\t\t\t\t\t: ''\n\t\tif (!base.length || !property) return []\n\t\treturn base[0] === '*' ? [property] : [...base, property]\n\t}\n\treturn []\n}\n\nfunction runtimeImports(program: Program) {\n\tconst imports: string[] = []\n\tnew Visitor({\n\t\tImportDeclaration(node) {\n\t\t\tif (\n\t\t\t\tnode.importKind !== 'type' &&\n\t\t\t\t(node.specifiers.length === 0 ||\n\t\t\t\t\tnode.specifiers.some((s) => s.type !== 'ImportSpecifier' || s.importKind !== 'type'))\n\t\t\t)\n\t\t\t\timports.push(node.source.value)\n\t\t},\n\t\tExportNamedDeclaration(node) {\n\t\t\tif (\n\t\t\t\tnode.source &&\n\t\t\t\tnode.exportKind !== 'type' &&\n\t\t\t\tnode.specifiers.some((specifier) => specifier.exportKind !== 'type')\n\t\t\t)\n\t\t\t\timports.push(node.source.value)\n\t\t},\n\t\tExportAllDeclaration(node) {\n\t\t\tif (node.exportKind !== 'type') imports.push(node.source.value)\n\t\t},\n\t\tImportExpression(node) {\n\t\t\tif (node.source.type === 'Literal' && String(node.source.value) === node.source.value)\n\t\t\t\timports.push(String(node.source.value))\n\t\t},\n\t}).visit(program)\n\treturn imports\n}\n\nfunction moduleOwner(file: string) {\n\tconst parts = file.split('/')\n\treturn parts[0] === 'domain' && parts.length >= 3 && parts[1] !== '__tests__'\n\t\t? `domain/${parts[1]}`\n\t\t: null\n}\n\nfunction cycles(graph: Map<string, Set<string>>) {\n\tconst completed = new Set<string>()\n\tconst stack: string[] = []\n\tconst found: string[][] = []\n\tfunction visit(owner: string) {\n\t\tconst index = stack.indexOf(owner)\n\t\tif (index >= 0) {\n\t\t\tfound.push([...stack.slice(index), owner])\n\t\t\treturn\n\t\t}\n\t\tif (completed.has(owner)) return\n\t\tstack.push(owner)\n\t\tfor (const dependency of graph.get(owner) ?? []) visit(dependency)\n\t\tstack.pop()\n\t\tcompleted.add(owner)\n\t}\n\tfor (const owner of graph.keys()) visit(owner)\n\treturn found\n}\n\nfunction sharedOwnership(dependencies: Map<string, Set<string>>): ArchitectureDiagnostic[] {\n\tconst consumers = new Map<string, Set<string>>()\n\tfor (const [file, targets] of dependencies) {\n\t\tconst owner = moduleOwner(file) ?? ''\n\t\tif (!owner || owner === 'domain/shared') continue\n\t\tconst visited = new Set<string>()\n\t\tfunction visit(target: string) {\n\t\t\tif (!target.startsWith('domain/shared/') || visited.has(target)) return\n\t\t\tvisited.add(target)\n\t\t\tconst owners = consumers.get(target) ?? new Set<string>()\n\t\t\towners.add(owner)\n\t\t\tconsumers.set(target, owners)\n\t\t\tfor (const next of dependencies.get(target) ?? []) visit(next)\n\t\t}\n\t\tfor (const target of targets) visit(target)\n\t}\n\tconst diagnostics: ArchitectureDiagnostic[] = []\n\tfor (const [file, owners] of consumers) {\n\t\tif (owners.size === 1)\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'shared-owner',\n\t\t\t\tfile,\n\t\t\t\tmessage: `This shared implementation is used only by ${[...owners][0]}. Move it into that module until another module needs it.`,\n\t\t\t})\n\t}\n\treturn diagnostics\n}\n"],"mappings":"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"}
|
package/dist/oxlint/ast.d.mts
CHANGED
|
@@ -5,10 +5,19 @@ export declare const consumerOptions: z.ZodObject<{
|
|
|
5
5
|
convexDir: z.ZodDefault<z.ZodString>;
|
|
6
6
|
}, z.core.$strip>;
|
|
7
7
|
export declare function appFile(context: Context, filename?: string): string | null;
|
|
8
|
-
export declare function imported(context: Context, node: ESTree.Node): {
|
|
8
|
+
export declare function imported(context: Context, node: ESTree.Node, active?: Set<ESTree.Node>): {
|
|
9
9
|
source: string;
|
|
10
10
|
name: string;
|
|
11
11
|
} | null;
|
|
12
|
+
/** Follow immutable bindings only; a same-named parameter never inherits outer provenance. */
|
|
13
|
+
export declare function localInitializer(context: Context, node: ESTree.Node): ESTree.Node | null;
|
|
14
|
+
export declare function localDestructured(context: Context, node: ESTree.Node): {
|
|
15
|
+
expression: ESTree.Expression;
|
|
16
|
+
name: string;
|
|
17
|
+
} | null;
|
|
18
|
+
export type ReadProvenance = 'table' | 'dtoSchema' | 'dto' | 'engine' | 'reader' | 'include' | 'context' | 'db' | 'stream' | 'relationship' | 'bounded' | 'page' | 'validator' | 'foundation' | 'queryRegistry' | 'queryOperation';
|
|
19
|
+
/** Suspend dependencies on a work stack; null in-progress entries terminate alias cycles. */
|
|
20
|
+
export declare function readProvenance(context: Context, node: ESTree.Node): ReadProvenance | null;
|
|
12
21
|
export declare function sourceVisitors(context: Context, check: (node: ESTree.Node, source: string) => void): Visitor;
|
|
13
22
|
export declare function isFunctionsImport(context: Context, source: string): boolean;
|
|
14
23
|
export declare function typeOnlySource(node: ESTree.Node): boolean;
|
package/dist/oxlint/ast.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createResolver as e,resolveImport as t}from"./architecture.mjs";import{z as n}from"zod";import{dirname as r,relative as i,resolve as a,sep as o}from"node:path";import{existsSync as s,realpathSync as c}from"node:fs";const l=n.object({convexDir:n.string().min(1).default(`convex`)});function u(e,t=e.filename){let n=a(e.cwd,l.parse(e.options[0]??{}).convexDir),r=s(n)?c(n):n,u=i(r,s(t)?c(t):t).split(o).join(`/`);return u===`..`||u.startsWith(`../`)||u.startsWith(`/`)?null:u}function d(e,t){if(t.type===`CallExpression`)return d(e,t.callee);if(t.type===`MemberExpression`){let n=d(e,t.object),r=E(t);return n&&r&&[`*`,`z`,`default`].includes(n.name)?{source:n.source,name:r}:null}if(t.type!==`Identifier`)return null;for(let n of D(e,t)?.defs??[]){if(n.type!==`ImportBinding`||n.parent?.type!==`ImportDeclaration`||n.parent.importKind===`type`)continue;let e=n.node;if(e.type!==`ImportSpecifier`||e.importKind!==`type`)return{source:n.parent.source.value,name:e.type===`ImportSpecifier`?k(e.imported)??``:e.type===`ImportDefaultSpecifier`?`default`:`*`}}return null}function f(e,t){function n(e,n){let r=T(n);r&&t(e,r)}return{ImportDeclaration(e){n(e,e.source)},ExportNamedDeclaration(e){n(e,e.source)},ExportAllDeclaration(e){n(e,e.source)},ImportExpression(e){n(e,e.source)},TSImportType(e){n(e,e.source)},CallExpression(t){t.callee.type===`Identifier`&&t.callee.name===`require`&&!D(e,t.callee)?.defs.length&&n(t,t.arguments[0])}}}function p(n,i){let o=i.startsWith(`.`)?a(r(n.filename),i):t(e(),n.filename,i);return o!==null&&u(n,o)?.replace(/\.[cm]?[jt]s$/,``)===`functions`}function m(e){return e.type===`TSImportType`||e.type===`ImportDeclaration`&&(e.importKind===`type`||e.specifiers.length>0&&e.specifiers.every(e=>e.type===`ImportSpecifier`&&e.importKind===`type`))||(e.type===`ExportNamedDeclaration`||e.type===`ExportAllDeclaration`)&&e.exportKind===`type`}function h(e){return e.callee.type===`MemberExpression`&&e.callee.object.type===`MemberExpression`&&E(e.callee.object)===`db`}function g(e,t){let n=d(e,t.callee);return n&&/^(?:node:)?(?:https?|net|tls|fs)(?:\/|$)|^(?:undici|axios)(?:\/|$)/.test(n.source)?!0:t.callee.type===`Identifier`&&t.callee.name===`fetch`&&!D(e,t.callee)?.defs.length||t.callee.type===`MemberExpression`&&E(t.callee)===`fetch`&&t.callee.object.type===`Identifier`&&t.callee.object.name===`globalThis`&&!D(e,t.callee.object)?.defs.length}function _(e,t){if(t.type===`MemberExpression`){let n=d(e,t.object);return n?.name===`components`&&/_generated\/api/.test(n.source)?!0:_(e,t.object)}return t.type===`ObjectExpression`&&t.properties.some(t=>t.type===`Property`&&_(e,t.value))}function v(e){return e.type===`MemberExpression`?v(e.object):e}function y(e){return e.type===`Identifier`?[e.name]:e.type===`MemberExpression`?[...y(e.object),E(e)??``]:[]}function b(e){return e.type===`MemberExpression`?E(e)===`table`||b(e.object):e.type===`CallExpression`&&b(e.callee)}function x(e){return e.callee.type===`MemberExpression`&&[`insert`,`patch`,`replace`,`delete`].includes(E(e.callee)??``)&&e.callee.object.type===`MemberExpression`&&E(e.callee.object)===`db`}function S(e,t){return e.type===`CallExpression`?e.callee.type===`MemberExpression`&&E(e.callee)===t&&(t!==`query`||E(e.callee.object)===`db`)||S(e.callee,t):e.type===`MemberExpression`&&S(e.object,t)}function C(e,t){return{type:`problem`,docs:{description:e},schema:[],messages:t}}function w(e,t){let n=a(e.cwd,l.parse(e.options[0]??{}).convexDir),r=s(n)?c(n):n,u=i(r,s(t)?c(t):t).split(o).join(`/`).match(/^components\/([^/]+)(?:\/|$)/);return u?a(r,`components`,u[1]):null}function T(e){return e?.type===`Literal`&&`value`in e&&String(e.value)===e.value?String(e.value):e?.type===`TemplateLiteral`&&e.expressions.length===0?e.quasis[0].value.cooked:null}function E(e){return e.type===`MemberExpression`?e.computed?T(e.property):e.property.name:null}function D(e,t){if(t.type!==`Identifier`)return null;let n=e.sourceCode.getScope(t);for(;n;){let e=n.set.get(t.name);if(e)return e;n=n.upper}return null}function O(e){let t=/* @__PURE__ */ new Set;for(let n of e.body)if(n.type===`ExportNamedDeclaration`&&!n.source)for(let e of n.specifiers)t.add(k(e.local)??``);else n.type===`ExportDefaultDeclaration`&&n.declaration.type===`Identifier`&&t.add(n.declaration.name);return t}function k(e){return e.type===`Identifier`?e.name:T(e)}function A(e){return e.type===`CallExpression`?!0:e.type===`AwaitExpression`?A(e.argument):e.type===`BlockStatement`&&e.body.length>0&&e.body.every(e=>e.type===`ReturnStatement`&&e.argument!==null&&A(e.argument)||e.type===`ExpressionStatement`&&A(e.expression))}export{u as appFile,D as binding,w as componentRoot,l as consumerOptions,_ as containsComponentReference,A as delegatingBody,k as exportName,O as exportedNames,S as hasCall,d as imported,h as isDbAccess,x as isDbWrite,g as isExternalCall,p as isFunctionsImport,b as isTableChain,y as memberPath,C as metadata,E as propertyName,v as rootMember,f as sourceVisitors,T as staticString,m as typeOnlySource};
|
|
1
|
+
import{createResolver as e,resolveImport as t}from"./architecture.mjs";import{z as n}from"zod";import{dirname as r,relative as i,resolve as a,sep as o}from"node:path";import{existsSync as s,readFileSync as c,realpathSync as l}from"node:fs";import{parseSync as u}from"oxc-parser";const d=n.object({convexDir:n.string().min(1).default(`convex`)});function f(e,t=e.filename){let n=a(e.cwd,d.parse(e.options[0]??{}).convexDir),r=s(n)?l(n):n,c=i(r,s(t)?l(t):t).split(o).join(`/`);return c===`..`||c.startsWith(`../`)||c.startsWith(`/`)?null:c}function p(e,t,n=/* @__PURE__ */ new Set){if(n.has(t)||n.size>32)return null;if(n=new Set(n).add(t),t.type===`TSAsExpression`||t.type===`TSSatisfiesExpression`||t.type===`TSNonNullExpression`)return p(e,t.expression,n);if(t.type===`CallExpression`)return p(e,t.callee,n);if(t.type===`MemberExpression`){let r=p(e,t.object,n),i=N(t);return r&&i&&[`*`,`z`,`v`,`default`].includes(r.name)?{source:r.source,name:i}:null}if(t.type!==`Identifier`)return null;let r=m(e,t);if(r&&r.type!==`CallExpression`&&r.type!==`AwaitExpression`)return p(e,r,n);let i=h(e,t);if(i){let t=p(e,i.expression,n);return t&&[`*`,`z`,`v`,`default`].includes(t.name)?{source:t.source,name:i.name}:null}for(let n of P(e,t)?.defs??[]){if(n.type!==`ImportBinding`||n.parent?.type!==`ImportDeclaration`||n.parent.importKind===`type`)continue;let e=n.node;if(e.type!==`ImportSpecifier`||e.importKind!==`type`)return{source:n.parent.source.value,name:e.type===`ImportSpecifier`?I(e.imported)??``:e.type===`ImportDefaultSpecifier`?`default`:`*`}}return null}function m(e,t){let n=P(e,t);if(!n||n.references.some(e=>e.isWrite()&&!e.init))return null;let r=n.defs.length===1?n.defs[0]:null;return r?.type===`Variable`&&r.parent?.type===`VariableDeclaration`&&r.parent.kind===`const`&&r.node.type===`VariableDeclarator`&&r.node.id.type===`Identifier`?r.node.init:null}function h(e,t){let n=P(e,t);if(!n||n.references.some(e=>e.isWrite()&&!e.init))return null;let r=n.defs.length===1?n.defs[0]:null;if(r?.type!==`Variable`||r.parent?.type!==`VariableDeclaration`||r.parent.kind!==`const`||r.node.type!==`VariableDeclarator`||r.node.id.type!==`ObjectPattern`||!r.node.init)return null;for(let e of r.node.id.properties)if(e.type===`Property`&&e.value.type===`Identifier`&&e.value.name===n.name){let t=e.computed?M(e.key):I(e.key);if(t)return{expression:r.node.init,name:t}}return null}const g=[`query`,`internalQuery`,`mutation`,`internalMutation`],_=/* @__PURE__ */ new WeakMap;function v(e,t){let n=B(e).nodes;if(n.has(t))return n.get(t)??null;n.set(t,null);let r=[{node:t,evaluation:V(e,t)}],i=null;for(;r.length;){let t=r[r.length-1],a=t.evaluation.next(i);a.done?(i=a.value,n.set(t.node,i),r.pop()):n.has(a.value)?i=n.get(a.value)??null:(n.set(a.value,null),r.push({node:a.value,evaluation:V(e,a.value)}),i=null)}return i}function y(e,t){function n(e,n){let r=M(n);r&&t(e,r)}return{ImportDeclaration(e){n(e,e.source)},ExportNamedDeclaration(e){n(e,e.source)},ExportAllDeclaration(e){n(e,e.source)},ImportExpression(e){n(e,e.source)},TSImportType(e){n(e,e.source)},CallExpression(t){t.callee.type===`Identifier`&&t.callee.name===`require`&&!P(e,t.callee)?.defs.length&&n(t,t.arguments[0])}}}function b(n,i){let o=i.startsWith(`.`)?a(r(n.filename),i):t(e(),n.filename,i);return o!==null&&f(n,o)?.replace(/\.[cm]?[jt]s$/,``)===`functions`}function x(e){return e.type===`TSImportType`||e.type===`ImportDeclaration`&&(e.importKind===`type`||e.specifiers.length>0&&e.specifiers.every(e=>e.type===`ImportSpecifier`&&e.importKind===`type`))||(e.type===`ExportNamedDeclaration`||e.type===`ExportAllDeclaration`)&&e.exportKind===`type`}function S(e){return e.callee.type===`MemberExpression`&&e.callee.object.type===`MemberExpression`&&N(e.callee.object)===`db`}function C(e,t){let n=p(e,t.callee);return n&&/^(?:node:)?(?:https?|net|tls|fs)(?:\/|$)|^(?:undici|axios)(?:\/|$)/.test(n.source)?!0:t.callee.type===`Identifier`&&t.callee.name===`fetch`&&!P(e,t.callee)?.defs.length||t.callee.type===`MemberExpression`&&N(t.callee)===`fetch`&&t.callee.object.type===`Identifier`&&t.callee.object.name===`globalThis`&&!P(e,t.callee.object)?.defs.length}function w(e,t){if(t.type===`MemberExpression`){let n=p(e,t.object);return n?.name===`components`&&/_generated\/api/.test(n.source)?!0:w(e,t.object)}return t.type===`ObjectExpression`&&t.properties.some(t=>t.type===`Property`&&w(e,t.value))}function T(e){return e.type===`MemberExpression`?T(e.object):e}function E(e){return e.type===`Identifier`?[e.name]:e.type===`MemberExpression`?[...E(e.object),N(e)??``]:[]}function D(e){return e.type===`MemberExpression`?N(e)===`table`||D(e.object):e.type===`CallExpression`&&D(e.callee)}function O(e){return e.callee.type===`MemberExpression`&&[`insert`,`patch`,`replace`,`delete`].includes(N(e.callee)??``)&&e.callee.object.type===`MemberExpression`&&N(e.callee.object)===`db`}function k(e,t){return e.type===`CallExpression`?e.callee.type===`MemberExpression`&&N(e.callee)===t&&(t!==`query`||N(e.callee.object)===`db`)||k(e.callee,t):e.type===`MemberExpression`&&k(e.object,t)}function A(e,t){return{type:`problem`,docs:{description:e},schema:[],messages:t}}function j(e,t){let n=a(e.cwd,d.parse(e.options[0]??{}).convexDir),r=s(n)?l(n):n,c=i(r,s(t)?l(t):t).split(o).join(`/`).match(/^components\/([^/]+)(?:\/|$)/);return c?a(r,`components`,c[1]):null}function M(e){return e?.type===`Literal`&&`value`in e&&String(e.value)===e.value?String(e.value):e?.type===`TemplateLiteral`&&e.expressions.length===0?e.quasis[0].value.cooked:null}function N(e){return e.type===`MemberExpression`?e.computed?M(e.property):e.property.name:null}function P(e,t){if(t.type!==`Identifier`)return null;let n=e.sourceCode.getScope(t);for(;n;){let e=n.set.get(t.name);if(e)return e;n=n.upper}return null}function F(e){let t=/* @__PURE__ */ new Set;for(let n of e.body)if(n.type===`ExportNamedDeclaration`&&!n.source)for(let e of n.specifiers)t.add(I(e.local)??``);else n.type===`ExportDefaultDeclaration`&&n.declaration.type===`Identifier`&&t.add(n.declaration.name);return t}function I(e){return e.type===`Identifier`?e.name:M(e)}function L(e){return e.type===`CallExpression`?!0:e.type===`AwaitExpression`?L(e.argument):e.type===`BlockStatement`&&e.body.length>0&&e.body.every(e=>e.type===`ReturnStatement`&&e.argument!==null&&L(e.argument)||e.type===`ExpressionStatement`&&L(e.expression))}function R(e,n){let r=B(e),i=t(r.resolver,e.filename,n.source),a=i&&f(e,i);if(!i||!a||!/^(?:domain\/.+\/schema\.ts|querying\.ts|foundation\.ts)$/.test(a)||!s(i))return null;let o=`${i}:${n.name}`;if(r.imports.has(o))return r.imports.get(o)??null;let c=z(e,i,n.name);return r.imports.set(o,c),c}function z(e,t,n){let r=B(e),i=r.files.get(t);if(i||(i=u(t,c(t,`utf8`)),r.files.set(t,i)),i.errors.length)return null;let a=/* @__PURE__ */ new Map,o=/* @__PURE__ */ new Map,s=/* @__PURE__ */ new Map,l=/* @__PURE__ */ new Map;for(let e of i.program.body){if(e.type===`ImportDeclaration`&&e.importKind!==`type`)for(let t of e.specifiers)t.type===`ImportSpecifier`&&t.importKind!==`type`&&a.set(t.local.name,{source:e.source.value,name:t.imported.type===`Identifier`?t.imported.name:``}),t.type===`ImportNamespaceSpecifier`&&a.set(t.local.name,{source:e.source.value,name:`*`});let t=e.type===`ExportNamedDeclaration`?e.declaration:e;if(t?.type===`VariableDeclaration`&&t.kind===`const`){for(let n of t.declarations)if(n.init){if(n.id.type===`ObjectPattern`)for(let t of n.id.properties){if(t.type!==`Property`||t.value.type!==`Identifier`)continue;let r=t.computed?G(t.key):t.key.type===`Identifier`?t.key.name:null;r&&(o.set(t.value.name,n.init),s.set(t.value.name,r),e.type===`ExportNamedDeclaration`&&l.set(t.value.name,t.value.name))}n.id.type===`Identifier`&&(o.set(n.id.name,n.init),e.type===`ExportNamedDeclaration`&&l.set(n.id.name,n.id.name))}}if(e.type===`ExportNamedDeclaration`&&!e.source&&e.exportKind!==`type`)for(let t of e.specifiers)t.exportKind!==`type`&&t.local.type===`Identifier`&&t.exported.type===`Identifier`&&l.set(t.exported.name,t.local.name)}let d=l.get(n);if(!d)return null;function f(e,t=/* @__PURE__ */ new Set){if(e.type===`Identifier`){if(t.has(e.name)||t.size>16)return null;let n=a.get(e.name);if(n)return n;let r=o.get(e.name);return r?f(r,new Set(t).add(e.name)):null}if(e.type===`MemberExpression`&&!e.computed&&e.property.type===`Identifier`){let n=f(e.object,t);if(n?.name===`*`)return{source:n.source,name:e.property.name}}return null}function p(e,t=/* @__PURE__ */ new Set){if(e.type===`TSAsExpression`||e.type===`TSSatisfiesExpression`||e.type===`ParenthesizedExpression`)return p(e.expression,t);if(e.type===`Identifier`){if(t.has(e.name)||t.size>16)return null;let n=o.get(e.name),r=n?p(n,new Set(t).add(e.name)):null;return s.has(e.name)?r===`foundation`&&s.get(e.name)===`Query`?`queryRegistry`:null:r}if(e.type===`MemberExpression`&&!e.computed&&e.property.type===`Identifier`)return p(e.object,t)===`foundation`&&e.property.name===`Query`?`queryRegistry`:null;if(e.type!==`CallExpression`&&e.type!==`NewExpression`)return null;let n=f(e.callee);return n&&U(n)?`foundation`:n&&[`cvx-kit`,`cvx-kit/zod-table`,`cvx-kit/tenancy`].includes(n.source)&&[`zodTable`,`tenantTable`,`zodVariantTable`].includes(n.name)?`table`:n&&[`cvx-kit`,`cvx-kit/querying`].includes(n.source)&&n.name===`createQueryEngine`?`engine`:null}let m=o.get(d),h=m?p(m):null;return s.has(d)?h===`foundation`&&s.get(d)===`Query`?`queryRegistry`:null:h}function B(t){let n=_.get(t);return n||(n={nodes:/* @__PURE__ */ new Map,files:/* @__PURE__ */ new Map,imports:/* @__PURE__ */ new Map,resolver:e()},_.set(t,n)),n}function*V(e,t){if(t.type===`AwaitExpression`)return yield t.argument;if(t.type===`TSAsExpression`||t.type===`TSSatisfiesExpression`||t.type===`TSNonNullExpression`)return yield t.expression;if(t.type===`Identifier`){if(P(e,t)?.references.some(e=>e.isWrite()&&!e.init))return null;let n=m(e,t);if(n)return yield n;let r=h(e,t);if(r){let e=yield r.expression;if(e===`context`&&r.name===`db`)return`db`;if(e===`page`&&r.name===`page`)return`bounded`;if(e===`table`&&r.name===`publicDto`)return`dtoSchema`;if(e===`foundation`&&r.name===`Query`)return`queryRegistry`}let i=P(e,t)?.defs[0];if(i?.type===`Parameter`&&(i.node.type===`ArrowFunctionExpression`||i.node.type===`FunctionExpression`)){let t=i.node.parent;if(t?.type===`CallExpression`&&t.arguments[0]===i.node&&i.node.params[0]===i.name&&(t.callee.type===`Identifier`||t.callee.type===`MemberExpression`)){let n=p(e,t.callee);if(n&&H(n))return`context`}if(t?.type===`CallExpression`&&t.callee.type===`MemberExpression`){let e=yield t.callee.object,n=N(t.callee);if(n===`handler`&&e===`queryOperation`&&t.arguments[0]===i.node&&i.node.params[1]===i.name)return`context`;if(i.node.params[0]!==i.name)return null;if((n===`execute`||n===`paginate`)&&t.arguments[1]===i.node&&(e===`stream`||e===`relationship`))return`bounded`;if(n===`then`&&t.arguments[0]===i.node&&(e===`bounded`||e===`page`))return e}let n=i.node.parent,r=n?.type===`Property`?n.parent:null,a=r?.type===`ObjectExpression`?r.parent:null,o=a?.type===`CallExpression`?p(e,a.callee):null;if(n?.type===`Property`&&(n.computed?M(n.key):I(n.key))===`operations`&&a?.type===`CallExpression`&&a.arguments[0]===r&&(yield a.callee)===`queryRegistry`&&r?.type===`ObjectExpression`&&i.node.params[0]?.type===`ObjectPattern`&&i.node.params[0].properties.some(e=>e.type===`Property`&&e.value===i.name&&(e.computed?M(e.key):I(e.key))===`query`)&&W(e,r))return`queryOperation`;if(n?.type===`Property`&&(n.computed?M(n.key):I(n.key))===`handler`&&a?.type===`CallExpression`&&a.arguments[0]===r&&i.node.params[1]===i.name&&(yield a.callee)===`queryOperation`||n?.type===`Property`&&(n.computed?M(n.key):I(n.key))===`handler`&&i.node.params[0]===i.name&&o&&(a?.type===`CallExpression`&&a.arguments[0]===r&&(a.callee.type===`Identifier`||a.callee.type===`MemberExpression`)&&H(o)||b(e,o.source)&&/^(?:auth|role|admin|system)(?:Query|Mutation)$/.test(o.name)))return`context`}let a=p(e,t);return a&&[`zod`,`zod/v4`,`convex/values`].includes(a.source)&&[`z`,`v`,`*`,`default`].includes(a.name)?`validator`:a?R(e,a):null}if(t.type===`MemberExpression`){let n=p(e,t);if(n){let t=R(e,n);if(t)return t}let r=yield t.object,i=N(t);return r===`context`&&i===`db`?`db`:r===`foundation`&&i===`Query`?`queryRegistry`:r===`reader`?`stream`:r===`page`&&i===`page`?`bounded`:r===`table`&&[`publicDto`,`dto`].includes(i??``)?`dtoSchema`:r===`validator`?`validator`:null}if(t.type!==`CallExpression`&&t.type!==`NewExpression`)return null;let n=yield t.callee;if(n===`engine`)return`reader`;if(n===`include`&&t.arguments[0]&&(yield t.arguments[0])===`stream`)return`stream`;let r=p(e,t.callee);if(r&&U(r))return`foundation`;if(r&&[`cvx-kit`,`cvx-kit/zod-table`,`cvx-kit/tenancy`].includes(r.source)&&[`zodTable`,`tenantTable`,`zodVariantTable`].includes(r.name))return`table`;if(r&&[`cvx-kit`,`cvx-kit/querying`].includes(r.source)&&r.name===`createQueryEngine`)return`engine`;if(r&&[`cvx-kit`,`cvx-kit/auth`].includes(r.source)&&r.name===`createInclude`)return`include`;if(r?.source===`convex-helpers/server/stream`&&r.name===`stream`&&t.arguments[0]&&(yield t.arguments[0])===`db`)return`db`;if(t.callee.type!==`MemberExpression`)return null;let i=yield t.callee.object,a=N(t.callee);if(i===`table`&&a===`toPublicDto`)return`dto`;if(i===`table`&&[`select`,`dto`].includes(a??``))return`dtoSchema`;if(i===`dtoSchema`&&[`parse`,`parseAsync`].includes(a??``))return`dto`;if(i===`db`&&a===`query`)return`stream`;if(i===`stream`&&a===`relation`)return`relationship`;if(i===`context`&&a===`include`&&t.arguments[0]&&(yield t.arguments[0])===`stream`)return`stream`;if(i===`stream`||i===`relationship`){if([`take`,`execute`].includes(a??``))return`bounded`;if(a===`paginate`)return`page`;if([`withIndex`,`withSearchIndex`,`filter`,`filterWith`,`map`,`flatMap`,`distinct`,`order`,`matching`,`when`,`otherwise`,`fullTableScan`,`where`,`with`].includes(a??``))return i}return i===`bounded`&&a===`map`?`bounded`:i===`validator`?`validator`:null}function H(e){return/_generated\/server(?:\.[cm]?[jt]s)?$/.test(e.source)&&g.includes(e.name)||e.source===`convex/server`&&g.some(t=>e.name===`${t}Generic`)}function U(e){return e.source===`cvx-kit`&&e.name===`createFoundation`||e.source===`cvx-kit/effect`&&e.name===`createEffectFoundation`||[`cvx-kit`,`cvx-kit/components/foundation`].includes(e.source)&&e.name===`Foundation`}function W(e,t){let n=t.properties.find(e=>e.type===`Property`&&(e.computed?M(e.key):I(e.key))===`context`);if(n?.type!==`Property`)return!1;let r=n.value;if(r.type!==`ArrowFunctionExpression`&&r.type!==`FunctionExpression`)return!1;let i=r.params[0];if(i?.type!==`Identifier`||P(e,i)?.references.some(e=>e.isWrite()&&!e.init))return!1;let a=r.body,o=a?.type===`BlockStatement`&&a.body.length===1&&a.body[0].type===`ReturnStatement`?a.body[0].argument:a;return o?.type===`Identifier`&&P(e,o)===P(e,i)}function G(e){return e.type===`Literal`&&String(e.value)===e.value?String(e.value):e.type===`TemplateLiteral`&&e.expressions.length===0?e.quasis[0].value.cooked:null}export{f as appFile,P as binding,j as componentRoot,d as consumerOptions,w as containsComponentReference,L as delegatingBody,I as exportName,F as exportedNames,k as hasCall,p as imported,S as isDbAccess,O as isDbWrite,C as isExternalCall,b as isFunctionsImport,D as isTableChain,h as localDestructured,m as localInitializer,E as memberPath,A as metadata,N as propertyName,v as readProvenance,T as rootMember,y as sourceVisitors,M as staticString,x as typeOnlySource};
|
|
2
2
|
//# sourceMappingURL=ast.mjs.map
|
package/dist/oxlint/ast.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast.mjs","names":["consumerOptions","z","appFile","context","requestedRoot","resolve","root","existsSync","realpathSync","file","relative","filename","sep","imported","node","owner","name","propertyName","def","binding","specifier","exportName","sourceVisitors","visit","text","staticString","source","check","isFunctionsImport","target","dirname","resolveImport","createResolver","typeOnlySource","isDbAccess","isExternalCall","ref","containsComponentReference","property","rootMember","memberPath","isTableChain","isDbWrite","hasCall","metadata","componentRoot","match","scope","variable","exportedNames","names","statement","program","delegatingBody"],"sources":["../../src/oxlint/ast.ts"],"sourcesContent":["import { existsSync, realpathSync } from 'node:fs'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport type { Context, ESTree, RuleMeta, Scope, Visitor } from '@oxlint/plugins'\nimport { z } from 'zod'\nimport { createResolver, resolveImport } from './architecture'\n\nexport const consumerOptions = z.object({ convexDir: z.string().min(1).default('convex') })\n\nexport function appFile(context: Context, filename = context.filename) {\n\tconst requestedRoot = resolve(\n\t\tcontext.cwd,\n\t\tconsumerOptions.parse(context.options[0] ?? {}).convexDir,\n\t)\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst file = relative(root, existsSync(filename) ? realpathSync(filename) : filename)\n\t\t.split(sep)\n\t\t.join('/')\n\treturn file === '..' || file.startsWith('../') || file.startsWith('/') ? null : file\n}\n\nexport function imported(\n\tcontext: Context,\n\tnode: ESTree.Node,\n): { source: string; name: string } | null {\n\tif (node.type === 'CallExpression') return imported(context, node.callee)\n\tif (node.type === 'MemberExpression') {\n\t\tconst owner = imported(context, node.object)\n\t\tconst name = propertyName(node)\n\t\treturn owner && name && ['*', 'z', 'default'].includes(owner.name)\n\t\t\t? { source: owner.source, name }\n\t\t\t: null\n\t}\n\tif (node.type !== 'Identifier') return null\n\tfor (const def of binding(context, node)?.defs ?? []) {\n\t\tif (\n\t\t\tdef.type !== 'ImportBinding' ||\n\t\t\tdef.parent?.type !== 'ImportDeclaration' ||\n\t\t\tdef.parent.importKind === 'type'\n\t\t)\n\t\t\tcontinue\n\t\tconst specifier = def.node\n\t\tif (specifier.type === 'ImportSpecifier' && specifier.importKind === 'type') continue\n\t\treturn {\n\t\t\tsource: def.parent.source.value,\n\t\t\tname:\n\t\t\t\tspecifier.type === 'ImportSpecifier'\n\t\t\t\t\t? (exportName(specifier.imported) ?? '')\n\t\t\t\t\t: specifier.type === 'ImportDefaultSpecifier'\n\t\t\t\t\t\t? 'default'\n\t\t\t\t\t\t: '*',\n\t\t}\n\t}\n\treturn null\n}\n\nexport function sourceVisitors(\n\tcontext: Context,\n\tcheck: (node: ESTree.Node, source: string) => void,\n): Visitor {\n\tfunction visit(node: ESTree.Node, source: ESTree.Node | null | undefined) {\n\t\tconst text = staticString(source)\n\t\tif (text) check(node, text)\n\t}\n\treturn {\n\t\tImportDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tExportNamedDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tExportAllDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tImportExpression(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tTSImportType(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tCallExpression(node) {\n\t\t\tif (\n\t\t\t\tnode.callee.type === 'Identifier' &&\n\t\t\t\tnode.callee.name === 'require' &&\n\t\t\t\t!binding(context, node.callee)?.defs.length\n\t\t\t)\n\t\t\t\tvisit(node, node.arguments[0])\n\t\t},\n\t}\n}\n\nexport function isFunctionsImport(context: Context, source: string) {\n\tconst target = source.startsWith('.')\n\t\t? resolve(dirname(context.filename), source)\n\t\t: resolveImport(createResolver(), context.filename, source)\n\treturn target !== null && appFile(context, target)?.replace(/\\.[cm]?[jt]s$/, '') === 'functions'\n}\n\nexport function typeOnlySource(node: ESTree.Node) {\n\treturn (\n\t\tnode.type === 'TSImportType' ||\n\t\t(node.type === 'ImportDeclaration' &&\n\t\t\t(node.importKind === 'type' ||\n\t\t\t\t(node.specifiers.length > 0 &&\n\t\t\t\t\tnode.specifiers.every(\n\t\t\t\t\t\t(specifier) => specifier.type === 'ImportSpecifier' && specifier.importKind === 'type',\n\t\t\t\t\t)))) ||\n\t\t((node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') &&\n\t\t\tnode.exportKind === 'type')\n\t)\n}\n\nexport function isDbAccess(node: ESTree.CallExpression) {\n\treturn (\n\t\tnode.callee.type === 'MemberExpression' &&\n\t\tnode.callee.object.type === 'MemberExpression' &&\n\t\tpropertyName(node.callee.object) === 'db'\n\t)\n}\n\nexport function isExternalCall(context: Context, node: ESTree.CallExpression) {\n\tconst ref = imported(context, node.callee)\n\tif (ref && /^(?:node:)?(?:https?|net|tls|fs)(?:\\/|$)|^(?:undici|axios)(?:\\/|$)/.test(ref.source))\n\t\treturn true\n\treturn (\n\t\t(node.callee.type === 'Identifier' &&\n\t\t\tnode.callee.name === 'fetch' &&\n\t\t\t!binding(context, node.callee)?.defs.length) ||\n\t\t(node.callee.type === 'MemberExpression' &&\n\t\t\tpropertyName(node.callee) === 'fetch' &&\n\t\t\tnode.callee.object.type === 'Identifier' &&\n\t\t\tnode.callee.object.name === 'globalThis' &&\n\t\t\t!binding(context, node.callee.object)?.defs.length)\n\t)\n}\n\nexport function containsComponentReference(context: Context, node: ESTree.Node): boolean {\n\tif (node.type === 'MemberExpression') {\n\t\tconst owner = imported(context, node.object)\n\t\tif (owner?.name === 'components' && /_generated\\/api/.test(owner.source)) return true\n\t\treturn containsComponentReference(context, node.object)\n\t}\n\tif (node.type === 'ObjectExpression')\n\t\treturn node.properties.some(\n\t\t\t(property) =>\n\t\t\t\tproperty.type === 'Property' && containsComponentReference(context, property.value),\n\t\t)\n\treturn false\n}\n\nexport function rootMember(node: ESTree.Node): ESTree.Node {\n\treturn node.type === 'MemberExpression' ? rootMember(node.object) : node\n}\n\nexport function memberPath(node: ESTree.Node): string[] {\n\tif (node.type === 'Identifier') return [node.name]\n\tif (node.type === 'MemberExpression')\n\t\treturn [...memberPath(node.object), propertyName(node) ?? '']\n\treturn []\n}\n\nexport function isTableChain(node: ESTree.Node): boolean {\n\tif (node.type === 'MemberExpression')\n\t\treturn propertyName(node) === 'table' || isTableChain(node.object)\n\treturn node.type === 'CallExpression' && isTableChain(node.callee)\n}\n\nexport function isDbWrite(node: ESTree.CallExpression) {\n\treturn (\n\t\tnode.callee.type === 'MemberExpression' &&\n\t\t['insert', 'patch', 'replace', 'delete'].includes(propertyName(node.callee) ?? '') &&\n\t\tnode.callee.object.type === 'MemberExpression' &&\n\t\tpropertyName(node.callee.object) === 'db'\n\t)\n}\n\nexport function hasCall(node: ESTree.Node, name: string): boolean {\n\tif (node.type === 'CallExpression')\n\t\treturn (\n\t\t\t(node.callee.type === 'MemberExpression' &&\n\t\t\t\tpropertyName(node.callee) === name &&\n\t\t\t\t(name !== 'query' || propertyName(node.callee.object) === 'db')) ||\n\t\t\thasCall(node.callee, name)\n\t\t)\n\tif (node.type === 'MemberExpression') return hasCall(node.object, name)\n\treturn false\n}\n\nexport function metadata(description: string, messages: Record<string, string>): RuleMeta {\n\treturn { type: 'problem', docs: { description }, schema: [], messages }\n}\n\nexport function componentRoot(context: Context, filename: string) {\n\tconst requestedRoot = resolve(\n\t\tcontext.cwd,\n\t\tconsumerOptions.parse(context.options[0] ?? {}).convexDir,\n\t)\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst file = relative(root, existsSync(filename) ? realpathSync(filename) : filename)\n\t\t.split(sep)\n\t\t.join('/')\n\tconst match = file.match(/^components\\/([^/]+)(?:\\/|$)/)\n\treturn match ? resolve(root, 'components', match[1]) : null\n}\n\nexport function staticString(node: ESTree.Node | null | undefined) {\n\tif (node?.type === 'Literal' && 'value' in node && String(node.value) === node.value)\n\t\treturn String(node.value)\n\tif (node?.type === 'TemplateLiteral' && node.expressions.length === 0)\n\t\treturn node.quasis[0].value.cooked\n\treturn null\n}\n\nexport function propertyName(node: ESTree.Node): string | null {\n\tif (node.type !== 'MemberExpression') return null\n\treturn node.computed ? staticString(node.property) : node.property.name\n}\n\nexport function binding(context: Context, node: ESTree.Node) {\n\tif (node.type !== 'Identifier') return null\n\tlet scope: Scope | null = context.sourceCode.getScope(node)\n\twhile (scope) {\n\t\tconst variable = scope.set.get(node.name)\n\t\tif (variable) return variable\n\t\tscope = scope.upper\n\t}\n\treturn null\n}\n\nexport function exportedNames(program: ESTree.Program) {\n\tconst names = new Set<string>()\n\tfor (const statement of program.body) {\n\t\tif (statement.type === 'ExportNamedDeclaration' && !statement.source) {\n\t\t\tfor (const specifier of statement.specifiers) names.add(exportName(specifier.local) ?? '')\n\t\t} else if (\n\t\t\tstatement.type === 'ExportDefaultDeclaration' &&\n\t\t\tstatement.declaration.type === 'Identifier'\n\t\t) {\n\t\t\tnames.add(statement.declaration.name)\n\t\t}\n\t}\n\treturn names\n}\n\nexport function exportName(node: ESTree.Node): string | null {\n\treturn node.type === 'Identifier' ? node.name : staticString(node)\n}\n\nexport function delegatingBody(node: ESTree.Node): boolean {\n\tif (node.type === 'CallExpression') return true\n\tif (node.type === 'AwaitExpression') return delegatingBody(node.argument)\n\tif (node.type === 'BlockStatement')\n\t\treturn (\n\t\t\tnode.body.length > 0 &&\n\t\t\tnode.body.every(\n\t\t\t\t(statement) =>\n\t\t\t\t\t(statement.type === 'ReturnStatement' &&\n\t\t\t\t\t\tstatement.argument !== null &&\n\t\t\t\t\t\tdelegatingBody(statement.argument)) ||\n\t\t\t\t\t(statement.type === 'ExpressionStatement' && delegatingBody(statement.expression)),\n\t\t\t)\n\t\t)\n\treturn false\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ast.mjs","names":["consumerOptions","z","appFile","context","requestedRoot","resolve","root","existsSync","realpathSync","file","relative","filename","sep","imported","active","node","owner","name","propertyName","initializer","localInitializer","member","localDestructured","def","binding","specifier","exportName","variable","reference","property","staticString","nativeReadBuilders","provenanceCaches","readProvenance","cache","provenanceCache","stack","evaluateReadProvenance","result","frame","step","sourceVisitors","visit","text","source","check","isFunctionsImport","target","dirname","resolveImport","createResolver","typeOnlySource","isDbAccess","isExternalCall","ref","containsComponentReference","rootMember","memberPath","isTableChain","isDbWrite","hasCall","metadata","componentRoot","match","scope","exportedNames","names","statement","program","delegatingBody","importedReadProvenance","key","physicalReadProvenance","parsed","parseSync","readFileSync","imports","declarations","members","exports","declaration","item","physicalString","local","factoryImport","importedFactory","init","evaluate","value","factory","foundationFactory","callbackCall","nativeReadBuilder","method","object","call","p","registryPreservesContext","importedValue","callee","callback","host","r","body","returned"],"sources":["../../src/oxlint/ast.ts"],"sourcesContent":["import { existsSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport type { Context, ESTree, RuleMeta, Scope, Visitor } from '@oxlint/plugins'\nimport { z } from 'zod'\nimport { parseSync, type Node } from 'oxc-parser'\nimport { createResolver, resolveImport } from './architecture'\n\nexport const consumerOptions = z.object({ convexDir: z.string().min(1).default('convex') })\n\nexport function appFile(context: Context, filename = context.filename) {\n\tconst requestedRoot = resolve(\n\t\tcontext.cwd,\n\t\tconsumerOptions.parse(context.options[0] ?? {}).convexDir,\n\t)\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst file = relative(root, existsSync(filename) ? realpathSync(filename) : filename)\n\t\t.split(sep)\n\t\t.join('/')\n\treturn file === '..' || file.startsWith('../') || file.startsWith('/') ? null : file\n}\n\nexport function imported(\n\tcontext: Context,\n\tnode: ESTree.Node,\n\tactive = new Set<ESTree.Node>(),\n): { source: string; name: string } | null {\n\tif (active.has(node) || active.size > 32) return null\n\tactive = new Set(active).add(node)\n\tif (\n\t\tnode.type === 'TSAsExpression' ||\n\t\tnode.type === 'TSSatisfiesExpression' ||\n\t\tnode.type === 'TSNonNullExpression'\n\t)\n\t\treturn imported(context, node.expression, active)\n\tif (node.type === 'CallExpression') return imported(context, node.callee, active)\n\tif (node.type === 'MemberExpression') {\n\t\tconst owner = imported(context, node.object, active)\n\t\tconst name = propertyName(node)\n\t\treturn owner && name && ['*', 'z', 'v', 'default'].includes(owner.name)\n\t\t\t? { source: owner.source, name }\n\t\t\t: null\n\t}\n\tif (node.type !== 'Identifier') return null\n\tconst initializer = localInitializer(context, node)\n\tif (\n\t\tinitializer &&\n\t\tinitializer.type !== 'CallExpression' &&\n\t\tinitializer.type !== 'AwaitExpression'\n\t)\n\t\treturn imported(context, initializer, active)\n\tconst member = localDestructured(context, node)\n\tif (member) {\n\t\tconst owner = imported(context, member.expression, active)\n\t\treturn owner && ['*', 'z', 'v', 'default'].includes(owner.name)\n\t\t\t? { source: owner.source, name: member.name }\n\t\t\t: null\n\t}\n\tfor (const def of binding(context, node)?.defs ?? []) {\n\t\tif (\n\t\t\tdef.type !== 'ImportBinding' ||\n\t\t\tdef.parent?.type !== 'ImportDeclaration' ||\n\t\t\tdef.parent.importKind === 'type'\n\t\t)\n\t\t\tcontinue\n\t\tconst specifier = def.node\n\t\tif (specifier.type === 'ImportSpecifier' && specifier.importKind === 'type') continue\n\t\treturn {\n\t\t\tsource: def.parent.source.value,\n\t\t\tname:\n\t\t\t\tspecifier.type === 'ImportSpecifier'\n\t\t\t\t\t? (exportName(specifier.imported) ?? '')\n\t\t\t\t\t: specifier.type === 'ImportDefaultSpecifier'\n\t\t\t\t\t\t? 'default'\n\t\t\t\t\t\t: '*',\n\t\t}\n\t}\n\treturn null\n}\n\n/** Follow immutable bindings only; a same-named parameter never inherits outer provenance. */\nexport function localInitializer(context: Context, node: ESTree.Node): ESTree.Node | null {\n\tconst variable = binding(context, node)\n\tif (!variable || variable.references.some((reference) => reference.isWrite() && !reference.init))\n\t\treturn null\n\tconst def = variable.defs.length === 1 ? variable.defs[0] : null\n\treturn def?.type === 'Variable' &&\n\t\tdef.parent?.type === 'VariableDeclaration' &&\n\t\tdef.parent.kind === 'const' &&\n\t\tdef.node.type === 'VariableDeclarator' &&\n\t\tdef.node.id.type === 'Identifier'\n\t\t? def.node.init\n\t\t: null\n}\n\nexport function localDestructured(context: Context, node: ESTree.Node) {\n\tconst variable = binding(context, node)\n\tif (!variable || variable.references.some((reference) => reference.isWrite() && !reference.init))\n\t\treturn null\n\tconst def = variable.defs.length === 1 ? variable.defs[0] : null\n\tif (\n\t\tdef?.type !== 'Variable' ||\n\t\tdef.parent?.type !== 'VariableDeclaration' ||\n\t\tdef.parent.kind !== 'const' ||\n\t\tdef.node.type !== 'VariableDeclarator' ||\n\t\tdef.node.id.type !== 'ObjectPattern' ||\n\t\t!def.node.init\n\t)\n\t\treturn null\n\tfor (const property of def.node.id.properties) {\n\t\tif (\n\t\t\tproperty.type === 'Property' &&\n\t\t\tproperty.value.type === 'Identifier' &&\n\t\t\tproperty.value.name === variable.name\n\t\t) {\n\t\t\tconst name = property.computed ? staticString(property.key) : exportName(property.key)\n\t\t\tif (name) return { expression: def.node.init, name }\n\t\t}\n\t}\n\treturn null\n}\n\nexport type ReadProvenance =\n\t| 'table'\n\t| 'dtoSchema'\n\t| 'dto'\n\t| 'engine'\n\t| 'reader'\n\t| 'include'\n\t| 'context'\n\t| 'db'\n\t| 'stream'\n\t| 'relationship'\n\t| 'bounded'\n\t| 'page'\n\t| 'validator'\n\t| 'foundation'\n\t| 'queryRegistry'\n\t| 'queryOperation'\n\nconst nativeReadBuilders = ['query', 'internalQuery', 'mutation', 'internalMutation']\n\n// Weak keys keep caches local to a lint invocation; no file state survives a new context.\nconst provenanceCaches = new WeakMap<\n\tContext,\n\t{\n\t\tnodes: Map<ESTree.Node, ReadProvenance | null>\n\t\tfiles: Map<string, ReturnType<typeof parseSync>>\n\t\timports: Map<string, ReadProvenance | null>\n\t\tresolver: ReturnType<typeof createResolver>\n\t}\n>()\n/** Suspend dependencies on a work stack; null in-progress entries terminate alias cycles. */\nexport function readProvenance(context: Context, node: ESTree.Node): ReadProvenance | null {\n\tconst cache = provenanceCache(context).nodes\n\tif (cache.has(node)) return cache.get(node) ?? null\n\tcache.set(node, null)\n\tconst stack = [{ node, evaluation: evaluateReadProvenance(context, node) }]\n\tlet result: ReadProvenance | null = null\n\twhile (stack.length) {\n\t\tconst frame = stack[stack.length - 1]!\n\t\tconst step = frame.evaluation.next(result)\n\t\tif (step.done) {\n\t\t\tresult = step.value\n\t\t\tcache.set(frame.node, result)\n\t\t\tstack.pop()\n\t\t} else if (cache.has(step.value)) {\n\t\t\tresult = cache.get(step.value) ?? null\n\t\t} else {\n\t\t\tcache.set(step.value, null)\n\t\t\tstack.push({ node: step.value, evaluation: evaluateReadProvenance(context, step.value) })\n\t\t\tresult = null\n\t\t}\n\t}\n\treturn result\n}\nexport function sourceVisitors(\n\tcontext: Context,\n\tcheck: (node: ESTree.Node, source: string) => void,\n): Visitor {\n\tfunction visit(node: ESTree.Node, source: ESTree.Node | null | undefined) {\n\t\tconst text = staticString(source)\n\t\tif (text) check(node, text)\n\t}\n\treturn {\n\t\tImportDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tExportNamedDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tExportAllDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tImportExpression(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tTSImportType(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tCallExpression(node) {\n\t\t\tif (\n\t\t\t\tnode.callee.type === 'Identifier' &&\n\t\t\t\tnode.callee.name === 'require' &&\n\t\t\t\t!binding(context, node.callee)?.defs.length\n\t\t\t)\n\t\t\t\tvisit(node, node.arguments[0])\n\t\t},\n\t}\n}\n\nexport function isFunctionsImport(context: Context, source: string) {\n\tconst target = source.startsWith('.')\n\t\t? resolve(dirname(context.filename), source)\n\t\t: resolveImport(createResolver(), context.filename, source)\n\treturn target !== null && appFile(context, target)?.replace(/\\.[cm]?[jt]s$/, '') === 'functions'\n}\n\nexport function typeOnlySource(node: ESTree.Node) {\n\treturn (\n\t\tnode.type === 'TSImportType' ||\n\t\t(node.type === 'ImportDeclaration' &&\n\t\t\t(node.importKind === 'type' ||\n\t\t\t\t(node.specifiers.length > 0 &&\n\t\t\t\t\tnode.specifiers.every(\n\t\t\t\t\t\t(specifier) => specifier.type === 'ImportSpecifier' && specifier.importKind === 'type',\n\t\t\t\t\t)))) ||\n\t\t((node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') &&\n\t\t\tnode.exportKind === 'type')\n\t)\n}\n\nexport function isDbAccess(node: ESTree.CallExpression) {\n\treturn (\n\t\tnode.callee.type === 'MemberExpression' &&\n\t\tnode.callee.object.type === 'MemberExpression' &&\n\t\tpropertyName(node.callee.object) === 'db'\n\t)\n}\n\nexport function isExternalCall(context: Context, node: ESTree.CallExpression) {\n\tconst ref = imported(context, node.callee)\n\tif (ref && /^(?:node:)?(?:https?|net|tls|fs)(?:\\/|$)|^(?:undici|axios)(?:\\/|$)/.test(ref.source))\n\t\treturn true\n\treturn (\n\t\t(node.callee.type === 'Identifier' &&\n\t\t\tnode.callee.name === 'fetch' &&\n\t\t\t!binding(context, node.callee)?.defs.length) ||\n\t\t(node.callee.type === 'MemberExpression' &&\n\t\t\tpropertyName(node.callee) === 'fetch' &&\n\t\t\tnode.callee.object.type === 'Identifier' &&\n\t\t\tnode.callee.object.name === 'globalThis' &&\n\t\t\t!binding(context, node.callee.object)?.defs.length)\n\t)\n}\n\nexport function containsComponentReference(context: Context, node: ESTree.Node): boolean {\n\tif (node.type === 'MemberExpression') {\n\t\tconst owner = imported(context, node.object)\n\t\tif (owner?.name === 'components' && /_generated\\/api/.test(owner.source)) return true\n\t\treturn containsComponentReference(context, node.object)\n\t}\n\tif (node.type === 'ObjectExpression')\n\t\treturn node.properties.some(\n\t\t\t(property) =>\n\t\t\t\tproperty.type === 'Property' && containsComponentReference(context, property.value),\n\t\t)\n\treturn false\n}\n\nexport function rootMember(node: ESTree.Node): ESTree.Node {\n\treturn node.type === 'MemberExpression' ? rootMember(node.object) : node\n}\n\nexport function memberPath(node: ESTree.Node): string[] {\n\tif (node.type === 'Identifier') return [node.name]\n\tif (node.type === 'MemberExpression')\n\t\treturn [...memberPath(node.object), propertyName(node) ?? '']\n\treturn []\n}\n\nexport function isTableChain(node: ESTree.Node): boolean {\n\tif (node.type === 'MemberExpression')\n\t\treturn propertyName(node) === 'table' || isTableChain(node.object)\n\treturn node.type === 'CallExpression' && isTableChain(node.callee)\n}\n\nexport function isDbWrite(node: ESTree.CallExpression) {\n\treturn (\n\t\tnode.callee.type === 'MemberExpression' &&\n\t\t['insert', 'patch', 'replace', 'delete'].includes(propertyName(node.callee) ?? '') &&\n\t\tnode.callee.object.type === 'MemberExpression' &&\n\t\tpropertyName(node.callee.object) === 'db'\n\t)\n}\n\nexport function hasCall(node: ESTree.Node, name: string): boolean {\n\tif (node.type === 'CallExpression')\n\t\treturn (\n\t\t\t(node.callee.type === 'MemberExpression' &&\n\t\t\t\tpropertyName(node.callee) === name &&\n\t\t\t\t(name !== 'query' || propertyName(node.callee.object) === 'db')) ||\n\t\t\thasCall(node.callee, name)\n\t\t)\n\tif (node.type === 'MemberExpression') return hasCall(node.object, name)\n\treturn false\n}\n\nexport function metadata(description: string, messages: Record<string, string>): RuleMeta {\n\treturn { type: 'problem', docs: { description }, schema: [], messages }\n}\n\nexport function componentRoot(context: Context, filename: string) {\n\tconst requestedRoot = resolve(\n\t\tcontext.cwd,\n\t\tconsumerOptions.parse(context.options[0] ?? {}).convexDir,\n\t)\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst file = relative(root, existsSync(filename) ? realpathSync(filename) : filename)\n\t\t.split(sep)\n\t\t.join('/')\n\tconst match = file.match(/^components\\/([^/]+)(?:\\/|$)/)\n\treturn match ? resolve(root, 'components', match[1]) : null\n}\n\nexport function staticString(node: ESTree.Node | null | undefined) {\n\tif (node?.type === 'Literal' && 'value' in node && String(node.value) === node.value)\n\t\treturn String(node.value)\n\tif (node?.type === 'TemplateLiteral' && node.expressions.length === 0)\n\t\treturn node.quasis[0].value.cooked\n\treturn null\n}\n\nexport function propertyName(node: ESTree.Node): string | null {\n\tif (node.type !== 'MemberExpression') return null\n\treturn node.computed ? staticString(node.property) : node.property.name\n}\n\nexport function binding(context: Context, node: ESTree.Node) {\n\tif (node.type !== 'Identifier') return null\n\tlet scope: Scope | null = context.sourceCode.getScope(node)\n\twhile (scope) {\n\t\tconst variable = scope.set.get(node.name)\n\t\tif (variable) return variable\n\t\tscope = scope.upper\n\t}\n\treturn null\n}\n\nexport function exportedNames(program: ESTree.Program) {\n\tconst names = new Set<string>()\n\tfor (const statement of program.body) {\n\t\tif (statement.type === 'ExportNamedDeclaration' && !statement.source) {\n\t\t\tfor (const specifier of statement.specifiers) names.add(exportName(specifier.local) ?? '')\n\t\t} else if (\n\t\t\tstatement.type === 'ExportDefaultDeclaration' &&\n\t\t\tstatement.declaration.type === 'Identifier'\n\t\t) {\n\t\t\tnames.add(statement.declaration.name)\n\t\t}\n\t}\n\treturn names\n}\n\nexport function exportName(node: ESTree.Node): string | null {\n\treturn node.type === 'Identifier' ? node.name : staticString(node)\n}\n\nexport function delegatingBody(node: ESTree.Node): boolean {\n\tif (node.type === 'CallExpression') return true\n\tif (node.type === 'AwaitExpression') return delegatingBody(node.argument)\n\tif (node.type === 'BlockStatement')\n\t\treturn (\n\t\t\tnode.body.length > 0 &&\n\t\t\tnode.body.every(\n\t\t\t\t(statement) =>\n\t\t\t\t\t(statement.type === 'ReturnStatement' &&\n\t\t\t\t\t\tstatement.argument !== null &&\n\t\t\t\t\t\tdelegatingBody(statement.argument)) ||\n\t\t\t\t\t(statement.type === 'ExpressionStatement' && delegatingBody(statement.expression)),\n\t\t\t)\n\t\t)\n\treturn false\n}\n\n/** Read only the owning schema/facade's top-level declaration, never arbitrary helper bodies. */\nfunction importedReadProvenance(\n\tcontext: Context,\n\tref: { source: string; name: string },\n): ReadProvenance | null {\n\tconst cache = provenanceCache(context)\n\tconst target = resolveImport(cache.resolver, context.filename, ref.source)\n\tconst file = target && appFile(context, target)\n\tif (\n\t\t!target ||\n\t\t!file ||\n\t\t!/^(?:domain\\/.+\\/schema\\.ts|querying\\.ts|foundation\\.ts)$/.test(file) ||\n\t\t!existsSync(target)\n\t)\n\t\treturn null\n\tconst key = `${target}:${ref.name}`\n\tif (cache.imports.has(key)) return cache.imports.get(key) ?? null\n\tconst result = physicalReadProvenance(context, target, ref.name)\n\tcache.imports.set(key, result)\n\treturn result\n}\nfunction physicalReadProvenance(\n\tcontext: Context,\n\ttarget: string,\n\tname: string,\n): ReadProvenance | null {\n\tconst cache = provenanceCache(context)\n\tlet parsed = cache.files.get(target)\n\tif (!parsed) {\n\t\tparsed = parseSync(target, readFileSync(target, 'utf8'))\n\t\tcache.files.set(target, parsed)\n\t}\n\tif (parsed.errors.length) return null\n\tconst imports = new Map<string, { source: string; name: string }>()\n\tconst declarations = new Map<string, Node>()\n\tconst members = new Map<string, string>()\n\tconst exports = new Map<string, string>()\n\tfor (const statement of parsed.program.body) {\n\t\tif (statement.type === 'ImportDeclaration' && statement.importKind !== 'type') {\n\t\t\tfor (const specifier of statement.specifiers) {\n\t\t\t\tif (specifier.type === 'ImportSpecifier' && specifier.importKind !== 'type')\n\t\t\t\t\timports.set(specifier.local.name, {\n\t\t\t\t\t\tsource: statement.source.value,\n\t\t\t\t\t\tname: specifier.imported.type === 'Identifier' ? specifier.imported.name : '',\n\t\t\t\t\t})\n\t\t\t\tif (specifier.type === 'ImportNamespaceSpecifier')\n\t\t\t\t\timports.set(specifier.local.name, { source: statement.source.value, name: '*' })\n\t\t\t}\n\t\t}\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration?.type === 'VariableDeclaration' && declaration.kind === 'const') {\n\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\tif (!item.init) continue\n\t\t\t\tif (item.id.type === 'ObjectPattern') {\n\t\t\t\t\tfor (const property of item.id.properties) {\n\t\t\t\t\t\tif (property.type !== 'Property' || property.value.type !== 'Identifier') continue\n\t\t\t\t\t\tconst member = property.computed\n\t\t\t\t\t\t\t? physicalString(property.key)\n\t\t\t\t\t\t\t: property.key.type === 'Identifier'\n\t\t\t\t\t\t\t\t? property.key.name\n\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tif (!member) continue\n\t\t\t\t\t\tdeclarations.set(property.value.name, item.init)\n\t\t\t\t\t\tmembers.set(property.value.name, member)\n\t\t\t\t\t\tif (statement.type === 'ExportNamedDeclaration')\n\t\t\t\t\t\t\texports.set(property.value.name, property.value.name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (item.id.type !== 'Identifier') continue\n\t\t\t\tdeclarations.set(item.id.name, item.init)\n\t\t\t\tif (statement.type === 'ExportNamedDeclaration') exports.set(item.id.name, item.id.name)\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\tstatement.type === 'ExportNamedDeclaration' &&\n\t\t\t!statement.source &&\n\t\t\tstatement.exportKind !== 'type'\n\t\t) {\n\t\t\tfor (const specifier of statement.specifiers)\n\t\t\t\tif (\n\t\t\t\t\tspecifier.exportKind !== 'type' &&\n\t\t\t\t\tspecifier.local.type === 'Identifier' &&\n\t\t\t\t\tspecifier.exported.type === 'Identifier'\n\t\t\t\t)\n\t\t\t\t\texports.set(specifier.exported.name, specifier.local.name)\n\t\t}\n\t}\n\tconst local = exports.get(name)\n\tif (!local) return null\n\tfunction factoryImport(\n\t\tnode: Node,\n\t\tactive = new Set<string>(),\n\t): { source: string; name: string } | null {\n\t\tif (node.type === 'Identifier') {\n\t\t\tif (active.has(node.name) || active.size > 16) return null\n\t\t\tconst importedFactory = imports.get(node.name)\n\t\t\tif (importedFactory) return importedFactory\n\t\t\tconst init = declarations.get(node.name)\n\t\t\treturn init ? factoryImport(init, new Set(active).add(node.name)) : null\n\t\t}\n\t\tif (node.type === 'MemberExpression' && !node.computed && node.property.type === 'Identifier') {\n\t\t\tconst owner = factoryImport(node.object, active)\n\t\t\tif (owner?.name === '*') return { source: owner.source, name: node.property.name }\n\t\t}\n\t\treturn null\n\t}\n\tfunction evaluate(node: Node, active = new Set<string>()): ReadProvenance | null {\n\t\tif (\n\t\t\tnode.type === 'TSAsExpression' ||\n\t\t\tnode.type === 'TSSatisfiesExpression' ||\n\t\t\tnode.type === 'ParenthesizedExpression'\n\t\t)\n\t\t\treturn evaluate(node.expression, active)\n\t\tif (node.type === 'Identifier') {\n\t\t\tif (active.has(node.name) || active.size > 16) return null\n\t\t\tconst init = declarations.get(node.name)\n\t\t\tconst value = init ? evaluate(init, new Set(active).add(node.name)) : null\n\t\t\treturn members.has(node.name)\n\t\t\t\t? value === 'foundation' && members.get(node.name) === 'Query'\n\t\t\t\t\t? 'queryRegistry'\n\t\t\t\t\t: null\n\t\t\t\t: value\n\t\t}\n\t\tif (node.type === 'MemberExpression' && !node.computed && node.property.type === 'Identifier')\n\t\t\treturn evaluate(node.object, active) === 'foundation' && node.property.name === 'Query'\n\t\t\t\t? 'queryRegistry'\n\t\t\t\t: null\n\t\tif (node.type !== 'CallExpression' && node.type !== 'NewExpression') return null\n\t\tconst factory = factoryImport(node.callee)\n\t\tif (factory && foundationFactory(factory)) return 'foundation'\n\t\tif (\n\t\t\tfactory &&\n\t\t\t['cvx-kit', 'cvx-kit/zod-table', 'cvx-kit/tenancy'].includes(factory.source) &&\n\t\t\t['zodTable', 'tenantTable', 'zodVariantTable'].includes(factory.name)\n\t\t)\n\t\t\treturn 'table'\n\t\tif (\n\t\t\tfactory &&\n\t\t\t['cvx-kit', 'cvx-kit/querying'].includes(factory.source) &&\n\t\t\tfactory.name === 'createQueryEngine'\n\t\t)\n\t\t\treturn 'engine'\n\t\treturn null\n\t}\n\tconst declaration = declarations.get(local)\n\tconst value = declaration ? evaluate(declaration) : null\n\treturn members.has(local)\n\t\t? value === 'foundation' && members.get(local) === 'Query'\n\t\t\t? 'queryRegistry'\n\t\t\t: null\n\t\t: value\n}\n\nfunction provenanceCache(context: Context) {\n\tlet cache = provenanceCaches.get(context)\n\tif (!cache) {\n\t\tcache = { nodes: new Map(), files: new Map(), imports: new Map(), resolver: createResolver() }\n\t\tprovenanceCaches.set(context, cache)\n\t}\n\treturn cache\n}\n\nfunction* evaluateReadProvenance(\n\tcontext: Context,\n\tnode: ESTree.Node,\n): Generator<ESTree.Node, ReadProvenance | null, ReadProvenance | null> {\n\tif (node.type === 'AwaitExpression') return yield node.argument\n\tif (\n\t\tnode.type === 'TSAsExpression' ||\n\t\tnode.type === 'TSSatisfiesExpression' ||\n\t\tnode.type === 'TSNonNullExpression'\n\t)\n\t\treturn yield node.expression\n\tif (node.type === 'Identifier') {\n\t\tconst variable = binding(context, node)\n\t\tif (variable?.references.some((reference) => reference.isWrite() && !reference.init))\n\t\t\treturn null\n\t\tconst initializer = localInitializer(context, node)\n\t\tif (initializer) return yield initializer\n\t\tconst member = localDestructured(context, node)\n\t\tif (member) {\n\t\t\tconst owner = yield member.expression\n\t\t\tif (owner === 'context' && member.name === 'db') return 'db'\n\t\t\tif (owner === 'page' && member.name === 'page') return 'bounded'\n\t\t\tif (owner === 'table' && member.name === 'publicDto') return 'dtoSchema'\n\t\t\tif (owner === 'foundation' && member.name === 'Query') return 'queryRegistry'\n\t\t}\n\t\tconst def = binding(context, node)?.defs[0]\n\t\tif (\n\t\t\tdef?.type === 'Parameter' &&\n\t\t\t(def.node.type === 'ArrowFunctionExpression' || def.node.type === 'FunctionExpression')\n\t\t) {\n\t\t\tconst callbackCall = def.node.parent\n\t\t\tif (\n\t\t\t\tcallbackCall?.type === 'CallExpression' &&\n\t\t\t\tcallbackCall.arguments[0] === def.node &&\n\t\t\t\tdef.node.params[0] === def.name &&\n\t\t\t\t(callbackCall.callee.type === 'Identifier' ||\n\t\t\t\t\tcallbackCall.callee.type === 'MemberExpression')\n\t\t\t) {\n\t\t\t\tconst ref = imported(context, callbackCall.callee)\n\t\t\t\tif (ref && nativeReadBuilder(ref)) return 'context'\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcallbackCall?.type === 'CallExpression' &&\n\t\t\t\tcallbackCall.callee.type === 'MemberExpression'\n\t\t\t) {\n\t\t\t\tconst owner = yield callbackCall.callee.object\n\t\t\t\tconst method = propertyName(callbackCall.callee)\n\t\t\t\tif (\n\t\t\t\t\tmethod === 'handler' &&\n\t\t\t\t\towner === 'queryOperation' &&\n\t\t\t\t\tcallbackCall.arguments[0] === def.node &&\n\t\t\t\t\tdef.node.params[1] === def.name\n\t\t\t\t)\n\t\t\t\t\treturn 'context'\n\t\t\t\tif (def.node.params[0] !== def.name) return null\n\t\t\t\tif (\n\t\t\t\t\t(method === 'execute' || method === 'paginate') &&\n\t\t\t\t\tcallbackCall.arguments[1] === def.node &&\n\t\t\t\t\t(owner === 'stream' || owner === 'relationship')\n\t\t\t\t)\n\t\t\t\t\treturn 'bounded'\n\t\t\t\tif (\n\t\t\t\t\tmethod === 'then' &&\n\t\t\t\t\tcallbackCall.arguments[0] === def.node &&\n\t\t\t\t\t(owner === 'bounded' || owner === 'page')\n\t\t\t\t)\n\t\t\t\t\treturn owner\n\t\t\t}\n\t\t\tconst property = def.node.parent\n\t\t\tconst object = property?.type === 'Property' ? property.parent : null\n\t\t\tconst call = object?.type === 'ObjectExpression' ? object.parent : null\n\t\t\tconst ref = call?.type === 'CallExpression' ? imported(context, call.callee) : null\n\t\t\tif (\n\t\t\t\tproperty?.type === 'Property' &&\n\t\t\t\t(property.computed ? staticString(property.key) : exportName(property.key)) ===\n\t\t\t\t\t'operations' &&\n\t\t\t\tcall?.type === 'CallExpression' &&\n\t\t\t\tcall.arguments[0] === object &&\n\t\t\t\t(yield call.callee) === 'queryRegistry' &&\n\t\t\t\tobject?.type === 'ObjectExpression' &&\n\t\t\t\tdef.node.params[0]?.type === 'ObjectPattern' &&\n\t\t\t\tdef.node.params[0].properties.some(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.type === 'Property' &&\n\t\t\t\t\t\tp.value === def.name &&\n\t\t\t\t\t\t(p.computed ? staticString(p.key) : exportName(p.key)) === 'query',\n\t\t\t\t) &&\n\t\t\t\tregistryPreservesContext(context, object)\n\t\t\t)\n\t\t\t\treturn 'queryOperation'\n\n\t\t\tif (\n\t\t\t\tproperty?.type === 'Property' &&\n\t\t\t\t(property.computed ? staticString(property.key) : exportName(property.key)) === 'handler' &&\n\t\t\t\tcall?.type === 'CallExpression' &&\n\t\t\t\tcall.arguments[0] === object &&\n\t\t\t\tdef.node.params[1] === def.name &&\n\t\t\t\t(yield call.callee) === 'queryOperation'\n\t\t\t)\n\t\t\t\treturn 'context'\n\n\t\t\tif (\n\t\t\t\tproperty?.type === 'Property' &&\n\t\t\t\t(property.computed ? staticString(property.key) : exportName(property.key)) === 'handler' &&\n\t\t\t\tdef.node.params[0] === def.name &&\n\t\t\t\tref &&\n\t\t\t\t((call?.type === 'CallExpression' &&\n\t\t\t\t\tcall.arguments[0] === object &&\n\t\t\t\t\t(call.callee.type === 'Identifier' || call.callee.type === 'MemberExpression') &&\n\t\t\t\t\tnativeReadBuilder(ref)) ||\n\t\t\t\t\t(isFunctionsImport(context, ref.source) &&\n\t\t\t\t\t\t/^(?:auth|role|admin|system)(?:Query|Mutation)$/.test(ref.name)))\n\t\t\t)\n\t\t\t\treturn 'context'\n\t\t}\n\t\tconst ref = imported(context, node)\n\t\tif (\n\t\t\tref &&\n\t\t\t['zod', 'zod/v4', 'convex/values'].includes(ref.source) &&\n\t\t\t['z', 'v', '*', 'default'].includes(ref.name)\n\t\t)\n\t\t\treturn 'validator'\n\t\tif (ref) return importedReadProvenance(context, ref)\n\t\treturn null\n\t}\n\tif (node.type === 'MemberExpression') {\n\t\tconst ref = imported(context, node)\n\t\tif (ref) {\n\t\t\tconst importedValue = importedReadProvenance(context, ref)\n\t\t\tif (importedValue) return importedValue\n\t\t}\n\t\tconst owner = yield node.object\n\t\tconst name = propertyName(node)\n\t\tif (owner === 'context' && name === 'db') return 'db'\n\t\tif (owner === 'foundation' && name === 'Query') return 'queryRegistry'\n\t\tif (owner === 'reader') return 'stream'\n\t\tif (owner === 'page' && name === 'page') return 'bounded'\n\t\tif (owner === 'table' && ['publicDto', 'dto'].includes(name ?? '')) return 'dtoSchema'\n\t\tif (owner === 'validator') return 'validator'\n\t\treturn null\n\t}\n\tif (node.type !== 'CallExpression' && node.type !== 'NewExpression') return null\n\tconst callee = yield node.callee\n\tif (callee === 'engine') return 'reader'\n\tif (callee === 'include' && node.arguments[0] && (yield node.arguments[0]) === 'stream')\n\t\treturn 'stream'\n\tconst ref = imported(context, node.callee)\n\tif (ref && foundationFactory(ref)) return 'foundation'\n\tif (\n\t\tref &&\n\t\t['cvx-kit', 'cvx-kit/zod-table', 'cvx-kit/tenancy'].includes(ref.source) &&\n\t\t['zodTable', 'tenantTable', 'zodVariantTable'].includes(ref.name)\n\t)\n\t\treturn 'table'\n\tif (\n\t\tref &&\n\t\t['cvx-kit', 'cvx-kit/querying'].includes(ref.source) &&\n\t\tref.name === 'createQueryEngine'\n\t)\n\t\treturn 'engine'\n\tif (ref && ['cvx-kit', 'cvx-kit/auth'].includes(ref.source) && ref.name === 'createInclude')\n\t\treturn 'include'\n\tif (\n\t\tref?.source === 'convex-helpers/server/stream' &&\n\t\tref.name === 'stream' &&\n\t\tnode.arguments[0] &&\n\t\t(yield node.arguments[0]) === 'db'\n\t)\n\t\treturn 'db'\n\tif (node.callee.type !== 'MemberExpression') return null\n\tconst owner = yield node.callee.object\n\tconst name = propertyName(node.callee)\n\tif (owner === 'table' && name === 'toPublicDto') return 'dto'\n\tif (owner === 'table' && ['select', 'dto'].includes(name ?? '')) return 'dtoSchema'\n\tif (owner === 'dtoSchema' && ['parse', 'parseAsync'].includes(name ?? '')) return 'dto'\n\tif (owner === 'db' && name === 'query') return 'stream'\n\tif (owner === 'stream' && name === 'relation') return 'relationship'\n\tif (\n\t\towner === 'context' &&\n\t\tname === 'include' &&\n\t\tnode.arguments[0] &&\n\t\t(yield node.arguments[0]) === 'stream'\n\t)\n\t\treturn 'stream'\n\tif (owner === 'stream' || owner === 'relationship') {\n\t\tif (['take', 'execute'].includes(name ?? '')) return 'bounded'\n\t\tif (name === 'paginate') return 'page'\n\t\tif (\n\t\t\t[\n\t\t\t\t'withIndex',\n\t\t\t\t'withSearchIndex',\n\t\t\t\t'filter',\n\t\t\t\t'filterWith',\n\t\t\t\t'map',\n\t\t\t\t'flatMap',\n\t\t\t\t'distinct',\n\t\t\t\t'order',\n\t\t\t\t'matching',\n\t\t\t\t'when',\n\t\t\t\t'otherwise',\n\t\t\t\t'fullTableScan',\n\t\t\t\t'where',\n\t\t\t\t'with',\n\t\t\t].includes(name ?? '')\n\t\t)\n\t\t\treturn owner\n\t}\n\tif (owner === 'bounded' && name === 'map') return 'bounded'\n\tif (owner === 'validator') return 'validator'\n\treturn null\n}\n\n/** Match native registration contracts by both their import source and exported name. */\nfunction nativeReadBuilder(ref: { source: string; name: string }) {\n\treturn (\n\t\t(/_generated\\/server(?:\\.[cm]?[jt]s)?$/.test(ref.source) &&\n\t\t\tnativeReadBuilders.includes(ref.name)) ||\n\t\t(ref.source === 'convex/server' &&\n\t\t\tnativeReadBuilders.some((name) => ref.name === `${name}Generic`))\n\t)\n}\n\nfunction foundationFactory(ref: { source: string; name: string }) {\n\treturn (\n\t\t(ref.source === 'cvx-kit' && ref.name === 'createFoundation') ||\n\t\t(ref.source === 'cvx-kit/effect' && ref.name === 'createEffectFoundation') ||\n\t\t(['cvx-kit', 'cvx-kit/components/foundation'].includes(ref.source) && ref.name === 'Foundation')\n\t)\n}\n\n/** The supported registry mapping passes the host through unchanged. */\nfunction registryPreservesContext(context: Context, object: ESTree.ObjectExpression) {\n\tconst property = object.properties.find(\n\t\t(p) =>\n\t\t\tp.type === 'Property' && (p.computed ? staticString(p.key) : exportName(p.key)) === 'context',\n\t)\n\tif (property?.type !== 'Property') return false\n\tconst callback = property.value\n\tif (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression')\n\t\treturn false\n\tconst host = callback.params[0]\n\tif (\n\t\thost?.type !== 'Identifier' ||\n\t\tbinding(context, host)?.references.some((r) => r.isWrite() && !r.init)\n\t)\n\t\treturn false\n\tconst body = callback.body\n\tconst returned =\n\t\tbody?.type === 'BlockStatement' &&\n\t\tbody.body.length === 1 &&\n\t\tbody.body[0].type === 'ReturnStatement'\n\t\t\t? body.body[0].argument\n\t\t\t: body\n\treturn returned?.type === 'Identifier' && binding(context, returned) === binding(context, host)\n}\n\nfunction physicalString(node: Node): string | null {\n\tif (node.type === 'Literal' && String(node.value) === node.value) return String(node.value)\n\tif (node.type === 'TemplateLiteral' && node.expressions.length === 0)\n\t\treturn node.quasis[0].value.cooked\n\treturn null\n}\n"],"mappings":"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"}
|
package/dist/oxlint.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import { OwnershipRuleName } from "./oxlint/ownership.mjs";
|
|
|
3
3
|
import { Plugin, Rule } from "@oxlint/plugins";
|
|
4
4
|
//#region src/oxlint.d.ts
|
|
5
5
|
export declare function checkArchitecture(options?: ArchitectureOptions): ArchitectureDiagnostic[];
|
|
6
|
-
export type RuleName = OwnershipRuleName | 'component-boundaries' | 'no-component-env' | 'schema-file-boundaries' | 'no-internal-reexports' | 'public-api-first' | 'named-private-helpers' | 'no-raw-builders' | 'no-handwritten-references' | 'domain-import-boundaries' | 'public-functions-in-api' | 'thin-api-adapters' | 'no-inline-enums' | 'no-unbounded-reads' | 'no-manual-timestamps' | 'reserved-domain-file-anatomy' | 'root-facade-ownership';
|
|
6
|
+
export type RuleName = OwnershipRuleName | 'component-boundaries' | 'no-component-env' | 'schema-file-boundaries' | 'no-internal-reexports' | 'public-api-first' | 'named-private-helpers' | 'no-raw-builders' | 'no-handwritten-references' | 'domain-import-boundaries' | 'public-functions-in-api' | 'thin-api-adapters' | 'no-inline-enums' | 'no-unbounded-reads' | 'no-manual-timestamps' | 'reserved-domain-file-anatomy' | 'root-facade-ownership' | 'no-manual-id-projection' | 'no-copied-pagination';
|
|
7
7
|
export declare const rules: Record<RuleName, Rule>;
|
|
8
8
|
declare const plugin: Plugin;
|
|
9
9
|
//#endregion
|
package/dist/oxlint.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createResolver as e,inspectArchitecture as t,resolveImport as n}from"./oxlint/architecture.mjs";import{appFile as r,binding as i,componentRoot as a,exportName as o,exportedNames as s,hasCall as c,imported as l,isDbWrite as u,isFunctionsImport as d,isTableChain as f,metadata as p,propertyName as m,sourceVisitors as h,staticString as g}from"./oxlint/ast.mjs";import{reservedDomainFiles as _}from"./oxlint/reserved-files.mjs";import{ownershipRules as v}from"./oxlint/ownership.mjs";import{basename as y,dirname as b,relative as x,sep as S}from"node:path";function C(e={}){return t(e)}const w=E({...v,"reserved-domain-file-anatomy":_,"root-facade-ownership":{meta:p(`Configure shared kit infrastructure once in its root facade.`,{facade:`Configure {{name}} once in convex/{{file}}; import that facade elsewhere.`}),create(e){if(a(e,e.filename))return{};let t=/* @__PURE__ */ new Set;function n(n){let i=l(e,n.callee);if(!i)return;let a=null;[`cvx-kit`,`cvx-kit/auth`].includes(i.source)&&i.name===`createAuthFunctions`&&(a=`functions.ts`),[`cvx-kit`,`cvx-kit/triggers`].includes(i.source)&&i.name===`createTriggers`&&(a=`triggers.ts`),[`cvx-kit`,`cvx-kit/components/foundation`].includes(i.source)&&i.name===`Foundation`&&(a=`foundation.ts`),(i.source===`cvx-kit/effect`&&i.name===`createEffectFoundation`||i.source===`cvx-kit`&&i.name===`createFoundation`)&&(a=`foundation.ts`),a&&((r(e)!==a||t.has(i.name))&&e.report({node:n,messageId:`facade`,data:{name:i.name,file:a}}),t.add(i.name))}return{CallExpression:n,NewExpression:n}}},"no-raw-builders":{meta:p(`Build host functions through the auth-aware root constructors.`,{builder:`Import raw builders only in convex/functions.ts; use auth*/role*/admin* or system* elsewhere.`}),create(t){if(r(t)===`functions.ts`||a(t,t.filename))return{};let i=e();return{ImportDeclaration(e){if(e.importKind===`type`)return;let a=e.source.value,s=n(i,t.filename,a),c=s&&r(t,s)?.startsWith(`_generated/`)?r(t,s):a;if(/(?:^|\/)_generated\/server(?:\.[cm]?[jt]s)?$/.test(c)||c===`convex/server`)for(let n of e.specifiers){if(n.type===`ImportSpecifier`&&n.importKind===`type`)continue;let e=n.type===`ImportSpecifier`?o(n.imported):null;(e===null&&c!==`convex/server`||e&&/^(?:internal)?(?:Query|Mutation|Action)(?:Generic)?$|^(?:query|mutation|action)(?:Generic)?$/.test(e))&&t.report({node:n,messageId:`builder`})}},CallExpression(e){let n=l(t,e.callee);n?.source===`convex/server`&&/^(?:internal)?(?:Query|Mutation|Action)Generic$|^(?:query|mutation|action)Generic$/.test(n.name)&&e.callee.type===`MemberExpression`&&t.report({node:e,messageId:`builder`})}}}},"no-handwritten-references":{meta:p(`Use generated api/internal references.`,{reference:`Use generated api/internal references instead of makeFunctionReference.`}),create(e){return{CallExpression(t){let n=l(e,t.callee);n?.source===`convex/server`&&n.name===`makeFunctionReference`&&e.report({node:t,messageId:`reference`})}}}},"domain-import-boundaries":{meta:p(`Keep api, application, domain, and shared dependencies directed.`,{boundary:`Follow api → application/domain → shared; sibling modules expose only rules.ts and queries.ts.`}),create(t){let i=r(t),a=e();return h(t,(e,o)=>{if(!i)return;let s=n(a,t.filename,o);if(!s)return;let c=r(t,s)?.replace(/\.[cm]?[jt]s$/,``);if(!c){s.split(S).includes(`node_modules`)||t.report({node:e,messageId:`boundary`});return}let l=i.split(`/`),u=c.split(`/`),d=!1;l[0]===`domain`?(d=[`api`,`application`,`migrations`].includes(u[0]),u[0]===`domain`&&l[1]!==u[1]&&u[1]!==`shared`&&l[1]!==`table.ts`&&(d=l[1]===`shared`||![`rules`,`queries`].includes(u.slice(2).join(`/`)))):l[0]===`api`?d=[`api`,`migrations`].includes(u[0])||u[0]===`domain`&&u[1]!==`shared`&&u[1]!==(l.length>2?l[1]:y(i).replace(/\.[cm]?[jt]s$/,``)):l[0]===`application`&&(d=[`api`,`migrations`].includes(u[0])),u[0]===`migrations`&&l[0]!==`migrations`&&(d=!0),[`api`,`domain`,`application`].includes(l[0])&&u.length>1&&![`api`,`domain`,`application`,`_generated`,`components`,`migrations`].includes(u[0])&&(d=!0),d&&t.report({node:e,messageId:`boundary`})})}},"public-functions-in-api":{meta:p(`Expose authenticated public functions only through api/.`,{public:`Declare public auth*/role*/admin* functions in convex/api/<module>.ts.`}),create(e){return r(e)?.startsWith(`api/`)?{}:{CallExpression(t){let n=l(e,t.callee);t.callee.type!==`CallExpression`&&n&&d(e,n.source)&&/^(auth|role|admin)(Query|Mutation|Action)$/.test(n.name)&&e.report({node:t,messageId:`public`})}}}},"thin-api-adapters":{meta:p(`Keep business decisions and writes in domain executors.`,{adapter:`Move business branches, private helpers, and database writes into the owning domain executor.`}),create(e){return r(e)?.startsWith(`api/`)?{IfStatement(t){e.report({node:t,messageId:`adapter`})},SwitchStatement(t){e.report({node:t,messageId:`adapter`})},ConditionalExpression(t){e.report({node:t,messageId:`adapter`})},Program(t){let n=s(t);for(let r of t.body)if(r.type===`FunctionDeclaration`&&r.id&&!n.has(r.id.name)&&e.report({node:r,messageId:`adapter`}),r.type===`VariableDeclaration`)for(let t of r.declarations)t.id.type===`Identifier`&&!n.has(t.id.name)&&[`ArrowFunctionExpression`,`FunctionExpression`].includes(t.init?.type??``)&&e.report({node:t,messageId:`adapter`})},CallExpression(t){u(t)&&e.report({node:t,messageId:`adapter`})}}:{}}},"no-inline-enums":{meta:p(`Keep vocabularies in named constants.ts tuples.`,{vocabulary:`Define a named readonly tuple in constants.ts and pass it to z.enum().`}),create(e){return{CallExpression(t){let n=l(e,t.callee),r=t.arguments[0];for(;r?.type===`TSAsExpression`||r?.type===`TSSatisfiesExpression`;)r=r.expression;n&&/^zod(?:\/v4)?$/.test(n.source)&&n.name===`enum`&&r?.type===`ArrayExpression`&&e.report({node:t,messageId:`vocabulary`})}}}},"no-unbounded-reads":{meta:p(`Bound collection reads through include or pagination.`,{bounded:`Use include(...).execute(limit) or bounded pagination; do not collect() or resolve() an unbounded query.`}),create(e){return a(e,e.filename)?{}:{CallExpression(t){if(t.callee.type!==`MemberExpression`)return;let n=m(t.callee);(n===`collect`&&c(t.callee.object,`query`)||n===`resolve`&&c(t.callee.object,`include`))&&e.report({node:t,messageId:`bounded`})}}}},"no-manual-timestamps":{meta:p(`Let timestamps triggers own createdAt and updatedAt.`,{timestamp:`Remove {{field}} from this write; register the timestamps trigger instead.`}),create(e){return a(e,e.filename)?{}:{CallExpression(t){if(!u(t))return;let n=t.arguments.at(-1);if(n?.type===`ObjectExpression`)for(let t of n.properties){if(t.type!==`Property`)continue;let n=t.computed?g(t.key):o(t.key);(n===`createdAt`||n===`updatedAt`)&&e.report({node:t,messageId:`timestamp`,data:{field:n}})}}}}},"component-boundaries":{meta:p(`Keep portable components isolated and consume their client facades.`,{boundary:`Components may import only their own files and npm dependencies; inject host policy through the client API.`,facade:`Import a component through its client.ts facade, not its private implementation.`}),create(t){let i=a(t,t.filename),o=e();return h(t,(e,s)=>{s.startsWith(`.`)||/^cvx-kit\/components\/[^/]+\//.test(s)&&!/^cvx-kit\/components\/[^/]+\/convex\.config(?:\.js)?$/.test(s)&&t.report({node:e,messageId:`facade`});let c=n(o,t.filename,s);c&&!c.split(S).includes(`node_modules`)&&(i&&(x(i,c).startsWith(`..${S}`)||c===b(i))?t.report({node:e,messageId:`boundary`}):!i&&a(t,c)&&!/^client(?:\.[cm]?[jt]s)?$/.test(y(c))&&!(r(t)===`convex.config.ts`&&/^convex\.config(?:\.[cm]?[jt]s)?$/.test(y(c)))&&t.report({node:e,messageId:`facade`}))})}},"no-component-env":{meta:p(`Pass environment configuration into portable components.`,{env:`Portable components must receive configuration through arguments; do not read process.env.`}),create(e){if(!a(e,e.filename))return{};function t(t){if(t.type!==`Identifier`)return!1;let n=i(e,t);return t.name===`process`&&!n?.defs.length||n?.defs.some(e=>e.type===`ImportBinding`&&e.parent?.type===`ImportDeclaration`&&[`node:process`,`process`].includes(e.parent.source.value)&&[`ImportDefaultSpecifier`,`ImportNamespaceSpecifier`].includes(e.node.type))}return{ImportDeclaration(t){if([`node:process`,`process`].includes(t.source.value))for(let n of t.specifiers)n.type===`ImportSpecifier`&&o(n.imported)===`env`&&e.report({node:n,messageId:`env`})},MemberExpression(n){if(m(n)!==`env`)return;let r=n.object,a=r.type===`MemberExpression`&&m(r)===`process`&&r.object.type===`Identifier`&&r.object.name===`globalThis`&&!i(e,r.object)?.defs.length;(t(r)||a)&&e.report({node:n,messageId:`env`})},VariableDeclarator(n){if(n.init&&t(n.init)&&n.id.type===`ObjectPattern`)for(let t of n.id.properties)t.type===`Property`&&(t.computed?g(t.key):o(t.key))===`env`&&e.report({node:t,messageId:`env`})}}}},"schema-file-boundaries":{meta:p(`Keep storage shapes and indexes in their documented owners.`,{schema:`{{builder}} belongs in {{file}}.`}),create(e){return{CallExpression(t){let n=l(e,t.callee),i=r(e);if(!i)return;let o=null;n?.source===`convex/server`&&(n.name===`defineSchema`&&i!==`schema.ts`&&!(a(e,e.filename)&&y(i)===`schema.ts`)&&(o=`the root schema.ts (or a component schema.ts)`),n.name===`defineTable`&&!(a(e,e.filename)&&[`schema.ts`,`table.ts`].includes(y(i)))&&(o=`a component schema.ts/table.ts; host tables use zodTable in domain/<module>/schema.ts`)),n&&[`cvx-kit`,`cvx-kit/zod-table`].includes(n.source)&&[`zodTable`,`tenantTable`,`zodVariantTable`].includes(n.name)&&!/^domain\/[^/]+\/schema\.ts$/.test(i)&&(o=`domain/<module>/schema.ts`),o&&e.report({node:t,messageId:`schema`,data:{builder:n?.name??`table`,file:o}}),t.callee.type===`MemberExpression`&&[`index`,`searchIndex`,`vectorIndex`].includes(m(t.callee)??``)&&f(t.callee.object)&&!a(e,e.filename)&&!/^domain\/[^/]+\/table\.ts$/.test(i)&&e.report({node:t,messageId:`schema`,data:{builder:`Table indexes`,file:`domain/<module>/table.ts`}})}}}},"no-internal-reexports":{meta:p(`Import from owning modules directly; consumer apps have no barrels.`,{reexport:`Import from the owning file directly; do not re-export imports inside convex/.`}),create(e){function t(t){if(t.source){e.report({node:t,messageId:`reexport`});return}for(let n of t.type===`ExportNamedDeclaration`?t.specifiers:[])i(e,n.local)?.defs.some(e=>e.type===`ImportBinding`)&&e.report({node:n,messageId:`reexport`})}return{ExportNamedDeclaration:t,ExportAllDeclaration:t,ExportDefaultDeclaration(t){t.declaration.type===`Identifier`&&i(e,t.declaration)?.defs.some(e=>e.type===`ImportBinding`)&&e.report({node:t,messageId:`reexport`})}}}},"public-api-first":{meta:p(`Place private helper implementations after the exported API.`,{order:`Move this private helper below the exported API so the file reads from public purpose to implementation.`}),create(e){return{Program(t){let n=s(t),r=t.body.findLastIndex(e=>e.type.startsWith(`Export`));for(let i of t.body.slice(0,r<0?0:r))i.type===`FunctionDeclaration`&&i.id&&!n.has(i.id.name)&&e.report({node:i,messageId:`order`})}}}},"named-private-helpers":{meta:p(`Use named declarations for top-level private helper functions.`,{helper:`Declare this private helper with function name(...) at the bottom of the file.`}),create(e){return{Program(t){let n=s(t);for(let r of t.body)if(r.type===`VariableDeclaration`)for(let t of r.declarations)t.id.type===`Identifier`&&!n.has(t.id.name)&&(t.init?.type===`ArrowFunctionExpression`||t.init?.type===`FunctionExpression`)&&e.report({node:t,messageId:`helper`})}}}}}),T={meta:{name:`cvx`},rules:w};function E(e){let t={...e},n=Object.keys(e);for(let i of n){let n=e[i];t[i]={meta:{...n.meta,schema:[{type:`object`,properties:{convexDir:{type:`string`,minLength:1}},additionalProperties:!1}]},create(e){let t=r(e);return!t||/(?:^|\/)(?:_generated|__tests__)(?:\/|$)/.test(t)||/\.(?:test|spec)\.[cm]?[jt]s$/.test(t)?{}:n.create(e)}}}return t}export{C as checkArchitecture,T as default,w as rules};
|
|
1
|
+
import{createResolver as e,inspectArchitecture as t,narrowRootDeclaration as n,resolveImport as r}from"./oxlint/architecture.mjs";import{appFile as i,binding as a,componentRoot as o,exportName as s,exportedNames as c,imported as l,isDbWrite as u,isFunctionsImport as d,isTableChain as f,localInitializer as p,metadata as m,propertyName as h,readProvenance as g,sourceVisitors as _,staticString as v}from"./oxlint/ast.mjs";import{reservedDomainFiles as y}from"./oxlint/reserved-files.mjs";import{ownershipRules as b}from"./oxlint/ownership.mjs";import{basename as x,dirname as S,relative as C,sep as w}from"node:path";function T(e={}){return t(e)}const E=O({...b,"root-wiring-only":{...b[`root-wiring-only`],create(e){let t=i(e)??``;return[`relations.ts`,`querying.ts`].includes(t)?n(t,e.sourceCode.text)?{}:{Program(n){e.report({node:n,messageId:`ownership`,data:{reason:`${t} must export one kit factory declaration and contain only declarative configuration`}})}}:b[`root-wiring-only`].create(e)}},"reserved-domain-file-anatomy":y,"root-facade-ownership":{meta:m(`Configure shared kit infrastructure once in its root facade.`,{facade:`Configure {{name}} once in convex/{{file}}; import that facade elsewhere.`}),create(e){if(o(e,e.filename))return{};let t=/* @__PURE__ */ new Set;function n(n){let r=l(e,n.callee);if(!r)return;let a=null;[`cvx-kit`,`cvx-kit/querying`].includes(r.source)&&r.name===`createQueryEngine`&&(a=`querying.ts`),[`cvx-kit`,`cvx-kit/relations`].includes(r.source)&&r.name===`defineRelations`&&(a=`relations.ts`),[`cvx-kit`,`cvx-kit/auth`].includes(r.source)&&r.name===`createAuthFunctions`&&(a=`functions.ts`),[`cvx-kit`,`cvx-kit/triggers`].includes(r.source)&&r.name===`createTriggers`&&(a=`triggers.ts`),[`cvx-kit`,`cvx-kit/components/foundation`].includes(r.source)&&r.name===`Foundation`&&(a=`foundation.ts`),(r.source===`cvx-kit/effect`&&r.name===`createEffectFoundation`||r.source===`cvx-kit`&&r.name===`createFoundation`)&&(a=`foundation.ts`),a&&((i(e)!==a||t.has(r.name))&&e.report({node:n,messageId:`facade`,data:{name:r.name,file:a}}),t.add(r.name))}return{CallExpression:n,NewExpression:n}}},"no-raw-builders":{meta:m(`Build host functions through the auth-aware root constructors.`,{builder:`Import raw builders only in convex/functions.ts; use auth*/role*/admin* or system* elsewhere.`}),create(t){if(i(t)===`functions.ts`||o(t,t.filename))return{};let n=e();return{ImportDeclaration(e){if(e.importKind===`type`)return;let a=e.source.value,o=r(n,t.filename,a),c=o&&i(t,o)?.startsWith(`_generated/`)?i(t,o):a;if(/(?:^|\/)_generated\/server(?:\.[cm]?[jt]s)?$/.test(c)||c===`convex/server`)for(let n of e.specifiers){if(n.type===`ImportSpecifier`&&n.importKind===`type`)continue;let e=n.type===`ImportSpecifier`?s(n.imported):null;(e===null&&c!==`convex/server`||e&&/^(?:internal)?(?:Query|Mutation|Action)(?:Generic)?$|^(?:query|mutation|action)(?:Generic)?$/.test(e))&&t.report({node:n,messageId:`builder`})}},CallExpression(e){let n=l(t,e.callee);n?.source===`convex/server`&&/^(?:internal)?(?:Query|Mutation|Action)Generic$|^(?:query|mutation|action)Generic$/.test(n.name)&&e.callee.type===`MemberExpression`&&t.report({node:e,messageId:`builder`})}}}},"no-handwritten-references":{meta:m(`Use generated api/internal references.`,{reference:`Use generated api/internal references instead of makeFunctionReference.`}),create(e){return{CallExpression(t){let n=l(e,t.callee);n?.source===`convex/server`&&n.name===`makeFunctionReference`&&e.report({node:t,messageId:`reference`})}}}},"domain-import-boundaries":{meta:m(`Keep api, application, domain, and shared dependencies directed.`,{boundary:`Follow api → application/domain → shared; sibling modules expose only rules.ts and queries.ts.`}),create(t){let n=i(t),a=e();return _(t,(e,o)=>{if(!n)return;let s=r(a,t.filename,o);if(!s)return;let c=i(t,s)?.replace(/\.[cm]?[jt]s$/,``);if(!c){s.split(w).includes(`node_modules`)||t.report({node:e,messageId:`boundary`});return}let l=n.split(`/`),u=c.split(`/`),d=!1;l[0]===`domain`?(d=[`api`,`application`,`migrations`].includes(u[0]),u[0]===`domain`&&l[1]!==u[1]&&u[1]!==`shared`&&l[1]!==`table.ts`&&(d=l[1]===`shared`||![`rules`,`queries`,`contracts`].includes(u.slice(2).join(`/`)))):l[0]===`api`?d=[`api`,`migrations`].includes(u[0])||u[0]===`domain`&&u[1]!==`shared`&&u[1]!==(l.length>2?l[1]:x(n).replace(/\.[cm]?[jt]s$/,``)):l[0]===`application`?d=[`api`,`migrations`].includes(u[0]):[`relations.ts`,`querying.ts`].includes(n)&&u[0]===`domain`&&(d=!(n===`relations.ts`?[`schema`,`table`]:[`queries`,`contracts`]).includes(u.slice(2).join(`/`))&&(n!==`relations.ts`||c!==`domain/table`)),u[0]===`migrations`&&l[0]!==`migrations`&&(d=!0),[`api`,`domain`,`application`].includes(l[0])&&u.length>1&&![`api`,`domain`,`application`,`_generated`,`components`,`migrations`].includes(u[0])&&(d=!0),d&&t.report({node:e,messageId:`boundary`})})}},"public-functions-in-api":{meta:m(`Expose authenticated public functions only through api/.`,{public:`Declare public auth*/role*/admin* functions in convex/api/<module>.ts.`}),create(e){return i(e)?.startsWith(`api/`)?{}:{CallExpression(t){let n=l(e,t.callee);t.callee.type!==`CallExpression`&&n&&d(e,n.source)&&/^(auth|role|admin)(Query|Mutation|Action)$/.test(n.name)&&e.report({node:t,messageId:`public`})}}}},"thin-api-adapters":{meta:m(`Keep business decisions and writes in domain executors.`,{adapter:`Move business branches, private helpers, and database writes into the owning domain executor.`}),create(e){return i(e)?.startsWith(`api/`)?{IfStatement(t){e.report({node:t,messageId:`adapter`})},SwitchStatement(t){e.report({node:t,messageId:`adapter`})},ConditionalExpression(t){e.report({node:t,messageId:`adapter`})},Program(t){let n=c(t);for(let r of t.body)if(r.type===`FunctionDeclaration`&&r.id&&!n.has(r.id.name)&&e.report({node:r,messageId:`adapter`}),r.type===`VariableDeclaration`)for(let t of r.declarations)t.id.type===`Identifier`&&!n.has(t.id.name)&&[`ArrowFunctionExpression`,`FunctionExpression`].includes(t.init?.type??``)&&e.report({node:t,messageId:`adapter`})},CallExpression(t){u(t)&&e.report({node:t,messageId:`adapter`})}}:{}}},"no-inline-enums":{meta:m(`Keep vocabularies in named constants.ts tuples.`,{vocabulary:`Define a named readonly tuple in constants.ts and pass it to z.enum().`}),create(e){return{CallExpression(t){let n=l(e,t.callee),r=t.arguments[0];for(;r?.type===`TSAsExpression`||r?.type===`TSSatisfiesExpression`;)r=r.expression;n&&/^zod(?:\/v4)?$/.test(n.source)&&n.name===`enum`&&r?.type===`ArrayExpression`&&e.report({node:t,messageId:`vocabulary`})}}}},"no-unbounded-reads":{meta:m(`Bound collection reads through include or pagination.`,{bounded:`Use include(...).execute(limit) or bounded pagination; do not collect() or resolve() an unbounded query.`,order:`Apply eligibility filters in the indexed query before take(), execute(), or paginate(); filtering a bounded result can omit eligible rows. Do not move the predicate automatically.`}),create(e){return o(e,e.filename)?{}:{CallExpression(t){if(t.callee.type!==`MemberExpression`)return;let n=h(t.callee),r=g(e,t.callee.object);n===`filter`&&r===`bounded`&&e.report({node:t,messageId:`order`}),(n===`collect`&&(r===`stream`||r===`relationship`)||n===`resolve`&&r===`stream`)&&e.report({node:t,messageId:`bounded`})}}}},"no-manual-id-projection":{meta:m(`Use the table DTO boundary to project public IDs.`,{projection:`Use toPublicDto(row, true) to include _id; do not add IDs manually after a table DTO parse or projection.`}),create(e){return{ObjectExpression(t){if(t.properties.some(t=>t.type===`SpreadElement`&&g(e,t.argument)===`dto`))for(let n of t.properties)n.type===`Property`&&[`id`,`_id`].includes((n.computed?v(n.key):s(n.key))??``)&&e.report({node:n,messageId:`projection`})},AssignmentExpression(t){t.left.type===`MemberExpression`&&[`id`,`_id`].includes(h(t.left)??``)&&g(e,t.left.object)===`dto`&&e.report({node:t,messageId:`projection`})}}}},"no-copied-pagination":{meta:m(`Use native or table pagination schemas instead of copying their shape.`,{pagination:`Use the native paginationOptsValidator (or paginated(table.dto())) for native pagination, or table.paginationOpts(selection) for table queries; do not copy pagination fields.`}),create(e){return{CallExpression(t){let n=l(e,t.callee);if(!(n?.name===`object`&&[`zod`,`zod/v4`,`convex/values`].includes(n.source)))return;let r=t.arguments[0],i=r&&(p(e,r)??r);if(i?.type!==`ObjectExpression`)return;let a=new Set(i.properties.flatMap(e=>e.type===`Property`?[e.computed?v(e.key):s(e.key)]:[]));(a.has(`numItems`)&&a.has(`cursor`)||[`page`,`isDone`,`continueCursor`].every(e=>a.has(e)))&&e.report({node:t,messageId:`pagination`})}}}},"no-manual-timestamps":{meta:m(`Let timestamps triggers own createdAt and updatedAt.`,{timestamp:`Remove {{field}} from this write; register the timestamps trigger instead.`}),create(e){return o(e,e.filename)?{}:{CallExpression(t){if(!u(t))return;let n=t.arguments.at(-1);if(n?.type===`ObjectExpression`)for(let t of n.properties){if(t.type!==`Property`)continue;let n=t.computed?v(t.key):s(t.key);(n===`createdAt`||n===`updatedAt`)&&e.report({node:t,messageId:`timestamp`,data:{field:n}})}}}}},"component-boundaries":{meta:m(`Keep portable components isolated and consume their client facades.`,{boundary:`Components may import only their own files and npm dependencies; inject host policy through the client API.`,facade:`Import a component through its client.ts facade, not its private implementation.`}),create(t){let n=o(t,t.filename),a=e();return _(t,(e,s)=>{s.startsWith(`.`)||/^cvx-kit\/components\/[^/]+\//.test(s)&&!/^cvx-kit\/components\/[^/]+\/convex\.config(?:\.js)?$/.test(s)&&t.report({node:e,messageId:`facade`});let c=r(a,t.filename,s);c&&!c.split(w).includes(`node_modules`)&&(n&&(C(n,c).startsWith(`..${w}`)||c===S(n))?t.report({node:e,messageId:`boundary`}):!n&&o(t,c)&&!/^client(?:\.[cm]?[jt]s)?$/.test(x(c))&&!(i(t)===`convex.config.ts`&&/^convex\.config(?:\.[cm]?[jt]s)?$/.test(x(c)))&&t.report({node:e,messageId:`facade`}))})}},"no-component-env":{meta:m(`Pass environment configuration into portable components.`,{env:`Portable components must receive configuration through arguments; do not read process.env.`}),create(e){if(!o(e,e.filename))return{};function t(t){if(t.type!==`Identifier`)return!1;let n=a(e,t);return t.name===`process`&&!n?.defs.length||n?.defs.some(e=>e.type===`ImportBinding`&&e.parent?.type===`ImportDeclaration`&&[`node:process`,`process`].includes(e.parent.source.value)&&[`ImportDefaultSpecifier`,`ImportNamespaceSpecifier`].includes(e.node.type))}return{ImportDeclaration(t){if([`node:process`,`process`].includes(t.source.value))for(let n of t.specifiers)n.type===`ImportSpecifier`&&s(n.imported)===`env`&&e.report({node:n,messageId:`env`})},MemberExpression(n){if(h(n)!==`env`)return;let r=n.object,i=r.type===`MemberExpression`&&h(r)===`process`&&r.object.type===`Identifier`&&r.object.name===`globalThis`&&!a(e,r.object)?.defs.length;(t(r)||i)&&e.report({node:n,messageId:`env`})},VariableDeclarator(n){if(n.init&&t(n.init)&&n.id.type===`ObjectPattern`)for(let t of n.id.properties)t.type===`Property`&&(t.computed?v(t.key):s(t.key))===`env`&&e.report({node:t,messageId:`env`})}}}},"schema-file-boundaries":{meta:m(`Keep storage shapes and indexes in their documented owners.`,{schema:`{{builder}} belongs in {{file}}.`}),create(e){return{CallExpression(t){let n=l(e,t.callee),r=i(e);if(!r)return;let a=null;n?.source===`convex/server`&&(n.name===`defineSchema`&&r!==`schema.ts`&&!(o(e,e.filename)&&x(r)===`schema.ts`)&&(a=`the root schema.ts (or a component schema.ts)`),n.name===`defineTable`&&!(o(e,e.filename)&&[`schema.ts`,`table.ts`].includes(x(r)))&&(a=`a component schema.ts/table.ts; host tables use zodTable in domain/<module>/schema.ts`)),n&&[`cvx-kit`,`cvx-kit/zod-table`].includes(n.source)&&[`zodTable`,`tenantTable`,`zodVariantTable`].includes(n.name)&&!/^domain\/[^/]+\/schema\.ts$/.test(r)&&(a=`domain/<module>/schema.ts`),a&&e.report({node:t,messageId:`schema`,data:{builder:n?.name??`table`,file:a}}),t.callee.type===`MemberExpression`&&[`index`,`searchIndex`,`vectorIndex`].includes(h(t.callee)??``)&&f(t.callee.object)&&!o(e,e.filename)&&!/^domain\/[^/]+\/table\.ts$/.test(r)&&e.report({node:t,messageId:`schema`,data:{builder:`Table indexes`,file:`domain/<module>/table.ts`}})}}}},"no-internal-reexports":{meta:m(`Import from owning modules directly; consumer apps have no barrels.`,{reexport:`Import from the owning file directly; do not re-export imports inside convex/.`}),create(e){function t(t){if(t.source){e.report({node:t,messageId:`reexport`});return}for(let n of t.type===`ExportNamedDeclaration`?t.specifiers:[])a(e,n.local)?.defs.some(e=>e.type===`ImportBinding`)&&e.report({node:n,messageId:`reexport`})}return{ExportNamedDeclaration:t,ExportAllDeclaration:t,ExportDefaultDeclaration(t){t.declaration.type===`Identifier`&&a(e,t.declaration)?.defs.some(e=>e.type===`ImportBinding`)&&e.report({node:t,messageId:`reexport`})}}}},"public-api-first":{meta:m(`Place private helper implementations after the exported API.`,{order:`Move this private helper below the exported API so the file reads from public purpose to implementation.`}),create(e){return{Program(t){let n=c(t),r=t.body.findLastIndex(e=>e.type.startsWith(`Export`));for(let i of t.body.slice(0,r<0?0:r))i.type===`FunctionDeclaration`&&i.id&&!n.has(i.id.name)&&e.report({node:i,messageId:`order`})}}}},"named-private-helpers":{meta:m(`Use named declarations for top-level private helper functions.`,{helper:`Declare this private helper with function name(...) at the bottom of the file.`}),create(e){return{Program(t){let n=c(t);for(let r of t.body)if(r.type===`VariableDeclaration`)for(let t of r.declarations)t.id.type===`Identifier`&&!n.has(t.id.name)&&(t.init?.type===`ArrowFunctionExpression`||t.init?.type===`FunctionExpression`)&&e.report({node:t,messageId:`helper`})}}}}}),D={meta:{name:`cvx`},rules:E};function O(e){let t={...e},n=Object.keys(e);for(let r of n){let n=e[r];t[r]={meta:{...n.meta,schema:[{type:`object`,properties:{convexDir:{type:`string`,minLength:1}},additionalProperties:!1}]},create(e){let t=i(e);return!t||/(?:^|\/)(?:_generated|__tests__)(?:\/|$)/.test(t)||/\.(?:test|spec)\.[cm]?[jt]s$/.test(t)?{}:n.create(e)}}}return t}export{T as checkArchitecture,D as default,E as rules};
|
|
2
2
|
//# sourceMappingURL=oxlint.mjs.map
|