cvx-kit 0.1.10 → 0.1.12

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +1 -0
  3. package/dist/contracts.d.mts +2 -1
  4. package/dist/contracts.mjs +1 -1
  5. package/dist/effect.d.mts +3 -2
  6. package/dist/effect.mjs +1 -1
  7. package/dist/index.d.mts +2 -1
  8. package/dist/index.mjs +1 -1
  9. package/dist/modules/contracts/binding.d.mts +14 -0
  10. package/dist/modules/contracts/binding.mjs +2 -0
  11. package/dist/modules/contracts/binding.mjs.map +1 -0
  12. package/dist/modules/contracts/domain.d.mts +59 -0
  13. package/dist/modules/contracts/domain.mjs +2 -0
  14. package/dist/modules/contracts/domain.mjs.map +1 -0
  15. package/dist/modules/effect/api-runtime.mjs +1 -1
  16. package/dist/modules/effect/auth.d.mts +43 -0
  17. package/dist/modules/effect/auth.mjs +2 -0
  18. package/dist/modules/effect/auth.mjs.map +1 -0
  19. package/dist/modules/effect/client.d.mts +1 -1
  20. package/dist/modules/effect/client.mjs +1 -1
  21. package/dist/modules/effect/command.d.mts +35 -1
  22. package/dist/modules/effect/command.mjs +1 -1
  23. package/dist/modules/effect/command.mjs.map +1 -1
  24. package/dist/modules/effect/crud.d.mts +6 -0
  25. package/dist/modules/effect/crud.mjs +1 -1
  26. package/dist/modules/effect/domain.d.mts +44 -0
  27. package/dist/modules/effect/domain.mjs +2 -0
  28. package/dist/modules/effect/domain.mjs.map +1 -0
  29. package/dist/modules/effect/operation.d.mts +4 -3
  30. package/dist/modules/effect/operation.mjs.map +1 -1
  31. package/dist/modules/effect/query.d.mts +23 -8
  32. package/dist/modules/effect/query.mjs +1 -1
  33. package/dist/modules/effect/query.mjs.map +1 -1
  34. package/dist/modules/effect/workflow.mjs +1 -1
  35. package/dist/modules/foundation/foundation.d.mts +108 -0
  36. package/dist/modules/foundation/foundation.mjs +2 -0
  37. package/dist/modules/foundation/foundation.mjs.map +1 -0
  38. package/dist/modules/foundation/operation.d.mts +121 -0
  39. package/dist/modules/foundation/operation.mjs +2 -0
  40. package/dist/modules/foundation/operation.mjs.map +1 -0
  41. package/dist/oxlint/ownership.mjs +1 -1
  42. package/dist/oxlint/ownership.mjs.map +1 -1
  43. package/dist/oxlint/reserved-files.d.mts +6 -0
  44. package/dist/oxlint/reserved-files.mjs +2 -0
  45. package/dist/oxlint/reserved-files.mjs.map +1 -0
  46. package/dist/oxlint.d.mts +1 -1
  47. package/dist/oxlint.mjs +1 -1
  48. package/dist/oxlint.mjs.map +1 -1
  49. package/docs/auth.md +131 -1
  50. package/docs/commands-legacy.md +3 -1
  51. package/docs/conventions.md +7 -3
  52. package/docs/domain-contracts.md +115 -0
  53. package/docs/effect.md +10 -2
  54. package/docs/llms.md +41 -20
  55. package/docs/oxlint.md +4 -0
  56. package/package.json +1 -1
  57. package/scripts/test-packed-auth.mjs +5 -1
  58. package/scripts/test-packed-effect.mjs +13 -0
  59. package/scripts/test-packed-oxlint.mjs +1 -1
@@ -0,0 +1,121 @@
1
+ import { ContractInput, ContractOutput, NeutralSchema } from "../contracts/contract.mjs";
2
+ import { AuditEntryInput } from "../../components/foundation/client.mjs";
3
+ import { DomainOperationContract, ExactOperationKeys } from "../contracts/domain.mjs";
4
+ //#region src/modules/foundation/operation.d.ts
5
+ type Supported<A> = A | PromiseLike<A>;
6
+ export type Audit = Omit<AuditEntryInput, 'classification'> | null;
7
+ export type NormalEntry = DomainOperationContract & {
8
+ input: NeutralSchema;
9
+ result: NeutralSchema;
10
+ replayResult?: NeutralSchema;
11
+ wire?: {
12
+ schema: NeutralSchema;
13
+ project: Function;
14
+ };
15
+ };
16
+ declare const checkedOperation: unique symbol;
17
+ export type CheckedDefinition<Context, Definition, Key = unknown> = NoInfer<Definition> & {
18
+ readonly [checkedOperation]: {
19
+ context: (context: Context) => void;
20
+ definition: Definition;
21
+ key: Key;
22
+ };
23
+ };
24
+ export type CheckedOperation<Context> = {
25
+ readonly [checkedOperation]: {
26
+ context: (context: Context) => void;
27
+ definition: unknown;
28
+ key: unknown;
29
+ };
30
+ };
31
+ export type ValidatedOperations<Operations> = { [Key in keyof Operations]: Operations[Key] extends {
32
+ readonly [checkedOperation]: {
33
+ definition: infer Definition;
34
+ };
35
+ } ? Operations[Key] extends Definition ? Operations[Key] : never : never; };
36
+ export type ExactOperations<Operations, Entries> = ExactOperationKeys<Operations, Entries> & { [Key in keyof Operations]: Operations[Key] extends {
37
+ readonly [checkedOperation]: {
38
+ key: Key;
39
+ };
40
+ } ? Operations[Key] : never; };
41
+ type Definition<Context, Entry extends NormalEntry> = {
42
+ handler: (input: ContractOutput<Entry['input']>, context: Context) => Supported<ContractInput<Entry['result']>>;
43
+ permission?: string;
44
+ metadata?: object;
45
+ aggregates?: readonly string[];
46
+ guard?: (context: Context, input: ContractOutput<Entry['input']>) => Supported<void>;
47
+ prepare?: (context: Context, input: ContractOutput<Entry['input']>) => Supported<{
48
+ kind: 'replay';
49
+ result: unknown;
50
+ } | {
51
+ kind: 'execute';
52
+ complete?: (result: ContractOutput<Entry['result']>) => Supported<void>;
53
+ }>;
54
+ audit?: (resolution: {
55
+ command: ContractOutput<Entry['input']>;
56
+ result: ContractOutput<Entry['result']>;
57
+ }, context: Context) => Supported<Audit>;
58
+ middleware?: (input: {
59
+ operation: string;
60
+ input: ContractOutput<Entry['input']>;
61
+ command: ContractOutput<Entry['input']>;
62
+ context: Context;
63
+ metadata: object;
64
+ next: (options?: {
65
+ context?: object;
66
+ }) => Promise<ContractInput<Entry['result']>>;
67
+ }) => Supported<ContractInput<Entry['result']>>;
68
+ };
69
+ type CommandRules<Context, Entry extends NormalEntry, Command extends boolean, Required extends boolean> = Command extends false ? {
70
+ audit?: never;
71
+ prepare?: never;
72
+ aggregates?: never;
73
+ replayResult?: never;
74
+ } : Required extends true ? {
75
+ audit: NonNullable<Definition<Context, Entry>['audit']>;
76
+ } : {};
77
+ type Forbidden = {
78
+ input?: never;
79
+ result?: never;
80
+ classification?: never;
81
+ replayResult?: never;
82
+ wire?: never;
83
+ };
84
+ export type DomainFactory<Context, Entries extends Readonly<Record<string, NormalEntry>>, Command extends boolean, Required extends boolean> = { [Kind in Command extends true ? 'command' : 'query']: { [Key in keyof Entries]: <const Implementation extends object>(implementation: Implementation & Definition<Context, Entries[Key]> & Forbidden & CommandRules<Context, Entries[Key], Command, Required>) => CheckedDefinition<Context, Entries[Key] & Implementation, Key>; }; };
85
+ export declare function domainFactory<Context, Entries extends Readonly<Record<string, NormalEntry>>, Command extends boolean, Required extends boolean>(entries: Entries, command: Command): DomainFactory<Context, Entries, Command, Required>;
86
+ export declare function operationFactory<Context, Required extends boolean = true>(): {
87
+ command: <const Input extends NeutralSchema, const Result extends NeutralSchema, const Wire extends NeutralSchema, const Replay extends NeutralSchema, const Implementation extends object>(implementation: Implementation & {
88
+ input: Input;
89
+ result: Result;
90
+ classification: string;
91
+ replayResult?: Replay & (ContractOutput<Replay> extends ContractOutput<Result> ? unknown : never);
92
+ wire?: {
93
+ schema: Wire;
94
+ project: (result: ContractOutput<Result>) => ContractInput<Wire>;
95
+ };
96
+ } & Definition<Context, {
97
+ input: Input;
98
+ result: Result;
99
+ }> & CommandRules<Context, {
100
+ input: Input;
101
+ result: Result;
102
+ }, true, Required>) => CheckedDefinition<Context, typeof implementation>;
103
+ query: <const Input extends NeutralSchema, const Result extends NeutralSchema, const Wire extends NeutralSchema, const Implementation extends object>(implementation: Implementation & {
104
+ input: Input;
105
+ result: Result;
106
+ classification?: string;
107
+ wire?: {
108
+ schema: Wire;
109
+ project: (result: ContractOutput<Result>) => ContractInput<Wire>;
110
+ };
111
+ } & Definition<Context, {
112
+ input: Input;
113
+ result: Result;
114
+ }> & CommandRules<Context, {
115
+ input: Input;
116
+ result: Result;
117
+ }, false, true>) => CheckedDefinition<Context, typeof implementation>;
118
+ };
119
+ export type InlineFactory<Context, Required extends boolean> = ReturnType<typeof operationFactory<Context, Required>>;
120
+ //#endregion
121
+ //# sourceMappingURL=operation.d.mts.map
@@ -0,0 +1,2 @@
1
+ import{domainHelpers as e}from"../contracts/binding.mjs";function t(t,n){let r=e(t);return{[n?`command`:`query`]:r}}function n(){function e(e){return e}function t(e){return e}return{command:e,query:t}}export{t as domainFactory,n as operationFactory};
2
+ //# sourceMappingURL=operation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation.mjs","names":["domainFactory","helpers","domainHelpers","entries","command","operationFactory","implementation","query"],"sources":["../../../src/modules/foundation/operation.ts"],"sourcesContent":["/* oxlint-disable anti-slop/no-object-parameters -- Internal helper storage is heterogeneous; the exported mapped signatures validate the schema-paired implementation. */\nimport type { AuditEntryInput } from '../../components/foundation/client'\nimport type { ContractInput, ContractOutput, NeutralSchema } from '../contracts/contract'\nimport type { DomainOperationContract, ExactOperationKeys } from '../contracts/domain'\nimport { domainHelpers } from '../contracts/binding'\n\ntype Supported<A> = A | PromiseLike<A>\nexport type Audit = Omit<AuditEntryInput, 'classification'> | null\nexport type NormalEntry = DomainOperationContract & {\n\tinput: NeutralSchema\n\tresult: NeutralSchema\n\treplayResult?: NeutralSchema\n\twire?: { schema: NeutralSchema; project: Function }\n}\ndeclare const checkedOperation: unique symbol\nexport type CheckedDefinition<Context, Definition, Key = unknown> = NoInfer<Definition> & {\n\treadonly [checkedOperation]: {\n\t\tcontext: (context: Context) => void\n\t\tdefinition: Definition\n\t\tkey: Key\n\t}\n}\nexport type CheckedOperation<Context> = {\n\treadonly [checkedOperation]: {\n\t\tcontext: (context: Context) => void\n\t\tdefinition: unknown\n\t\tkey: unknown\n\t}\n}\nexport type ValidatedOperations<Operations> = {\n\t[Key in keyof Operations]: Operations[Key] extends {\n\t\treadonly [checkedOperation]: { definition: infer Definition }\n\t}\n\t\t? Operations[Key] extends Definition\n\t\t\t? Operations[Key]\n\t\t\t: never\n\t\t: never\n}\nexport type ExactOperations<Operations, Entries> = ExactOperationKeys<Operations, Entries> & {\n\t[Key in keyof Operations]: Operations[Key] extends { readonly [checkedOperation]: { key: Key } }\n\t\t? Operations[Key]\n\t\t: never\n}\ntype Definition<Context, Entry extends NormalEntry> = {\n\thandler: (\n\t\tinput: ContractOutput<Entry['input']>,\n\t\tcontext: Context,\n\t) => Supported<ContractInput<Entry['result']>>\n\tpermission?: string\n\tmetadata?: object\n\taggregates?: readonly string[]\n\tguard?: (context: Context, input: ContractOutput<Entry['input']>) => Supported<void>\n\tprepare?: (\n\t\tcontext: Context,\n\t\tinput: ContractOutput<Entry['input']>,\n\t) => Supported<\n\t\t| { kind: 'replay'; result: unknown }\n\t\t| { kind: 'execute'; complete?: (result: ContractOutput<Entry['result']>) => Supported<void> }\n\t>\n\taudit?: (\n\t\tresolution: {\n\t\t\tcommand: ContractOutput<Entry['input']>\n\t\t\tresult: ContractOutput<Entry['result']>\n\t\t},\n\t\tcontext: Context,\n\t) => Supported<Audit>\n\tmiddleware?: (input: {\n\t\toperation: string\n\t\tinput: ContractOutput<Entry['input']>\n\t\tcommand: ContractOutput<Entry['input']>\n\t\tcontext: Context\n\t\tmetadata: object\n\t\tnext: (options?: { context?: object }) => Promise<ContractInput<Entry['result']>>\n\t}) => Supported<ContractInput<Entry['result']>>\n}\ntype CommandRules<\n\tContext,\n\tEntry extends NormalEntry,\n\tCommand extends boolean,\n\tRequired extends boolean,\n> = Command extends false\n\t? { audit?: never; prepare?: never; aggregates?: never; replayResult?: never }\n\t: Required extends true\n\t\t? { audit: NonNullable<Definition<Context, Entry>['audit']> }\n\t\t: {}\ntype Forbidden = {\n\tinput?: never\n\tresult?: never\n\tclassification?: never\n\treplayResult?: never\n\twire?: never\n}\nexport type DomainFactory<\n\tContext,\n\tEntries extends Readonly<Record<string, NormalEntry>>,\n\tCommand extends boolean,\n\tRequired extends boolean,\n> = {\n\t[Kind in Command extends true ? 'command' : 'query']: {\n\t\t[Key in keyof Entries]: <const Implementation extends object>(\n\t\t\timplementation: Implementation &\n\t\t\t\tDefinition<Context, Entries[Key]> &\n\t\t\t\tForbidden &\n\t\t\t\tCommandRules<Context, Entries[Key], Command, Required>,\n\t\t) => CheckedDefinition<Context, Entries[Key] & Implementation, Key>\n\t}\n}\nexport function domainFactory<\n\tContext,\n\tEntries extends Readonly<Record<string, NormalEntry>>,\n\tCommand extends boolean,\n\tRequired extends boolean,\n>(entries: Entries, command: Command): DomainFactory<Context, Entries, Command, Required> {\n\tconst helpers = domainHelpers(entries)\n\t// SAFETY: paired schemas and callbacks are checked by the named helper signatures.\n\treturn { [command ? 'command' : 'query']: helpers } as DomainFactory<\n\t\tContext,\n\t\tEntries,\n\t\tCommand,\n\t\tRequired\n\t>\n}\nexport function operationFactory<Context, Required extends boolean = true>() {\n\tfunction command<\n\t\tconst Input extends NeutralSchema,\n\t\tconst Result extends NeutralSchema,\n\t\tconst Wire extends NeutralSchema,\n\t\tconst Replay extends NeutralSchema,\n\t\tconst Implementation extends object,\n\t>(\n\t\timplementation: Implementation & {\n\t\t\tinput: Input\n\t\t\tresult: Result\n\t\t\tclassification: string\n\t\t\treplayResult?: Replay &\n\t\t\t\t(ContractOutput<Replay> extends ContractOutput<Result> ? unknown : never)\n\t\t\twire?: { schema: Wire; project: (result: ContractOutput<Result>) => ContractInput<Wire> }\n\t\t} & Definition<Context, { input: Input; result: Result }> &\n\t\t\tCommandRules<Context, { input: Input; result: Result }, true, Required>,\n\t) {\n\t\t// SAFETY: this type-only evidence records the complete helper-checked definition.\n\t\treturn implementation as CheckedDefinition<Context, typeof implementation>\n\t}\n\tfunction query<\n\t\tconst Input extends NeutralSchema,\n\t\tconst Result extends NeutralSchema,\n\t\tconst Wire extends NeutralSchema,\n\t\tconst Implementation extends object,\n\t>(\n\t\timplementation: Implementation & {\n\t\t\tinput: Input\n\t\t\tresult: Result\n\t\t\tclassification?: string\n\t\t\twire?: { schema: Wire; project: (result: ContractOutput<Result>) => ContractInput<Wire> }\n\t\t} & Definition<Context, { input: Input; result: Result }> &\n\t\t\tCommandRules<Context, { input: Input; result: Result }, false, true>,\n\t) {\n\t\t// SAFETY: this type-only evidence records the complete helper-checked definition.\n\t\treturn implementation as CheckedDefinition<Context, typeof implementation>\n\t}\n\treturn { command, query }\n}\nexport type InlineFactory<Context, Required extends boolean> = ReturnType<\n\ttypeof operationFactory<Context, Required>\n>\n"],"mappings":"yDA2GA,SAAgBA,EAKd,EAAkB,EAAsE,CACzF,IAAMC,EAAUC,EAAcC,CAAO,EAErC,MAAO,EAAGC,EAAU,UAAY,SAAUH,CAAQ,CAMnD,CACA,SAAgBI,GAA6D,CAC5E,SAASD,EAOR,EASC,CAED,OAAOE,CACR,CACA,SAASC,EAMR,EAOC,CAED,OAAOD,CACR,CACA,MAAO,CAAE,UAAS,OAAM,CACzB"}
@@ -1,2 +1,2 @@
1
- import{architectureAnchor as e,createResolver as t,inspectArchitecture as n,resolveImport as r}from"./architecture.mjs";import{appFile as i,binding as a,componentRoot as o,consumerOptions as s,containsComponentReference as c,delegatingBody as l,exportedNames as u,imported as d,isDbAccess as f,isDbWrite as p,isExternalCall as m,isFunctionsImport as h,memberPath as g,metadata as _,propertyName as v,rootMember as y,sourceVisitors as b,typeOnlySource as x}from"./ast.mjs";import{basename as S,resolve as C}from"node:path";import{existsSync as w,realpathSync as T}from"node:fs";const E={"project-structure":{meta:_(`Validate the application tree, colocated tests, and module cycles.`,{structure:`{{file}}: {{message}}`}),create(t){let r=s.parse(t.options[0]??{}),i=C(t.cwd,r.convexDir);return(w(t.filename)?T(t.filename):C(t.filename))===e(i)?{Program(e){for(let i of n({cwd:t.cwd,convexDir:r.convexDir}))t.report({node:e,messageId:`structure`,data:{file:i.file,message:i.message}})}}:{}}},"root-wiring-only":{meta:_(`Keep root files limited to configuration, assembly, and component facades.`,{ownership:`Root files only wire configuration and components. Move behavior into domain/<module>/: {{reason}}.`}),create(e){let t=i(e);if(!t||t.includes(`/`))return{};let n=null,r=`business implementation`,a=!1,o=/^(?:convex\.config|auth\.config|vite\.config|vitest\.config|auth|schema|functions|triggers|foundation|http|crons)\.[cm]?[jt]s$/.test(t);function s(e){n??=e}return{Program(e){e.body.some(e=>e.type===`FunctionDeclaration`||e.type===`ExportNamedDeclaration`&&e.declaration?.type===`FunctionDeclaration`)&&s(e)},NewExpression(t){d(e,t.callee)&&t.arguments.some(t=>c(e,t))&&(a=!0)},CallExpression(n){d(e,n.callee)&&n.arguments.some(t=>c(e,t))&&(a=!0),(p(n)||m(e,n)||t===`schema.ts`&&d(e,n.callee)?.name!==`defineSchema`)&&s(n)},ArrowFunctionExpression(e){(!e.body||!l(e.body))&&s(e)},FunctionExpression(e){(!e.body||!l(e.body))&&s(e)},IfStatement:s,SwitchStatement:s,ConditionalExpression:s,ForStatement:s,ForOfStatement:s,WhileStatement:s,"Program:exit"(t){!o&&!a&&(n=t,r=`unknown root file; only declared component facades may add root source files`),n&&e.report({node:n,messageId:`ownership`,data:{reason:r}})}}}},"application-orchestration":{meta:_(`Reserve application/ for thin cross-domain coordination.`,{ownership:`application/ only coordinates two or more domains. Move schemas, providers, storage access, helpers, and business decisions into their owning domain.`}),create(e){if(!i(e)?.startsWith(`application/`))return{};let n=/* @__PURE__ */ new Set,a=t(),o=null;function s(e){o??=e}let c=b(e,(t,o)=>{if(x(t))return;let c=r(a,e.filename,o),l=c&&i(e,c),u=l?.match(/^domain\/([^/]+)\/(?:commands|queries|rules)(?:\.[cm]?[jt]s)?$/);u&&u[1]!==`shared`&&n.add(u[1]),l?.startsWith(`domain/`)&&!u&&!l.startsWith(`domain/shared/`)&&s(t),!l&&![`cvx-kit`,`cvx-kit/components/foundation`,`@convex-dev/workflow`,`convex/values`].includes(o)&&s(t)});return{...c,Program(e){let t=u(e);for(let n of e.body){n.type===`FunctionDeclaration`&&n.id&&!t.has(n.id.name)&&s(n);let e=n.type===`ExportNamedDeclaration`?n.declaration:n;if((e?.type===`TSTypeAliasDeclaration`||e?.type===`TSInterfaceDeclaration`)&&s(n),e?.type===`VariableDeclaration`)for(let r of e.declarations)r.init&&[`ObjectExpression`,`ArrayExpression`,`Literal`].includes(r.init.type)&&s(r),n.type===`VariableDeclaration`&&r.id.type===`Identifier`&&!t.has(r.id.name)&&[`ArrowFunctionExpression`,`FunctionExpression`].includes(r.init?.type??``)&&s(r)}},CallExpression(t){c.CallExpression?.(t),(f(t)||m(e,t))&&s(t);let n=d(e,t.callee);n&&[`zod`,`zod/v4`].includes(n.source)&&s(t)},MemberExpression(t){let r=g(t);if(r.length>=4&&r[1]===`domain`){let i=d(e,y(t));i?.name===`internal`&&/_generated\/api/.test(i.source)&&n.add(r[2])}},NewExpression:s,IfStatement:s,SwitchStatement:s,ConditionalExpression:s,"Program:exit"(t){(n.size<2||o)&&e.report({node:o??t,messageId:`ownership`})}}}},"internal-function-ownership":{meta:_(`Place internal handlers with their owner, never in root, api/, or shared/.`,{ownership:`Declare system/internal handlers in domain/<module>/, cross-domain application/, migrations/, or an isolated component.`}),create(e){let t=i(e)??``;return o(e,e.filename)||/^(?:domain\/(?!shared\/)[^/]+\/|application\/|migrations\/)/.test(t)?{}:{CallExpression(t){if(t.callee.type===`CallExpression`)return;let n=d(e,t.callee);n&&(h(e,n.source)&&/^system(Query|Mutation|Action)$/.test(n.name)||/(?:_generated\/server|convex\/server)/.test(n.source)&&/^internal(Query|Mutation|Action)(Generic)?$/.test(n.name))&&e.report({node:t,messageId:`ownership`})}}}},"domain-file-responsibilities":{meta:_(`Keep invariants pure, reads read-only, shapes declarative, and I/O action-side.`,{ownership:`Respect this domain file responsibility: pure rules, read-only queries, declarative schemas/tables/constants, and external I/O only in actions or integrations.`}),create(e){let n=i(e)??``,o=n===`domain/table.ts`;if(!o&&!/^domain\/[^/]+\//.test(n))return{};let s=S(n).replace(/\.[cm]?[jt]s$/,``),c=s===`rules`,l=s===`queries`,u=[`schema`,`table`,`constants`].includes(s),g=/(?:^|\/)(?:actions|integrations|providers)(?:\/|\.)/.test(n)||/(?:^|_)actions\./.test(n),_=t(),y=null;function C(e){y??=e}let w=b(e,(t,n)=>{if(x(t))return;let a=r(_,e.filename,n),s=a&&i(e,a);o&&n!==`cvx-kit/zod-table`&&!/^domain\/[^/]+\/table(?:\.[cm]?[jt]s)?$/.test(s??``)&&C(t),c&&s&&!/(?:^|\/)(?:rules|constants)(?:\.[cm]?[jt]s)?$/.test(s)&&C(t),(c||l||u)&&!s&&![`zod`,`zod/v4`,`convex/values`,`cvx-kit`,`cvx-kit/zod-table`,`cvx-kit/errors`].includes(n)&&C(t),l&&s&&/(?:^|\/)(?:commands|actions|integrations|providers)(?:[./]|$)/.test(s)&&C(t)});return{...w,Program(e){if(o)for(let t of e.body){if(t.type===`ImportDeclaration`||t.type===`EmptyStatement`)continue;let e=t.type===`ExportNamedDeclaration`?t.declaration:t;(e?.type!==`VariableDeclaration`||e.declarations.some(e=>e.init?.type!==`CallExpression`))&&C(t)}},CallExpression(t){if(w.CallExpression?.(t),o){let n=d(e,t.callee);(n?.source!==`cvx-kit/zod-table`||n.name!==`createModule`)&&C(t)}let n=t.callee.type===`MemberExpression`?v(t.callee):null;(c||u)&&(f(t)||[`runQuery`,`runMutation`,`runAction`,`runAfter`,`runAt`].includes(n??``))&&C(t),l&&(p(t)||[`runMutation`,`runAction`,`runAfter`,`runAt`].includes(n??``))&&C(t);let r=d(e,t.callee);r&&h(e,r.source)&&(c||u||l&&/(?:Mutation|Action)$/.test(r.name))&&C(t),l&&t.callee.type===`MemberExpression`&&v(t.callee.object)===`storage`&&[`store`,`delete`,`generateUploadUrl`].includes(n??``)&&C(t),!g&&m(e,t)&&C(t),c&&t.callee.type===`MemberExpression`&&t.callee.object.type===`Identifier`&&!a(e,t.callee.object)?.defs.length&&(t.callee.object.name===`Date`&&n===`now`||t.callee.object.name===`Math`&&n===`random`)&&C(t)},MemberExpression(e){c&&[`db`,`storage`,`scheduler`,`env`].includes(v(e)??``)&&C(e)},NewExpression(t){(c||l||u)&&(t.callee.type!==`Identifier`||a(e,t.callee)?.defs.length||![`Error`,`TypeError`,`RangeError`,`Set`,`Map`,`RegExp`].includes(t.callee.name))&&C(t)},"Program:exit"(){y&&e.report({node:y,messageId:`ownership`})}}}}};export{E as ownershipRules};
1
+ import{architectureAnchor as e,createResolver as t,inspectArchitecture as n,resolveImport as r}from"./architecture.mjs";import{appFile as i,binding as a,componentRoot as o,consumerOptions as s,containsComponentReference as c,delegatingBody as l,exportedNames as u,imported as d,isDbAccess as f,isDbWrite as p,isExternalCall as m,isFunctionsImport as h,memberPath as g,metadata as _,propertyName as v,rootMember as y,sourceVisitors as b,typeOnlySource as x}from"./ast.mjs";import{basename as S,resolve as C}from"node:path";import{existsSync as w,realpathSync as T}from"node:fs";const E={"project-structure":{meta:_(`Validate the application tree, colocated tests, and module cycles.`,{structure:`{{file}}: {{message}}`}),create(t){let r=s.parse(t.options[0]??{}),i=C(t.cwd,r.convexDir);return(w(t.filename)?T(t.filename):C(t.filename))===e(i)?{Program(e){for(let i of n({cwd:t.cwd,convexDir:r.convexDir}))t.report({node:e,messageId:`structure`,data:{file:i.file,message:i.message}})}}:{}}},"root-wiring-only":{meta:_(`Keep root files limited to configuration, assembly, and component facades.`,{ownership:`Root files only wire configuration and components. Move behavior into domain/<module>/: {{reason}}.`}),create(e){let t=i(e);if(!t||t.includes(`/`))return{};let n=null,r=`business implementation`,a=!1,o=/^(?:convex\.config|auth\.config|vite\.config|vitest\.config|auth|schema|functions|triggers|foundation|http|crons)\.[cm]?[jt]s$/.test(t);function s(e){n??=e}return{Program(e){e.body.some(e=>e.type===`FunctionDeclaration`||e.type===`ExportNamedDeclaration`&&e.declaration?.type===`FunctionDeclaration`)&&s(e)},NewExpression(t){d(e,t.callee)&&t.arguments.some(t=>c(e,t))&&(a=!0)},CallExpression(n){d(e,n.callee)&&n.arguments.some(t=>c(e,t))&&(a=!0),(p(n)||m(e,n)||t===`schema.ts`&&d(e,n.callee)?.name!==`defineSchema`)&&s(n)},ArrowFunctionExpression(e){(!e.body||!l(e.body))&&s(e)},FunctionExpression(e){(!e.body||!l(e.body))&&s(e)},IfStatement:s,SwitchStatement:s,ConditionalExpression:s,ForStatement:s,ForOfStatement:s,WhileStatement:s,"Program:exit"(t){!o&&!a&&(n=t,r=`unknown root file; only declared component facades may add root source files`),n&&e.report({node:n,messageId:`ownership`,data:{reason:r}})}}}},"application-orchestration":{meta:_(`Reserve application/ for thin cross-domain coordination.`,{ownership:`application/ only coordinates two or more domains. Move schemas, providers, storage access, helpers, and business decisions into their owning domain.`}),create(e){if(!i(e)?.startsWith(`application/`))return{};let n=/* @__PURE__ */ new Set,a=t(),o=null;function s(e){o??=e}let c=b(e,(t,o)=>{if(x(t))return;let c=r(a,e.filename,o),l=c&&i(e,c),u=l?.match(/^domain\/([^/]+)\/(?:commands|queries|rules)(?:\.[cm]?[jt]s)?$/);u&&u[1]!==`shared`&&n.add(u[1]),l?.startsWith(`domain/`)&&!u&&!l.startsWith(`domain/shared/`)&&s(t),!l&&![`cvx-kit`,`cvx-kit/components/foundation`,`@convex-dev/workflow`,`convex/values`].includes(o)&&s(t)});return{...c,Program(e){let t=u(e);for(let n of e.body){n.type===`FunctionDeclaration`&&n.id&&!t.has(n.id.name)&&s(n);let e=n.type===`ExportNamedDeclaration`?n.declaration:n;if((e?.type===`TSTypeAliasDeclaration`||e?.type===`TSInterfaceDeclaration`)&&s(n),e?.type===`VariableDeclaration`)for(let r of e.declarations)r.init&&[`ObjectExpression`,`ArrayExpression`,`Literal`].includes(r.init.type)&&s(r),n.type===`VariableDeclaration`&&r.id.type===`Identifier`&&!t.has(r.id.name)&&[`ArrowFunctionExpression`,`FunctionExpression`].includes(r.init?.type??``)&&s(r)}},CallExpression(t){c.CallExpression?.(t),(f(t)||m(e,t))&&s(t);let n=d(e,t.callee);n&&[`zod`,`zod/v4`].includes(n.source)&&s(t)},MemberExpression(t){let r=g(t);if(r.length>=4&&r[1]===`domain`){let i=d(e,y(t));i?.name===`internal`&&/_generated\/api/.test(i.source)&&n.add(r[2])}},NewExpression:s,IfStatement:s,SwitchStatement:s,ConditionalExpression:s,"Program:exit"(t){(n.size<2||o)&&e.report({node:o??t,messageId:`ownership`})}}}},"internal-function-ownership":{meta:_(`Place internal handlers with their owner, never in root, api/, or shared/.`,{ownership:`Declare system/internal handlers in domain/<module>/, cross-domain application/, migrations/, or an isolated component.`}),create(e){let t=i(e)??``;return o(e,e.filename)||/^(?:domain\/(?!shared\/)[^/]+\/|application\/|migrations\/)/.test(t)?{}:{CallExpression(t){if(t.callee.type===`CallExpression`)return;let n=d(e,t.callee);n&&(h(e,n.source)&&/^system(Query|Mutation|Action)$/.test(n.name)||/(?:_generated\/server|convex\/server)/.test(n.source)&&/^internal(Query|Mutation|Action)(Generic)?$/.test(n.name))&&e.report({node:t,messageId:`ownership`})}}}},"domain-file-responsibilities":{meta:_(`Keep invariants pure, reads read-only, shapes declarative, and I/O action-side.`,{ownership:`Respect this domain file responsibility: pure rules, read-only queries, declarative schemas/tables/constants, and external I/O only in actions or integrations.`}),create(e){let n=i(e)??``,o=n===`domain/table.ts`;if(!o&&!/^domain\/[^/]+\//.test(n))return{};let s=S(n).replace(/\.[cm]?[jt]s$/,``),c=s===`rules`,l=s===`queries`,u=[`schema`,`table`,`contracts`,`constants`].includes(s),g=/(?:^|\/)(?:actions|integrations|providers)(?:\/|\.)/.test(n)||/(?:^|_)actions\./.test(n),_=t(),y=null;function C(e){y??=e}let w=b(e,(t,n)=>{if(x(t))return;let a=r(_,e.filename,n),s=a&&i(e,a);o&&n!==`cvx-kit/zod-table`&&!/^domain\/[^/]+\/table(?:\.[cm]?[jt]s)?$/.test(s??``)&&C(t),c&&s&&!/(?:^|\/)(?:rules|constants)(?:\.[cm]?[jt]s)?$/.test(s)&&C(t),(c||l||u)&&!s&&![`zod`,`zod/v4`,`convex/values`,`cvx-kit`,`cvx-kit/zod-table`,`cvx-kit/errors`,`cvx-kit/contracts`].includes(n)&&C(t),l&&s&&/(?:^|\/)(?:commands|actions|integrations|providers)(?:[./]|$)/.test(s)&&C(t)});return{...w,Program(e){if(o)for(let t of e.body){if(t.type===`ImportDeclaration`||t.type===`EmptyStatement`)continue;let e=t.type===`ExportNamedDeclaration`?t.declaration:t;(e?.type!==`VariableDeclaration`||e.declarations.some(e=>e.init?.type!==`CallExpression`))&&C(t)}},CallExpression(t){if(w.CallExpression?.(t),o){let n=d(e,t.callee);(n?.source!==`cvx-kit/zod-table`||n.name!==`createModule`)&&C(t)}let n=t.callee.type===`MemberExpression`?v(t.callee):null;(c||u)&&(f(t)||[`runQuery`,`runMutation`,`runAction`,`runAfter`,`runAt`].includes(n??``))&&C(t),l&&(p(t)||[`runMutation`,`runAction`,`runAfter`,`runAt`].includes(n??``))&&C(t);let r=d(e,t.callee);r&&h(e,r.source)&&(c||u||l&&/(?:Mutation|Action)$/.test(r.name))&&C(t),l&&t.callee.type===`MemberExpression`&&v(t.callee.object)===`storage`&&[`store`,`delete`,`generateUploadUrl`].includes(n??``)&&C(t),!g&&m(e,t)&&C(t),c&&t.callee.type===`MemberExpression`&&t.callee.object.type===`Identifier`&&!a(e,t.callee.object)?.defs.length&&(t.callee.object.name===`Date`&&n===`now`||t.callee.object.name===`Math`&&n===`random`)&&C(t)},Property(e){s===`contracts`&&[`handler`,`context`,`audit`,`prepare`,`middleware`,`guard`].includes(e.key.type===`Identifier`?e.key.name:String(e.key.type===`Literal`?e.key.value:``))&&C(e)},MemberExpression(e){c&&[`db`,`storage`,`scheduler`,`env`].includes(v(e)??``)&&C(e)},NewExpression(t){(c||l||u)&&(t.callee.type!==`Identifier`||a(e,t.callee)?.defs.length||![`Error`,`TypeError`,`RangeError`,`Set`,`Map`,`RegExp`].includes(t.callee.name))&&C(t)},"Program:exit"(){y&&e.report({node:y,messageId:`ownership`})}}}}};export{E as ownershipRules};
2
2
  //# sourceMappingURL=ownership.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ownership.mjs","names":["ownershipRules","metadata","settings","consumerOptions","context","root","resolve","existsSync","realpathSync","architectureAnchor","issue","inspectArchitecture","file","appFile","reason","componentFacade","standard","flag","node","statement","imported","containsComponentReference","argument","isDbWrite","isExternalCall","delegatingBody","owners","resolver","createResolver","sources","sourceVisitors","typeOnlySource","target","resolveImport","source","path","match","publicNames","exportedNames","declaration","item","isDbAccess","ref","memberPath","rootMember","componentRoot","isFunctionsImport","assembly","role","basename","pure","read","declarative","actionSide","method","propertyName","constructor","binding"],"sources":["../../src/oxlint/ownership.ts"],"sourcesContent":["import { existsSync, realpathSync } from 'node:fs'\nimport { basename, resolve } from 'node:path'\nimport type { CreateRule, ESTree } from '@oxlint/plugins'\nimport {\n\tarchitectureAnchor,\n\tinspectArchitecture,\n\tcreateResolver,\n\tresolveImport,\n} from './architecture'\nimport {\n\tconsumerOptions,\n\tappFile,\n\timported,\n\tsourceVisitors,\n\tisFunctionsImport,\n\ttypeOnlySource,\n\tisDbAccess,\n\tisExternalCall,\n\tcontainsComponentReference,\n\trootMember,\n\tmemberPath,\n\tisDbWrite,\n\tmetadata,\n\tcomponentRoot,\n\tpropertyName,\n\tbinding,\n\texportedNames,\n\tdelegatingBody,\n} from './ast'\n\nexport const ownershipRules = {\n\t'project-structure': {\n\t\tmeta: metadata('Validate the application tree, colocated tests, and module cycles.', {\n\t\t\tstructure: '{{file}}: {{message}}',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tconst settings = consumerOptions.parse(context.options[0] ?? {})\n\t\t\tconst root = resolve(context.cwd, settings.convexDir)\n\t\t\tif (\n\t\t\t\t(existsSync(context.filename)\n\t\t\t\t\t? realpathSync(context.filename)\n\t\t\t\t\t: resolve(context.filename)) !== architectureAnchor(root)\n\t\t\t)\n\t\t\t\treturn {}\n\t\t\treturn {\n\t\t\t\tProgram(node) {\n\t\t\t\t\tfor (const issue of inspectArchitecture({\n\t\t\t\t\t\tcwd: context.cwd,\n\t\t\t\t\t\tconvexDir: settings.convexDir,\n\t\t\t\t\t}))\n\t\t\t\t\t\tcontext.report({\n\t\t\t\t\t\t\tnode,\n\t\t\t\t\t\t\tmessageId: 'structure',\n\t\t\t\t\t\t\tdata: { file: issue.file, message: issue.message },\n\t\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'root-wiring-only': {\n\t\tmeta: metadata('Keep root files limited to configuration, assembly, and component facades.', {\n\t\t\townership:\n\t\t\t\t'Root files only wire configuration and components. Move behavior into domain/<module>/: {{reason}}.',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tconst file = appFile(context)\n\t\t\tif (!file || file.includes('/')) return {}\n\t\t\tlet issue: ESTree.Node | null = null\n\t\t\tlet reason = 'business implementation'\n\t\t\tlet componentFacade = false\n\t\t\tconst standard =\n\t\t\t\t/^(?:convex\\.config|auth\\.config|vite\\.config|vitest\\.config|auth|schema|functions|triggers|foundation|http|crons)\\.[cm]?[jt]s$/.test(\n\t\t\t\t\tfile,\n\t\t\t\t)\n\t\t\tfunction flag(node: ESTree.Node) {\n\t\t\t\tissue ??= node\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tProgram(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.body.some(\n\t\t\t\t\t\t\t(statement) =>\n\t\t\t\t\t\t\t\tstatement.type === 'FunctionDeclaration' ||\n\t\t\t\t\t\t\t\t(statement.type === 'ExportNamedDeclaration' &&\n\t\t\t\t\t\t\t\t\tstatement.declaration?.type === 'FunctionDeclaration'),\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tNewExpression(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\timported(context, node.callee) &&\n\t\t\t\t\t\tnode.arguments.some((argument) => containsComponentReference(context, argument))\n\t\t\t\t\t)\n\t\t\t\t\t\tcomponentFacade = true\n\t\t\t\t},\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\timported(context, node.callee) &&\n\t\t\t\t\t\tnode.arguments.some((argument) => containsComponentReference(context, argument))\n\t\t\t\t\t)\n\t\t\t\t\t\tcomponentFacade = true\n\t\t\t\t\tif (\n\t\t\t\t\t\tisDbWrite(node) ||\n\t\t\t\t\t\tisExternalCall(context, node) ||\n\t\t\t\t\t\t(file === 'schema.ts' && !(imported(context, node.callee)?.name === 'defineSchema'))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tArrowFunctionExpression(node) {\n\t\t\t\t\tif (!node.body || !delegatingBody(node.body)) flag(node)\n\t\t\t\t},\n\t\t\t\tFunctionExpression(node) {\n\t\t\t\t\tif (!node.body || !delegatingBody(node.body)) flag(node)\n\t\t\t\t},\n\t\t\t\tIfStatement: flag,\n\t\t\t\tSwitchStatement: flag,\n\t\t\t\tConditionalExpression: flag,\n\t\t\t\tForStatement: flag,\n\t\t\t\tForOfStatement: flag,\n\t\t\t\tWhileStatement: flag,\n\t\t\t\t'Program:exit'(node) {\n\t\t\t\t\tif (!standard && !componentFacade) {\n\t\t\t\t\t\tissue = node\n\t\t\t\t\t\treason = 'unknown root file; only declared component facades may add root source files'\n\t\t\t\t\t}\n\t\t\t\t\tif (issue) context.report({ node: issue, messageId: 'ownership', data: { reason } })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'application-orchestration': {\n\t\tmeta: metadata('Reserve application/ for thin cross-domain coordination.', {\n\t\t\townership:\n\t\t\t\t'application/ only coordinates two or more domains. Move schemas, providers, storage access, helpers, and business decisions into their owning domain.',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tif (!appFile(context)?.startsWith('application/')) return {}\n\t\t\tconst owners = new Set<string>()\n\t\t\tconst resolver = createResolver()\n\t\t\tlet issue: ESTree.Node | null = null\n\t\t\tfunction flag(node: ESTree.Node) {\n\t\t\t\tissue ??= node\n\t\t\t}\n\t\t\tconst sources = sourceVisitors(context, (node, source) => {\n\t\t\t\tif (typeOnlySource(node)) return\n\t\t\t\tconst target = resolveImport(resolver, context.filename, source)\n\t\t\t\tconst path = target && appFile(context, target)\n\t\t\t\tconst match = path?.match(/^domain\\/([^/]+)\\/(?:commands|queries|rules)(?:\\.[cm]?[jt]s)?$/)\n\t\t\t\tif (match && match[1] !== 'shared') owners.add(match[1])\n\t\t\t\tif (path?.startsWith('domain/') && !match && !path.startsWith('domain/shared/')) flag(node)\n\t\t\t\tif (\n\t\t\t\t\t!path &&\n\t\t\t\t\t![\n\t\t\t\t\t\t'cvx-kit',\n\t\t\t\t\t\t'cvx-kit/components/foundation',\n\t\t\t\t\t\t'@convex-dev/workflow',\n\t\t\t\t\t\t'convex/values',\n\t\t\t\t\t].includes(source)\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t})\n\t\t\treturn {\n\t\t\t\t...sources,\n\t\t\t\tProgram(node) {\n\t\t\t\t\tconst publicNames = exportedNames(node)\n\t\t\t\t\tfor (const statement of node.body) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tstatement.type === 'FunctionDeclaration' &&\n\t\t\t\t\t\t\tstatement.id &&\n\t\t\t\t\t\t\t!publicNames.has(statement.id.name)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tflag(statement)\n\t\t\t\t\t\tconst declaration =\n\t\t\t\t\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tdeclaration?.type === 'TSTypeAliasDeclaration' ||\n\t\t\t\t\t\t\tdeclaration?.type === 'TSInterfaceDeclaration'\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tflag(statement)\n\t\t\t\t\t\tif (declaration?.type === 'VariableDeclaration')\n\t\t\t\t\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\titem.init &&\n\t\t\t\t\t\t\t\t\t['ObjectExpression', 'ArrayExpression', 'Literal'].includes(item.init.type)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tflag(item)\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tstatement.type === 'VariableDeclaration' &&\n\t\t\t\t\t\t\t\t\titem.id.type === 'Identifier' &&\n\t\t\t\t\t\t\t\t\t!publicNames.has(item.id.name) &&\n\t\t\t\t\t\t\t\t\t['ArrowFunctionExpression', 'FunctionExpression'].includes(item.init?.type ?? '')\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tflag(item)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tsources.CallExpression?.(node)\n\t\t\t\t\tif (isDbAccess(node) || isExternalCall(context, node)) flag(node)\n\t\t\t\t\tconst ref = imported(context, node.callee)\n\t\t\t\t\tif (ref && ['zod', 'zod/v4'].includes(ref.source)) flag(node)\n\t\t\t\t},\n\t\t\t\tMemberExpression(node) {\n\t\t\t\t\tconst path = memberPath(node)\n\t\t\t\t\tif (path.length >= 4 && path[1] === 'domain') {\n\t\t\t\t\t\tconst ref = imported(context, rootMember(node))\n\t\t\t\t\t\tif (ref?.name === 'internal' && /_generated\\/api/.test(ref.source)) owners.add(path[2])\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tNewExpression: flag,\n\t\t\t\tIfStatement: flag,\n\t\t\t\tSwitchStatement: flag,\n\t\t\t\tConditionalExpression: flag,\n\t\t\t\t'Program:exit'(node) {\n\t\t\t\t\tif (owners.size < 2 || issue)\n\t\t\t\t\t\tcontext.report({ node: issue ?? node, messageId: 'ownership' })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'internal-function-ownership': {\n\t\tmeta: metadata('Place internal handlers with their owner, never in root, api/, or shared/.', {\n\t\t\townership:\n\t\t\t\t'Declare system/internal handlers in domain/<module>/, cross-domain application/, migrations/, or an isolated component.',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tconst file = appFile(context) ?? ''\n\t\t\tif (\n\t\t\t\tcomponentRoot(context, context.filename) ||\n\t\t\t\t/^(?:domain\\/(?!shared\\/)[^/]+\\/|application\\/|migrations\\/)/.test(file)\n\t\t\t)\n\t\t\t\treturn {}\n\t\t\treturn {\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tif (node.callee.type === 'CallExpression') return\n\t\t\t\t\tconst ref = imported(context, node.callee)\n\t\t\t\t\tif (\n\t\t\t\t\t\tref &&\n\t\t\t\t\t\t((isFunctionsImport(context, ref.source) &&\n\t\t\t\t\t\t\t/^system(Query|Mutation|Action)$/.test(ref.name)) ||\n\t\t\t\t\t\t\t(/(?:_generated\\/server|convex\\/server)/.test(ref.source) &&\n\t\t\t\t\t\t\t\t/^internal(Query|Mutation|Action)(Generic)?$/.test(ref.name)))\n\t\t\t\t\t)\n\t\t\t\t\t\tcontext.report({ node, messageId: 'ownership' })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'domain-file-responsibilities': {\n\t\tmeta: metadata(\n\t\t\t'Keep invariants pure, reads read-only, shapes declarative, and I/O action-side.',\n\t\t\t{\n\t\t\t\townership:\n\t\t\t\t\t'Respect this domain file responsibility: pure rules, read-only queries, declarative schemas/tables/constants, and external I/O only in actions or integrations.',\n\t\t\t},\n\t\t),\n\t\tcreate(context) {\n\t\t\tconst file = appFile(context) ?? ''\n\t\t\tconst assembly = file === 'domain/table.ts'\n\t\t\tif (!assembly && !/^domain\\/[^/]+\\//.test(file)) return {}\n\t\t\tconst role = basename(file).replace(/\\.[cm]?[jt]s$/, '')\n\t\t\tconst pure = role === 'rules'\n\t\t\tconst read = role === 'queries'\n\t\t\tconst declarative = ['schema', 'table', 'constants'].includes(role)\n\t\t\tconst actionSide =\n\t\t\t\t/(?:^|\\/)(?:actions|integrations|providers)(?:\\/|\\.)/.test(file) ||\n\t\t\t\t/(?:^|_)actions\\./.test(file)\n\t\t\tconst resolver = createResolver()\n\t\t\tlet issue: ESTree.Node | null = null\n\t\t\tfunction flag(node: ESTree.Node) {\n\t\t\t\tissue ??= node\n\t\t\t}\n\t\t\tconst sources = sourceVisitors(context, (node, source) => {\n\t\t\t\tif (typeOnlySource(node)) return\n\t\t\t\tconst target = resolveImport(resolver, context.filename, source)\n\t\t\t\tconst path = target && appFile(context, target)\n\t\t\t\tif (\n\t\t\t\t\tassembly &&\n\t\t\t\t\tsource !== 'cvx-kit/zod-table' &&\n\t\t\t\t\t!/^domain\\/[^/]+\\/table(?:\\.[cm]?[jt]s)?$/.test(path ?? '')\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t\tif (pure && path && !/(?:^|\\/)(?:rules|constants)(?:\\.[cm]?[jt]s)?$/.test(path)) flag(node)\n\t\t\t\tif (\n\t\t\t\t\t(pure || read || declarative) &&\n\t\t\t\t\t!path &&\n\t\t\t\t\t![\n\t\t\t\t\t\t'zod',\n\t\t\t\t\t\t'zod/v4',\n\t\t\t\t\t\t'convex/values',\n\t\t\t\t\t\t'cvx-kit',\n\t\t\t\t\t\t'cvx-kit/zod-table',\n\t\t\t\t\t\t'cvx-kit/errors',\n\t\t\t\t\t].includes(source)\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t\tif (\n\t\t\t\t\tread &&\n\t\t\t\t\tpath &&\n\t\t\t\t\t/(?:^|\\/)(?:commands|actions|integrations|providers)(?:[./]|$)/.test(path)\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t})\n\t\t\treturn {\n\t\t\t\t...sources,\n\t\t\t\tProgram(node) {\n\t\t\t\t\tif (!assembly) return\n\t\t\t\t\tfor (const statement of node.body) {\n\t\t\t\t\t\tif (statement.type === 'ImportDeclaration' || statement.type === 'EmptyStatement')\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\tconst declaration =\n\t\t\t\t\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tdeclaration?.type !== 'VariableDeclaration' ||\n\t\t\t\t\t\t\tdeclaration.declarations.some((item) => item.init?.type !== 'CallExpression')\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tflag(statement)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tsources.CallExpression?.(node)\n\t\t\t\t\tif (assembly) {\n\t\t\t\t\t\tconst ref = imported(context, node.callee)\n\t\t\t\t\t\tif (ref?.source !== 'cvx-kit/zod-table' || ref.name !== 'createModule') flag(node)\n\t\t\t\t\t}\n\t\t\t\t\tconst method = node.callee.type === 'MemberExpression' ? propertyName(node.callee) : null\n\t\t\t\t\tif (\n\t\t\t\t\t\t(pure || declarative) &&\n\t\t\t\t\t\t(isDbAccess(node) ||\n\t\t\t\t\t\t\t['runQuery', 'runMutation', 'runAction', 'runAfter', 'runAt'].includes(method ?? ''))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tif (\n\t\t\t\t\t\tread &&\n\t\t\t\t\t\t(isDbWrite(node) ||\n\t\t\t\t\t\t\t['runMutation', 'runAction', 'runAfter', 'runAt'].includes(method ?? ''))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tconst constructor = imported(context, node.callee)\n\t\t\t\t\tif (\n\t\t\t\t\t\tconstructor &&\n\t\t\t\t\t\tisFunctionsImport(context, constructor.source) &&\n\t\t\t\t\t\t(pure || declarative || (read && /(?:Mutation|Action)$/.test(constructor.name)))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tif (\n\t\t\t\t\t\tread &&\n\t\t\t\t\t\tnode.callee.type === 'MemberExpression' &&\n\t\t\t\t\t\tpropertyName(node.callee.object) === 'storage' &&\n\t\t\t\t\t\t['store', 'delete', 'generateUploadUrl'].includes(method ?? '')\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tif (!actionSide && isExternalCall(context, node)) flag(node)\n\t\t\t\t\tif (\n\t\t\t\t\t\tpure &&\n\t\t\t\t\t\tnode.callee.type === 'MemberExpression' &&\n\t\t\t\t\t\tnode.callee.object.type === 'Identifier' &&\n\t\t\t\t\t\t!binding(context, node.callee.object)?.defs.length &&\n\t\t\t\t\t\t((node.callee.object.name === 'Date' && method === 'now') ||\n\t\t\t\t\t\t\t(node.callee.object.name === 'Math' && method === 'random'))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tMemberExpression(node) {\n\t\t\t\t\tif (pure && ['db', 'storage', 'scheduler', 'env'].includes(propertyName(node) ?? ''))\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tNewExpression(node) {\n\t\t\t\t\tif (!(pure || read || declarative)) return\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.callee.type === 'Identifier' &&\n\t\t\t\t\t\t!binding(context, node.callee)?.defs.length &&\n\t\t\t\t\t\t['Error', 'TypeError', 'RangeError', 'Set', 'Map', 'RegExp'].includes(node.callee.name)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn\n\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\t'Program:exit'() {\n\t\t\t\t\tif (issue) context.report({ node: issue, messageId: 'ownership' })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n} satisfies Record<string, CreateRule>\n\nexport type OwnershipRuleName = keyof typeof ownershipRules\n"],"mappings":"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"}
1
+ {"version":3,"file":"ownership.mjs","names":["ownershipRules","metadata","settings","consumerOptions","context","root","resolve","existsSync","realpathSync","architectureAnchor","issue","inspectArchitecture","file","appFile","reason","componentFacade","standard","flag","node","statement","imported","containsComponentReference","argument","isDbWrite","isExternalCall","delegatingBody","owners","resolver","createResolver","sources","sourceVisitors","typeOnlySource","target","resolveImport","source","path","match","publicNames","exportedNames","declaration","item","isDbAccess","ref","memberPath","rootMember","componentRoot","isFunctionsImport","assembly","role","basename","pure","read","declarative","actionSide","method","propertyName","constructor","binding"],"sources":["../../src/oxlint/ownership.ts"],"sourcesContent":["import { existsSync, realpathSync } from 'node:fs'\nimport { basename, resolve } from 'node:path'\nimport type { CreateRule, ESTree } from '@oxlint/plugins'\nimport {\n\tarchitectureAnchor,\n\tinspectArchitecture,\n\tcreateResolver,\n\tresolveImport,\n} from './architecture'\nimport {\n\tconsumerOptions,\n\tappFile,\n\timported,\n\tsourceVisitors,\n\tisFunctionsImport,\n\ttypeOnlySource,\n\tisDbAccess,\n\tisExternalCall,\n\tcontainsComponentReference,\n\trootMember,\n\tmemberPath,\n\tisDbWrite,\n\tmetadata,\n\tcomponentRoot,\n\tpropertyName,\n\tbinding,\n\texportedNames,\n\tdelegatingBody,\n} from './ast'\n\nexport const ownershipRules = {\n\t'project-structure': {\n\t\tmeta: metadata('Validate the application tree, colocated tests, and module cycles.', {\n\t\t\tstructure: '{{file}}: {{message}}',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tconst settings = consumerOptions.parse(context.options[0] ?? {})\n\t\t\tconst root = resolve(context.cwd, settings.convexDir)\n\t\t\tif (\n\t\t\t\t(existsSync(context.filename)\n\t\t\t\t\t? realpathSync(context.filename)\n\t\t\t\t\t: resolve(context.filename)) !== architectureAnchor(root)\n\t\t\t)\n\t\t\t\treturn {}\n\t\t\treturn {\n\t\t\t\tProgram(node) {\n\t\t\t\t\tfor (const issue of inspectArchitecture({\n\t\t\t\t\t\tcwd: context.cwd,\n\t\t\t\t\t\tconvexDir: settings.convexDir,\n\t\t\t\t\t}))\n\t\t\t\t\t\tcontext.report({\n\t\t\t\t\t\t\tnode,\n\t\t\t\t\t\t\tmessageId: 'structure',\n\t\t\t\t\t\t\tdata: { file: issue.file, message: issue.message },\n\t\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'root-wiring-only': {\n\t\tmeta: metadata('Keep root files limited to configuration, assembly, and component facades.', {\n\t\t\townership:\n\t\t\t\t'Root files only wire configuration and components. Move behavior into domain/<module>/: {{reason}}.',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tconst file = appFile(context)\n\t\t\tif (!file || file.includes('/')) return {}\n\t\t\tlet issue: ESTree.Node | null = null\n\t\t\tlet reason = 'business implementation'\n\t\t\tlet componentFacade = false\n\t\t\tconst standard =\n\t\t\t\t/^(?:convex\\.config|auth\\.config|vite\\.config|vitest\\.config|auth|schema|functions|triggers|foundation|http|crons)\\.[cm]?[jt]s$/.test(\n\t\t\t\t\tfile,\n\t\t\t\t)\n\t\t\tfunction flag(node: ESTree.Node) {\n\t\t\t\tissue ??= node\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tProgram(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.body.some(\n\t\t\t\t\t\t\t(statement) =>\n\t\t\t\t\t\t\t\tstatement.type === 'FunctionDeclaration' ||\n\t\t\t\t\t\t\t\t(statement.type === 'ExportNamedDeclaration' &&\n\t\t\t\t\t\t\t\t\tstatement.declaration?.type === 'FunctionDeclaration'),\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tNewExpression(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\timported(context, node.callee) &&\n\t\t\t\t\t\tnode.arguments.some((argument) => containsComponentReference(context, argument))\n\t\t\t\t\t)\n\t\t\t\t\t\tcomponentFacade = true\n\t\t\t\t},\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\timported(context, node.callee) &&\n\t\t\t\t\t\tnode.arguments.some((argument) => containsComponentReference(context, argument))\n\t\t\t\t\t)\n\t\t\t\t\t\tcomponentFacade = true\n\t\t\t\t\tif (\n\t\t\t\t\t\tisDbWrite(node) ||\n\t\t\t\t\t\tisExternalCall(context, node) ||\n\t\t\t\t\t\t(file === 'schema.ts' && !(imported(context, node.callee)?.name === 'defineSchema'))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tArrowFunctionExpression(node) {\n\t\t\t\t\tif (!node.body || !delegatingBody(node.body)) flag(node)\n\t\t\t\t},\n\t\t\t\tFunctionExpression(node) {\n\t\t\t\t\tif (!node.body || !delegatingBody(node.body)) flag(node)\n\t\t\t\t},\n\t\t\t\tIfStatement: flag,\n\t\t\t\tSwitchStatement: flag,\n\t\t\t\tConditionalExpression: flag,\n\t\t\t\tForStatement: flag,\n\t\t\t\tForOfStatement: flag,\n\t\t\t\tWhileStatement: flag,\n\t\t\t\t'Program:exit'(node) {\n\t\t\t\t\tif (!standard && !componentFacade) {\n\t\t\t\t\t\tissue = node\n\t\t\t\t\t\treason = 'unknown root file; only declared component facades may add root source files'\n\t\t\t\t\t}\n\t\t\t\t\tif (issue) context.report({ node: issue, messageId: 'ownership', data: { reason } })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'application-orchestration': {\n\t\tmeta: metadata('Reserve application/ for thin cross-domain coordination.', {\n\t\t\townership:\n\t\t\t\t'application/ only coordinates two or more domains. Move schemas, providers, storage access, helpers, and business decisions into their owning domain.',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tif (!appFile(context)?.startsWith('application/')) return {}\n\t\t\tconst owners = new Set<string>()\n\t\t\tconst resolver = createResolver()\n\t\t\tlet issue: ESTree.Node | null = null\n\t\t\tfunction flag(node: ESTree.Node) {\n\t\t\t\tissue ??= node\n\t\t\t}\n\t\t\tconst sources = sourceVisitors(context, (node, source) => {\n\t\t\t\tif (typeOnlySource(node)) return\n\t\t\t\tconst target = resolveImport(resolver, context.filename, source)\n\t\t\t\tconst path = target && appFile(context, target)\n\t\t\t\tconst match = path?.match(/^domain\\/([^/]+)\\/(?:commands|queries|rules)(?:\\.[cm]?[jt]s)?$/)\n\t\t\t\tif (match && match[1] !== 'shared') owners.add(match[1])\n\t\t\t\tif (path?.startsWith('domain/') && !match && !path.startsWith('domain/shared/')) flag(node)\n\t\t\t\tif (\n\t\t\t\t\t!path &&\n\t\t\t\t\t![\n\t\t\t\t\t\t'cvx-kit',\n\t\t\t\t\t\t'cvx-kit/components/foundation',\n\t\t\t\t\t\t'@convex-dev/workflow',\n\t\t\t\t\t\t'convex/values',\n\t\t\t\t\t].includes(source)\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t})\n\t\t\treturn {\n\t\t\t\t...sources,\n\t\t\t\tProgram(node) {\n\t\t\t\t\tconst publicNames = exportedNames(node)\n\t\t\t\t\tfor (const statement of node.body) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tstatement.type === 'FunctionDeclaration' &&\n\t\t\t\t\t\t\tstatement.id &&\n\t\t\t\t\t\t\t!publicNames.has(statement.id.name)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tflag(statement)\n\t\t\t\t\t\tconst declaration =\n\t\t\t\t\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tdeclaration?.type === 'TSTypeAliasDeclaration' ||\n\t\t\t\t\t\t\tdeclaration?.type === 'TSInterfaceDeclaration'\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tflag(statement)\n\t\t\t\t\t\tif (declaration?.type === 'VariableDeclaration')\n\t\t\t\t\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\titem.init &&\n\t\t\t\t\t\t\t\t\t['ObjectExpression', 'ArrayExpression', 'Literal'].includes(item.init.type)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tflag(item)\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tstatement.type === 'VariableDeclaration' &&\n\t\t\t\t\t\t\t\t\titem.id.type === 'Identifier' &&\n\t\t\t\t\t\t\t\t\t!publicNames.has(item.id.name) &&\n\t\t\t\t\t\t\t\t\t['ArrowFunctionExpression', 'FunctionExpression'].includes(item.init?.type ?? '')\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tflag(item)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tsources.CallExpression?.(node)\n\t\t\t\t\tif (isDbAccess(node) || isExternalCall(context, node)) flag(node)\n\t\t\t\t\tconst ref = imported(context, node.callee)\n\t\t\t\t\tif (ref && ['zod', 'zod/v4'].includes(ref.source)) flag(node)\n\t\t\t\t},\n\t\t\t\tMemberExpression(node) {\n\t\t\t\t\tconst path = memberPath(node)\n\t\t\t\t\tif (path.length >= 4 && path[1] === 'domain') {\n\t\t\t\t\t\tconst ref = imported(context, rootMember(node))\n\t\t\t\t\t\tif (ref?.name === 'internal' && /_generated\\/api/.test(ref.source)) owners.add(path[2])\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tNewExpression: flag,\n\t\t\t\tIfStatement: flag,\n\t\t\t\tSwitchStatement: flag,\n\t\t\t\tConditionalExpression: flag,\n\t\t\t\t'Program:exit'(node) {\n\t\t\t\t\tif (owners.size < 2 || issue)\n\t\t\t\t\t\tcontext.report({ node: issue ?? node, messageId: 'ownership' })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'internal-function-ownership': {\n\t\tmeta: metadata('Place internal handlers with their owner, never in root, api/, or shared/.', {\n\t\t\townership:\n\t\t\t\t'Declare system/internal handlers in domain/<module>/, cross-domain application/, migrations/, or an isolated component.',\n\t\t}),\n\t\tcreate(context) {\n\t\t\tconst file = appFile(context) ?? ''\n\t\t\tif (\n\t\t\t\tcomponentRoot(context, context.filename) ||\n\t\t\t\t/^(?:domain\\/(?!shared\\/)[^/]+\\/|application\\/|migrations\\/)/.test(file)\n\t\t\t)\n\t\t\t\treturn {}\n\t\t\treturn {\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tif (node.callee.type === 'CallExpression') return\n\t\t\t\t\tconst ref = imported(context, node.callee)\n\t\t\t\t\tif (\n\t\t\t\t\t\tref &&\n\t\t\t\t\t\t((isFunctionsImport(context, ref.source) &&\n\t\t\t\t\t\t\t/^system(Query|Mutation|Action)$/.test(ref.name)) ||\n\t\t\t\t\t\t\t(/(?:_generated\\/server|convex\\/server)/.test(ref.source) &&\n\t\t\t\t\t\t\t\t/^internal(Query|Mutation|Action)(Generic)?$/.test(ref.name)))\n\t\t\t\t\t)\n\t\t\t\t\t\tcontext.report({ node, messageId: 'ownership' })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\t'domain-file-responsibilities': {\n\t\tmeta: metadata(\n\t\t\t'Keep invariants pure, reads read-only, shapes declarative, and I/O action-side.',\n\t\t\t{\n\t\t\t\townership:\n\t\t\t\t\t'Respect this domain file responsibility: pure rules, read-only queries, declarative schemas/tables/constants, and external I/O only in actions or integrations.',\n\t\t\t},\n\t\t),\n\t\tcreate(context) {\n\t\t\tconst file = appFile(context) ?? ''\n\t\t\tconst assembly = file === 'domain/table.ts'\n\t\t\tif (!assembly && !/^domain\\/[^/]+\\//.test(file)) return {}\n\t\t\tconst role = basename(file).replace(/\\.[cm]?[jt]s$/, '')\n\t\t\tconst pure = role === 'rules'\n\t\t\tconst read = role === 'queries'\n\t\t\tconst declarative = ['schema', 'table', 'contracts', 'constants'].includes(role)\n\t\t\tconst actionSide =\n\t\t\t\t/(?:^|\\/)(?:actions|integrations|providers)(?:\\/|\\.)/.test(file) ||\n\t\t\t\t/(?:^|_)actions\\./.test(file)\n\t\t\tconst resolver = createResolver()\n\t\t\tlet issue: ESTree.Node | null = null\n\t\t\tfunction flag(node: ESTree.Node) {\n\t\t\t\tissue ??= node\n\t\t\t}\n\t\t\tconst sources = sourceVisitors(context, (node, source) => {\n\t\t\t\tif (typeOnlySource(node)) return\n\t\t\t\tconst target = resolveImport(resolver, context.filename, source)\n\t\t\t\tconst path = target && appFile(context, target)\n\t\t\t\tif (\n\t\t\t\t\tassembly &&\n\t\t\t\t\tsource !== 'cvx-kit/zod-table' &&\n\t\t\t\t\t!/^domain\\/[^/]+\\/table(?:\\.[cm]?[jt]s)?$/.test(path ?? '')\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t\tif (pure && path && !/(?:^|\\/)(?:rules|constants)(?:\\.[cm]?[jt]s)?$/.test(path)) flag(node)\n\t\t\t\tif (\n\t\t\t\t\t(pure || read || declarative) &&\n\t\t\t\t\t!path &&\n\t\t\t\t\t![\n\t\t\t\t\t\t'zod',\n\t\t\t\t\t\t'zod/v4',\n\t\t\t\t\t\t'convex/values',\n\t\t\t\t\t\t'cvx-kit',\n\t\t\t\t\t\t'cvx-kit/zod-table',\n\t\t\t\t\t\t'cvx-kit/errors',\n\t\t\t\t\t\t'cvx-kit/contracts',\n\t\t\t\t\t].includes(source)\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t\tif (\n\t\t\t\t\tread &&\n\t\t\t\t\tpath &&\n\t\t\t\t\t/(?:^|\\/)(?:commands|actions|integrations|providers)(?:[./]|$)/.test(path)\n\t\t\t\t)\n\t\t\t\t\tflag(node)\n\t\t\t})\n\t\t\treturn {\n\t\t\t\t...sources,\n\t\t\t\tProgram(node) {\n\t\t\t\t\tif (!assembly) return\n\t\t\t\t\tfor (const statement of node.body) {\n\t\t\t\t\t\tif (statement.type === 'ImportDeclaration' || statement.type === 'EmptyStatement')\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\tconst declaration =\n\t\t\t\t\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tdeclaration?.type !== 'VariableDeclaration' ||\n\t\t\t\t\t\t\tdeclaration.declarations.some((item) => item.init?.type !== 'CallExpression')\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tflag(statement)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tCallExpression(node) {\n\t\t\t\t\tsources.CallExpression?.(node)\n\t\t\t\t\tif (assembly) {\n\t\t\t\t\t\tconst ref = imported(context, node.callee)\n\t\t\t\t\t\tif (ref?.source !== 'cvx-kit/zod-table' || ref.name !== 'createModule') flag(node)\n\t\t\t\t\t}\n\t\t\t\t\tconst method = node.callee.type === 'MemberExpression' ? propertyName(node.callee) : null\n\t\t\t\t\tif (\n\t\t\t\t\t\t(pure || declarative) &&\n\t\t\t\t\t\t(isDbAccess(node) ||\n\t\t\t\t\t\t\t['runQuery', 'runMutation', 'runAction', 'runAfter', 'runAt'].includes(method ?? ''))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tif (\n\t\t\t\t\t\tread &&\n\t\t\t\t\t\t(isDbWrite(node) ||\n\t\t\t\t\t\t\t['runMutation', 'runAction', 'runAfter', 'runAt'].includes(method ?? ''))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tconst constructor = imported(context, node.callee)\n\t\t\t\t\tif (\n\t\t\t\t\t\tconstructor &&\n\t\t\t\t\t\tisFunctionsImport(context, constructor.source) &&\n\t\t\t\t\t\t(pure || declarative || (read && /(?:Mutation|Action)$/.test(constructor.name)))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tif (\n\t\t\t\t\t\tread &&\n\t\t\t\t\t\tnode.callee.type === 'MemberExpression' &&\n\t\t\t\t\t\tpropertyName(node.callee.object) === 'storage' &&\n\t\t\t\t\t\t['store', 'delete', 'generateUploadUrl'].includes(method ?? '')\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t\tif (!actionSide && isExternalCall(context, node)) flag(node)\n\t\t\t\t\tif (\n\t\t\t\t\t\tpure &&\n\t\t\t\t\t\tnode.callee.type === 'MemberExpression' &&\n\t\t\t\t\t\tnode.callee.object.type === 'Identifier' &&\n\t\t\t\t\t\t!binding(context, node.callee.object)?.defs.length &&\n\t\t\t\t\t\t((node.callee.object.name === 'Date' && method === 'now') ||\n\t\t\t\t\t\t\t(node.callee.object.name === 'Math' && method === 'random'))\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tProperty(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\trole === 'contracts' &&\n\t\t\t\t\t\t['handler', 'context', 'audit', 'prepare', 'middleware', 'guard'].includes(\n\t\t\t\t\t\t\tnode.key.type === 'Identifier'\n\t\t\t\t\t\t\t\t? node.key.name\n\t\t\t\t\t\t\t\t: String(node.key.type === 'Literal' ? node.key.value : ''),\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tMemberExpression(node) {\n\t\t\t\t\tif (pure && ['db', 'storage', 'scheduler', 'env'].includes(propertyName(node) ?? ''))\n\t\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\tNewExpression(node) {\n\t\t\t\t\tif (!(pure || read || declarative)) return\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.callee.type === 'Identifier' &&\n\t\t\t\t\t\t!binding(context, node.callee)?.defs.length &&\n\t\t\t\t\t\t['Error', 'TypeError', 'RangeError', 'Set', 'Map', 'RegExp'].includes(node.callee.name)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn\n\t\t\t\t\tflag(node)\n\t\t\t\t},\n\t\t\t\t'Program:exit'() {\n\t\t\t\t\tif (issue) context.report({ node: issue, messageId: 'ownership' })\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n} satisfies Record<string, CreateRule>\n\nexport type OwnershipRuleName = keyof typeof ownershipRules\n"],"mappings":"ikBA8BA,MAAaA,EAAiB,CAC7B,oBAAqB,CACpB,KAAMC,EAAS,qEAAsE,CACpF,UAAW,uBACZ,CAAC,EACD,OAAO,EAAS,CACf,IAAMC,EAAWC,EAAgB,MAAMC,EAAQ,QAAQ,IAAM,CAAC,CAAC,EACzDC,EAAOC,EAAQF,EAAQ,IAAKF,EAAS,SAAS,EAOpD,OALEK,EAAWH,EAAQ,QAAQ,EACzBI,EAAaJ,EAAQ,QAAQ,EAC7BE,EAAQF,EAAQ,QAAQ,KAAOK,EAAmBJ,CAAI,EAGnD,CACN,QAAQ,EAAM,CACb,IAAK,IAAMK,KAASC,EAAoB,CACvC,IAAKP,EAAQ,IACb,UAAWF,EAAS,SACrB,CAAC,EACAE,EAAQ,OAAO,CACd,OACA,UAAW,YACX,KAAM,CAAE,KAAMM,EAAM,KAAM,QAASA,EAAM,OAAQ,CAClD,CAAC,CACH,CACD,EAbQ,CAAC,CAcV,CACD,EACA,mBAAoB,CACnB,KAAMT,EAAS,6EAA8E,CAC5F,UACC,qGACF,CAAC,EACD,OAAO,EAAS,CACf,IAAMW,EAAOC,EAAQT,CAAO,EAC5B,GAAI,CAACQ,GAAQA,EAAK,SAAS,GAAG,EAAG,MAAO,CAAC,EACzC,IAAIF,EAA4B,KAC5BI,EAAS,0BACTC,EAAkB,GAChBC,EACL,iIAAiI,KAChIJ,CACD,EACD,SAASK,EAAK,EAAmB,CAChC,IAAUC,CACX,CACA,MAAO,CACN,QAAQ,EAAM,CAEZA,EAAK,KAAK,KACR,GACAC,EAAU,OAAS,uBAClBA,EAAU,OAAS,0BACnBA,EAAU,aAAa,OAAS,qBACnC,GAEAF,EAAKC,CAAI,CACX,EACA,cAAc,EAAM,CAElBE,EAAShB,EAASc,EAAK,MAAM,GAC7BA,EAAK,UAAU,KAAM,GAAaG,EAA2BjB,EAASkB,CAAQ,CAAC,IAE/E,EAAkB,GACpB,EACA,eAAe,EAAM,CAEnBF,EAAShB,EAASc,EAAK,MAAM,GAC7BA,EAAK,UAAU,KAAM,GAAaG,EAA2BjB,EAASkB,CAAQ,CAAC,IAE/E,EAAkB,KAElBC,EAAUL,CAAI,GACdM,EAAepB,EAASc,CAAI,GAC3BN,IAAS,aAAiBQ,EAAShB,EAASc,EAAK,MAAM,CAAC,EAAE,OAAS,iBAEpED,EAAKC,CAAI,CACX,EACA,wBAAwB,EAAM,EACzB,CAACA,EAAK,MAAQ,CAACO,EAAeP,EAAK,IAAI,IAAGD,EAAKC,CAAI,CACxD,EACA,mBAAmB,EAAM,EACpB,CAACA,EAAK,MAAQ,CAACO,EAAeP,EAAK,IAAI,IAAGD,EAAKC,CAAI,CACxD,EACA,YAAaD,EACb,gBAAiBA,EACjB,sBAAuBA,EACvB,aAAcA,EACd,eAAgBA,EAChB,eAAgBA,EAChB,eAAe,EAAM,CAChB,CAACD,GAAY,CAACD,IACjB,EAAQG,EACR,EAAS,gFAENR,GAAON,EAAQ,OAAO,CAAE,KAAMM,EAAO,UAAW,YAAa,KAAM,CAAE,QAAO,CAAE,CAAC,CACpF,CACD,CACD,CACD,EACA,4BAA6B,CAC5B,KAAMT,EAAS,2DAA4D,CAC1E,UACC,uJACF,CAAC,EACD,OAAO,EAAS,CACf,GAAI,CAACY,EAAQT,CAAO,CAAC,EAAE,WAAW,cAAc,EAAG,MAAO,CAAC,EAC3D,IAAMsB,kBAAS,IAAI,IACbC,EAAWC,EAAe,EAC5BlB,EAA4B,KAChC,SAASO,EAAK,EAAmB,CAChC,IAAUC,CACX,CACA,IAAMW,EAAUC,EAAe1B,GAAU,EAAM,IAAW,CACzD,GAAI2B,EAAeb,CAAI,EAAG,OAC1B,IAAMc,EAASC,EAAcN,EAAUvB,EAAQ,SAAU8B,CAAM,EACzDC,EAAOH,GAAUnB,EAAQT,EAAS4B,CAAM,EACxCI,EAAQD,GAAM,MAAM,gEAAgE,EACtFC,GAASA,EAAM,KAAO,UAAUV,EAAO,IAAIU,EAAM,EAAE,EACnDD,GAAM,WAAW,SAAS,GAAK,CAACC,GAAS,CAACD,EAAK,WAAW,gBAAgB,GAAGlB,EAAKC,CAAI,EAEzF,CAACiB,GACD,CAAC,CACA,UACA,gCACA,uBACA,eACD,CAAC,CAAC,SAASD,CAAM,GAEjBjB,EAAKC,CAAI,CACX,CAAC,EACD,MAAO,CACN,GAAGW,EACH,QAAQ,EAAM,CACb,IAAMQ,EAAcC,EAAcpB,CAAI,EACtC,IAAK,IAAMC,KAAaD,EAAK,KAAM,CAEjCC,EAAU,OAAS,uBACnBA,EAAU,IACV,CAACkB,EAAY,IAAIlB,EAAU,GAAG,IAAI,GAElCF,EAAKE,CAAS,EACf,IAAMoB,EACLpB,EAAU,OAAS,yBAA2BA,EAAU,YAAcA,EAMvE,IAJCoB,GAAa,OAAS,0BACtBA,GAAa,OAAS,2BAEtBtB,EAAKE,CAAS,EACXoB,GAAa,OAAS,sBACzB,IAAK,IAAMC,KAAQD,EAAY,aAE7BC,EAAK,MACL,CAAC,mBAAoB,kBAAmB,SAAS,CAAC,CAAC,SAASA,EAAK,KAAK,IAAI,GAE1EvB,EAAKuB,CAAI,EAETrB,EAAU,OAAS,uBACnBqB,EAAK,GAAG,OAAS,cACjB,CAACH,EAAY,IAAIG,EAAK,GAAG,IAAI,GAC7B,CAAC,0BAA2B,oBAAoB,CAAC,CAAC,SAASA,EAAK,MAAM,MAAQ,EAAE,GAEhFvB,EAAKuB,CAAI,CAEb,CACD,EACA,eAAe,EAAM,CACpBX,EAAQ,iBAAiBX,CAAI,GACzBuB,EAAWvB,CAAI,GAAKM,EAAepB,EAASc,CAAI,IAAGD,EAAKC,CAAI,EAChE,IAAMwB,EAAMtB,EAAShB,EAASc,EAAK,MAAM,EACrCwB,GAAO,CAAC,MAAO,QAAQ,CAAC,CAAC,SAASA,EAAI,MAAM,GAAGzB,EAAKC,CAAI,CAC7D,EACA,iBAAiB,EAAM,CACtB,IAAMiB,EAAOQ,EAAWzB,CAAI,EAC5B,GAAIiB,EAAK,QAAU,GAAKA,EAAK,KAAO,SAAU,CAC7C,IAAMO,EAAMtB,EAAShB,EAASwC,EAAW1B,CAAI,CAAC,EAC1CwB,GAAK,OAAS,YAAc,kBAAkB,KAAKA,EAAI,MAAM,GAAGhB,EAAO,IAAIS,EAAK,EAAE,CACvF,CACD,EACA,cAAelB,EACf,YAAaA,EACb,gBAAiBA,EACjB,sBAAuBA,EACvB,eAAe,EAAM,EAChBS,EAAO,KAAO,GAAKhB,IACtBN,EAAQ,OAAO,CAAE,KAAMM,GAASQ,EAAM,UAAW,WAAY,CAAC,CAChE,CACD,CACD,CACD,EACA,8BAA+B,CAC9B,KAAMjB,EAAS,6EAA8E,CAC5F,UACC,yHACF,CAAC,EACD,OAAO,EAAS,CACf,IAAMW,EAAOC,EAAQT,CAAO,GAAK,GAMjC,OAJCyC,EAAczC,EAASA,EAAQ,QAAQ,GACvC,8DAA8D,KAAKQ,CAAI,EAEhE,CAAC,EACF,CACN,eAAe,EAAM,CACpB,GAAIM,EAAK,OAAO,OAAS,iBAAkB,OAC3C,IAAMwB,EAAMtB,EAAShB,EAASc,EAAK,MAAM,EAExCwB,IACEI,EAAkB1C,EAASsC,EAAI,MAAM,GACtC,kCAAkC,KAAKA,EAAI,IAAI,GAC9C,wCAAwC,KAAKA,EAAI,MAAM,GACvD,8CAA8C,KAAKA,EAAI,IAAI,IAE7DtC,EAAQ,OAAO,CAAE,OAAM,UAAW,WAAY,CAAC,CACjD,CACD,CACD,CACD,EACA,+BAAgC,CAC/B,KAAMH,EACL,kFACA,CACC,UACC,iKACF,CACD,EACA,OAAO,EAAS,CACf,IAAMW,EAAOC,EAAQT,CAAO,GAAK,GAC3B2C,EAAWnC,IAAS,kBAC1B,GAAI,CAACmC,GAAY,CAAC,mBAAmB,KAAKnC,CAAI,EAAG,MAAO,CAAC,EACzD,IAAMoC,EAAOC,EAASrC,CAAI,CAAC,CAAC,QAAQ,gBAAiB,EAAE,EACjDsC,EAAOF,IAAS,QAChBG,EAAOH,IAAS,UAChBI,EAAc,CAAC,SAAU,QAAS,YAAa,WAAW,CAAC,CAAC,SAASJ,CAAI,EACzEK,EACL,sDAAsD,KAAKzC,CAAI,GAC/D,mBAAmB,KAAKA,CAAI,EACvBe,EAAWC,EAAe,EAC5BlB,EAA4B,KAChC,SAASO,EAAK,EAAmB,CAChC,IAAUC,CACX,CACA,IAAMW,EAAUC,EAAe1B,GAAU,EAAM,IAAW,CACzD,GAAI2B,EAAeb,CAAI,EAAG,OAC1B,IAAMc,EAASC,EAAcN,EAAUvB,EAAQ,SAAU8B,CAAM,EACzDC,EAAOH,GAAUnB,EAAQT,EAAS4B,CAAM,EAE7Ce,GACAb,IAAW,qBACX,CAAC,0CAA0C,KAAKC,GAAQ,EAAE,GAE1DlB,EAAKC,CAAI,EACNgC,GAAQf,GAAQ,CAAC,gDAAgD,KAAKA,CAAI,GAAGlB,EAAKC,CAAI,GAExFgC,GAAQC,GAAQC,IACjB,CAACjB,GACD,CAAC,CACA,MACA,SACA,gBACA,UACA,oBACA,iBACA,mBACD,CAAC,CAAC,SAASD,CAAM,GAEjBjB,EAAKC,CAAI,EAETiC,GACAhB,GACA,gEAAgE,KAAKA,CAAI,GAEzElB,EAAKC,CAAI,CACX,CAAC,EACD,MAAO,CACN,GAAGW,EACH,QAAQ,EAAM,CACb,GAAKkB,EACL,IAAK,IAAM5B,KAAaD,EAAK,KAAM,CAClC,GAAIC,EAAU,OAAS,qBAAuBA,EAAU,OAAS,iBAChE,SACD,IAAMoB,EACLpB,EAAU,OAAS,yBAA2BA,EAAU,YAAcA,GAEtEoB,GAAa,OAAS,uBACtBA,EAAY,aAAa,KAAM,GAASC,EAAK,MAAM,OAAS,gBAAgB,IAE5EvB,EAAKE,CAAS,CAChB,CACD,EACA,eAAe,EAAM,CAEpB,GADAU,EAAQ,iBAAiBX,CAAI,EACzB6B,EAAU,CACb,IAAML,EAAMtB,EAAShB,EAASc,EAAK,MAAM,GACrCwB,GAAK,SAAW,qBAAuBA,EAAI,OAAS,iBAAgBzB,EAAKC,CAAI,CAClF,CACA,IAAMoC,EAASpC,EAAK,OAAO,OAAS,mBAAqBqC,EAAarC,EAAK,MAAM,EAAI,MAEnFgC,GAAQE,KACRX,EAAWvB,CAAI,GACf,CAAC,WAAY,cAAe,YAAa,WAAY,OAAO,CAAC,CAAC,SAASoC,GAAU,EAAE,IAEpFrC,EAAKC,CAAI,EAETiC,IACC5B,EAAUL,CAAI,GACd,CAAC,cAAe,YAAa,WAAY,OAAO,CAAC,CAAC,SAASoC,GAAU,EAAE,IAExErC,EAAKC,CAAI,EACV,IAAMsC,EAAcpC,EAAShB,EAASc,EAAK,MAAM,EAEhDsC,GACAV,EAAkB1C,EAASoD,EAAY,MAAM,IAC5CN,GAAQE,GAAgBD,GAAQ,uBAAuB,KAAKK,EAAY,IAAI,IAE7EvC,EAAKC,CAAI,EAETiC,GACAjC,EAAK,OAAO,OAAS,oBACrBqC,EAAarC,EAAK,OAAO,MAAM,IAAM,WACrC,CAAC,QAAS,SAAU,mBAAmB,CAAC,CAAC,SAASoC,GAAU,EAAE,GAE9DrC,EAAKC,CAAI,EACN,CAACmC,GAAc7B,EAAepB,EAASc,CAAI,GAAGD,EAAKC,CAAI,EAE1DgC,GACAhC,EAAK,OAAO,OAAS,oBACrBA,EAAK,OAAO,OAAO,OAAS,cAC5B,CAACuC,EAAQrD,EAASc,EAAK,OAAO,MAAM,CAAC,EAAE,KAAK,SAC1CA,EAAK,OAAO,OAAO,OAAS,QAAUoC,IAAW,OACjDpC,EAAK,OAAO,OAAO,OAAS,QAAUoC,IAAW,WAEnDrC,EAAKC,CAAI,CACX,EACA,SAAS,EAAM,CAEb8B,IAAS,aACT,CAAC,UAAW,UAAW,QAAS,UAAW,aAAc,OAAO,CAAC,CAAC,SACjE9B,EAAK,IAAI,OAAS,aACfA,EAAK,IAAI,KACT,OAAOA,EAAK,IAAI,OAAS,UAAYA,EAAK,IAAI,MAAQ,EAAE,CAC5D,GAEAD,EAAKC,CAAI,CACX,EACA,iBAAiB,EAAM,CAClBgC,GAAQ,CAAC,KAAM,UAAW,YAAa,KAAK,CAAC,CAAC,SAASK,EAAarC,CAAI,GAAK,EAAE,GAClFD,EAAKC,CAAI,CACX,EACA,cAAc,EAAM,EACbgC,GAAQC,GAAQC,KAErBlC,EAAK,OAAO,OAAS,cACpBuC,EAAQrD,EAASc,EAAK,MAAM,CAAC,EAAE,KAAK,QACrC,EAAC,QAAS,YAAa,aAAc,MAAO,MAAO,QAAQ,CAAC,CAAC,SAASA,EAAK,OAAO,IAAI,IAGvFD,EAAKC,CAAI,CACV,EACA,gBAAiB,CACZR,GAAON,EAAQ,OAAO,CAAE,KAAMM,EAAO,UAAW,WAAY,CAAC,CAClE,CACD,CACD,CACD,CACD"}
@@ -0,0 +1,6 @@
1
+ import { CreateRule } from "@oxlint/plugins";
2
+ //#region src/oxlint/reserved-files.d.ts
3
+ /** Reserved files prove their exported declaration's provenance, not an unused import. */
4
+ export declare const reservedDomainFiles: CreateRule;
5
+ //#endregion
6
+ //# sourceMappingURL=reserved-files.d.mts.map
@@ -0,0 +1,2 @@
1
+ import{createResolver as e,resolveImport as t}from"./architecture.mjs";import{appFile as n,exportName as r,metadata as i,propertyName as a}from"./ast.mjs";import{readFileSync as o}from"node:fs";import{parseSync as s}from"oxc-parser";const c={meta:i(`Require kit-backed declarations in reserved domain files.`,{anatomy:`{{file}} must export {{expected}} built with cvx-kit; imports or local lookalikes do not count.`}),create(e){let t=n(e)??``,r=t.match(/^domain\/(?:.+\/)?(commands|queries|contracts|schema|table)\.ts$/);if(!r)return{};let i=r[1];return{Program(n){let r=u(e,n,e.filename),a=l(n).map(e=>r(e)),o=i===`commands`?`one Command registry`:i===`queries`?`one Query registry`:i===`schema`?`zodTable shapes`:i===`contracts`?`declarative contracts`:t===`domain/table.ts`?`createModule assembly`:`a table topology map`,s=i===`commands`?`registry:Command`:i===`queries`?`registry:Query`:i===`schema`?`shape`:i===`contracts`?`contract`:t===`domain/table.ts`?`assembly`:`topology`,c=a.filter(e=>e===s).length;(i===`commands`||i===`queries`?c===1:c>0)||e.report({node:n,messageId:`anatomy`,data:{file:t,expected:o}})}}}};function l(e){let t=[],n=/* @__PURE__ */ new Map;for(let r of e.body){let e=r.type===`ExportNamedDeclaration`?r.declaration:r;if(e?.type===`VariableDeclaration`&&e.kind===`const`)for(let i of e.declarations)i.id.type===`Identifier`&&i.init&&(n.set(i.id.name,i.init),r.type===`ExportNamedDeclaration`&&t.push(i.init))}for(let i of e.body){if(i.type===`ExportNamedDeclaration`&&i.exportKind!==`type`&&!i.source)for(let e of i.specifiers){if(e.exportKind===`type`)continue;let i=n.get(r(e.local)??``);i&&t.push(i)}i.type===`ExportDefaultDeclaration`&&i.declaration.type!==`FunctionDeclaration`&&i.declaration.type!==`ClassDeclaration`&&i.declaration.type!==`TSInterfaceDeclaration`&&t.push(i.declaration)}return t}function u(i,c,l,d=/* @__PURE__ */ new Set){let f=/* @__PURE__ */ new Map,p=/* @__PURE__ */ new Map,m=e();for(let e of c.body){if(e.type===`ImportDeclaration`&&e.importKind!==`type`)for(let t of e.specifiers)(t.type!==`ImportSpecifier`||t.importKind!==`type`)&&f.set(t.local.name,{source:e.source.value,name:t.type===`ImportSpecifier`?r(t.imported)??``:t.type===`ImportNamespaceSpecifier`?`*`:`default`});let t=e.type===`ExportNamedDeclaration`?e.declaration:e;if(t?.type===`VariableDeclaration`&&t.kind===`const`){for(let e of t.declarations)if(e.init&&(e.id.type===`Identifier`&&p.set(e.id.name,{expression:e.init}),e.id.type===`ObjectPattern`))for(let t of e.id.properties)t.type===`Property`&&t.value.type===`Identifier`&&p.set(t.value.name,{expression:e.init,member:r(t.key)??``})}}function h(e,a){if([`cvx-kit`,`cvx-kit/effect`,`cvx-kit/components/foundation`,`cvx-kit/contracts`,`cvx-kit/zod-table`,`cvx-kit/errors`].includes(e))return a===`*`?`namespace:${e}`:e===`cvx-kit/effect`&&a===`createEffectFoundation`||e===`cvx-kit`&&a===`createFoundation`||[`cvx-kit`,`cvx-kit/components/foundation`].includes(e)&&a===`Foundation`?`foundationFactory`:[`cvx-kit`,`cvx-kit/zod-table`].includes(e)&&[`zodTable`,`zodVariantTable`].includes(a)?`shapeFactory`:[`cvx-kit`,`cvx-kit/zod-table`].includes(e)&&a===`createModule`?`assemblyFactory`:e===`cvx-kit/contracts`&&[`defineDomainContract`,`operationContract`].includes(a)||e===`cvx-kit/errors`&&a===`defineErrorContract`?`contractFactory`:null;if([`zod`,`zod/v4`,`convex/values`].includes(e))return`validator`;let c=t(m,l,e),f=c&&n(i,c);if(!c||!f||!/^(?:foundation\.ts|domain\/.+\/(?:schema|contracts)\.ts)$/.test(f)||d.has(c)||d.size>=6)return null;if(a===`*`)return`namespace:${e}`;let p=s(c,o(c,`utf8`));if(p.errors.length)return null;let h=p.program,g=u(i,h,c,new Set(d).add(c));for(let e of h.body)if(e.type===`ExportNamedDeclaration`&&e.exportKind!==`type`){if(e.declaration?.type===`VariableDeclaration`)for(let t of e.declaration.declarations){if(t.id.type===`Identifier`&&t.id.name===a)return g(t.id);if(t.id.type===`ObjectPattern`){for(let e of t.id.properties)if(e.type===`Property`&&e.value.type===`Identifier`&&e.value.name===a)return g(e.value)}}for(let t of e.specifiers)if(t.exportKind!==`type`&&r(t.exported)===a&&!e.source)return g(t.local)}return null}function g(e,t){return e===`foundation`&&[`Command`,`Query`].includes(t)?t:e?.startsWith(`namespace:`)?h(e.slice(10),t):e===`validator`||e===`contract`?`validator`:e===`shape`&&t===`table`?`table`:e===`table`&&[`index`,`searchIndex`,`vectorIndex`].includes(t)?`indexFactory`:null}function _(e,t=/* @__PURE__ */ new Set){if(e.type===`TSAsExpression`||e.type===`TSSatisfiesExpression`||e.type===`TSNonNullExpression`)return _(e.expression,t);if(e.type===`Identifier`){if(t.has(e.name))return null;let n=f.get(e.name);if(n)return h(n.source,n.name);let r=p.get(e.name);if(!r)return null;let i=_(r.expression,new Set(t).add(e.name));return r.member?g(i,r.member):i}if(e.type===`MemberExpression`)return g(_(e.object,t),a(e)??``);if(e.type===`CallExpression`||e.type===`NewExpression`){let n=_(e.callee,t);return n===`foundationFactory`?`foundation`:n===`Command`||n===`Query`?`registry:${n}`:n===`shapeFactory`?`shape`:n===`assemblyFactory`?`assembly`:n===`contractFactory`||n===`validator`?`contract`:n===`indexFactory`?`table`:null}if(e.type===`ObjectExpression`){let n=e.properties.map(e=>e.type===`Property`?_(e.value,t):null);if(n.length&&n.every(e=>e===`table`||e===`topology`))return`topology`;if(n.some(e=>e===`contract`||e===`validator`)&&n.every(e=>e===`contract`||e===`validator`||e===`data`))return`contract`;if(n.every(e=>e===`data`))return`data`}return e.type===`Literal`?`data`:null}return _}export{c as reservedDomainFiles};
2
+ //# sourceMappingURL=reserved-files.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reserved-files.mjs","names":["reservedDomainFiles","metadata","file","appFile","context","match","role","evaluate","provenance","program","values","publicExpressions","expression","expected","wanted","count","value","expressions","declarations","statement","declaration","item","specifier","exportName","imports","variables","resolver","createResolver","property","imported","source","name","target","resolveImport","filename","visited","parsed","parseSync","readFileSync","remote","evaluateRemote","member","owner","node","active","reference","variable","propertyName","callee"],"sources":["../../src/oxlint/reserved-files.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport type { Context, CreateRule, ESTree } from '@oxlint/plugins'\nimport { parseSync } from 'oxc-parser'\nimport { appFile, metadata, propertyName, exportName } from './ast'\nimport { createResolver, resolveImport } from './architecture'\n\n/** Reserved files prove their exported declaration's provenance, not an unused import. */\nexport const reservedDomainFiles: CreateRule = {\n\tmeta: metadata('Require kit-backed declarations in reserved domain files.', {\n\t\tanatomy:\n\t\t\t'{{file}} must export {{expected}} built with cvx-kit; imports or local lookalikes do not count.',\n\t}),\n\tcreate(context) {\n\t\tconst file = appFile(context) ?? ''\n\t\tconst match = file.match(/^domain\\/(?:.+\\/)?(commands|queries|contracts|schema|table)\\.ts$/)\n\t\tif (!match) return {}\n\t\tconst role = match[1]\n\t\treturn {\n\t\t\tProgram(program) {\n\t\t\t\tconst evaluate = provenance(context, program, context.filename)\n\t\t\t\tconst exports = publicExpressions(program)\n\t\t\t\tconst values = exports.map((expression) => evaluate(expression))\n\t\t\t\tconst expected =\n\t\t\t\t\trole === 'commands'\n\t\t\t\t\t\t? 'one Command registry'\n\t\t\t\t\t\t: role === 'queries'\n\t\t\t\t\t\t\t? 'one Query registry'\n\t\t\t\t\t\t\t: role === 'schema'\n\t\t\t\t\t\t\t\t? 'zodTable shapes'\n\t\t\t\t\t\t\t\t: role === 'contracts'\n\t\t\t\t\t\t\t\t\t? 'declarative contracts'\n\t\t\t\t\t\t\t\t\t: file === 'domain/table.ts'\n\t\t\t\t\t\t\t\t\t\t? 'createModule assembly'\n\t\t\t\t\t\t\t\t\t\t: 'a table topology map'\n\t\t\t\tconst wanted =\n\t\t\t\t\trole === 'commands'\n\t\t\t\t\t\t? 'registry:Command'\n\t\t\t\t\t\t: role === 'queries'\n\t\t\t\t\t\t\t? 'registry:Query'\n\t\t\t\t\t\t\t: role === 'schema'\n\t\t\t\t\t\t\t\t? 'shape'\n\t\t\t\t\t\t\t\t: role === 'contracts'\n\t\t\t\t\t\t\t\t\t? 'contract'\n\t\t\t\t\t\t\t\t\t: file === 'domain/table.ts'\n\t\t\t\t\t\t\t\t\t\t? 'assembly'\n\t\t\t\t\t\t\t\t\t\t: 'topology'\n\t\t\t\tconst count = values.filter((value) => value === wanted).length\n\t\t\t\tconst valid = role === 'commands' || role === 'queries' ? count === 1 : count > 0\n\t\t\t\tif (!valid)\n\t\t\t\t\tcontext.report({ node: program, messageId: 'anatomy', data: { file, expected } })\n\t\t\t},\n\t\t}\n\t},\n}\n\nfunction publicExpressions(program: ESTree.Program): ESTree.Expression[] {\n\tconst expressions: ESTree.Expression[] = []\n\tconst declarations = new Map<string, ESTree.Expression>()\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 === 'VariableDeclaration' && declaration.kind === 'const')\n\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\tif (item.id.type === 'Identifier' && item.init) {\n\t\t\t\t\tdeclarations.set(item.id.name, item.init)\n\t\t\t\t\tif (statement.type === 'ExportNamedDeclaration') expressions.push(item.init)\n\t\t\t\t}\n\t\t\t}\n\t}\n\tfor (const statement of program.body) {\n\t\tif (\n\t\t\tstatement.type === 'ExportNamedDeclaration' &&\n\t\t\tstatement.exportKind !== 'type' &&\n\t\t\t!statement.source\n\t\t)\n\t\t\tfor (const specifier of statement.specifiers) {\n\t\t\t\tif (specifier.exportKind === 'type') continue\n\t\t\t\tconst expression = declarations.get(exportName(specifier.local) ?? '')\n\t\t\t\tif (expression) expressions.push(expression)\n\t\t\t}\n\t\tif (\n\t\t\tstatement.type === 'ExportDefaultDeclaration' &&\n\t\t\tstatement.declaration.type !== 'FunctionDeclaration' &&\n\t\t\tstatement.declaration.type !== 'ClassDeclaration' &&\n\t\t\tstatement.declaration.type !== 'TSInterfaceDeclaration'\n\t\t) {\n\t\t\texpressions.push(statement.declaration)\n\t\t}\n\t}\n\treturn expressions\n}\n\nfunction provenance(\n\tcontext: Context,\n\tprogram: ESTree.Program,\n\tfilename: string,\n\tvisited = new Set<string>(),\n) {\n\tconst imports = new Map<string, { source: string; name: string }>()\n\tconst variables = new Map<string, { expression: ESTree.Expression; member?: string }>()\n\tconst resolver = createResolver()\n\tfor (const statement of 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') continue\n\t\t\t\timports.set(specifier.local.name, {\n\t\t\t\t\tsource: statement.source.value,\n\t\t\t\t\tname:\n\t\t\t\t\t\tspecifier.type === 'ImportSpecifier'\n\t\t\t\t\t\t\t? (exportName(specifier.imported) ?? '')\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: 'default',\n\t\t\t\t})\n\t\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 === 'Identifier') variables.set(item.id.name, { expression: item.init })\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')\n\t\t\t\t\t\t\tvariables.set(property.value.name, {\n\t\t\t\t\t\t\t\texpression: item.init,\n\t\t\t\t\t\t\t\tmember: exportName(property.key) ?? '',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t}\n\t}\n\tfunction imported(source: string, name: string): string | null {\n\t\tif (\n\t\t\t[\n\t\t\t\t'cvx-kit',\n\t\t\t\t'cvx-kit/effect',\n\t\t\t\t'cvx-kit/components/foundation',\n\t\t\t\t'cvx-kit/contracts',\n\t\t\t\t'cvx-kit/zod-table',\n\t\t\t\t'cvx-kit/errors',\n\t\t\t].includes(source)\n\t\t) {\n\t\t\tif (name === '*') return `namespace:${source}`\n\t\t\tif (\n\t\t\t\t(source === 'cvx-kit/effect' && name === 'createEffectFoundation') ||\n\t\t\t\t(source === 'cvx-kit' && name === 'createFoundation') ||\n\t\t\t\t(['cvx-kit', 'cvx-kit/components/foundation'].includes(source) && name === 'Foundation')\n\t\t\t)\n\t\t\t\treturn 'foundationFactory'\n\t\t\tif (\n\t\t\t\t['cvx-kit', 'cvx-kit/zod-table'].includes(source) &&\n\t\t\t\t['zodTable', 'zodVariantTable'].includes(name)\n\t\t\t)\n\t\t\t\treturn 'shapeFactory'\n\t\t\tif (['cvx-kit', 'cvx-kit/zod-table'].includes(source) && name === 'createModule')\n\t\t\t\treturn 'assemblyFactory'\n\t\t\tif (\n\t\t\t\tsource === 'cvx-kit/contracts' &&\n\t\t\t\t['defineDomainContract', 'operationContract'].includes(name)\n\t\t\t)\n\t\t\t\treturn 'contractFactory'\n\t\t\tif (source === 'cvx-kit/errors' && name === 'defineErrorContract') return 'contractFactory'\n\t\t\treturn null\n\t\t}\n\t\tif (['zod', 'zod/v4', 'convex/values'].includes(source)) return 'validator'\n\t\tconst target = resolveImport(resolver, filename, source)\n\t\tconst file = target && appFile(context, target)\n\t\tif (\n\t\t\t!target ||\n\t\t\t!file ||\n\t\t\t!/^(?:foundation\\.ts|domain\\/.+\\/(?:schema|contracts)\\.ts)$/.test(file) ||\n\t\t\tvisited.has(target) ||\n\t\t\tvisited.size >= 6\n\t\t)\n\t\t\treturn null\n\t\tif (name === '*') return `namespace:${source}`\n\t\tconst parsed = parseSync(target, readFileSync(target, 'utf8'))\n\t\tif (parsed.errors.length) return null\n\t\t// SAFETY: oxc-parser and the rule API share these declaration fields; provenance never reads rule-API loc/tokens.\n\t\t// oxlint-disable-next-line anti-slop/no-chained-type-assertions\n\t\tconst remote = parsed.program as unknown as ESTree.Program\n\t\tconst nextVisited = new Set(visited).add(target)\n\t\tconst evaluateRemote = provenance(context, remote, target, nextVisited)\n\t\tfor (const statement of remote.body) {\n\t\t\tif (statement.type !== 'ExportNamedDeclaration' || statement.exportKind === 'type') continue\n\t\t\tif (statement.declaration?.type === 'VariableDeclaration')\n\t\t\t\tfor (const item of statement.declaration.declarations) {\n\t\t\t\t\tif (item.id.type === 'Identifier' && item.id.name === name) return evaluateRemote(item.id)\n\t\t\t\t\tif (item.id.type === 'ObjectPattern')\n\t\t\t\t\t\tfor (const property of item.id.properties)\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tproperty.type === 'Property' &&\n\t\t\t\t\t\t\t\tproperty.value.type === 'Identifier' &&\n\t\t\t\t\t\t\t\tproperty.value.name === name\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn evaluateRemote(property.value)\n\t\t\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\texportName(specifier.exported) === name &&\n\t\t\t\t\t!statement.source\n\t\t\t\t)\n\t\t\t\t\treturn evaluateRemote(specifier.local)\n\t\t}\n\t\treturn null\n\t}\n\tfunction member(owner: string | null, name: string): string | null {\n\t\tif (owner === 'foundation' && ['Command', 'Query'].includes(name)) return name\n\t\tif (owner?.startsWith('namespace:')) return imported(owner.slice(10), name)\n\t\tif (owner === 'validator' || owner === 'contract') return 'validator'\n\t\tif (owner === 'shape' && name === 'table') return 'table'\n\t\tif (owner === 'table' && ['index', 'searchIndex', 'vectorIndex'].includes(name))\n\t\t\treturn 'indexFactory'\n\t\treturn null\n\t}\n\tfunction evaluate(node: ESTree.Node, active = new Set<string>()): string | null {\n\t\tif (\n\t\t\tnode.type === 'TSAsExpression' ||\n\t\t\tnode.type === 'TSSatisfiesExpression' ||\n\t\t\tnode.type === 'TSNonNullExpression'\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)) return null\n\t\t\tconst reference = imports.get(node.name)\n\t\t\tif (reference) return imported(reference.source, reference.name)\n\t\t\tconst variable = variables.get(node.name)\n\t\t\tif (!variable) return null\n\t\t\tconst value = evaluate(variable.expression, new Set(active).add(node.name))\n\t\t\treturn variable.member ? member(value, variable.member) : value\n\t\t}\n\t\tif (node.type === 'MemberExpression')\n\t\t\treturn member(evaluate(node.object, active), propertyName(node) ?? '')\n\t\tif (node.type === 'CallExpression' || node.type === 'NewExpression') {\n\t\t\tconst callee = evaluate(node.callee, active)\n\t\t\tif (callee === 'foundationFactory') return 'foundation'\n\t\t\tif (callee === 'Command' || callee === 'Query') return `registry:${callee}`\n\t\t\tif (callee === 'shapeFactory') return 'shape'\n\t\t\tif (callee === 'assemblyFactory') return 'assembly'\n\t\t\tif (callee === 'contractFactory' || callee === 'validator') return 'contract'\n\t\t\tif (callee === 'indexFactory') return 'table'\n\t\t\treturn null\n\t\t}\n\t\tif (node.type === 'ObjectExpression') {\n\t\t\tconst values = node.properties.map((property) =>\n\t\t\t\tproperty.type === 'Property' ? evaluate(property.value, active) : null,\n\t\t\t)\n\t\t\tif (values.length && values.every((value) => value === 'table' || value === 'topology'))\n\t\t\t\treturn 'topology'\n\t\t\tif (\n\t\t\t\tvalues.some((value) => value === 'contract' || value === 'validator') &&\n\t\t\t\tvalues.every((value) => value === 'contract' || value === 'validator' || value === 'data')\n\t\t\t)\n\t\t\t\treturn 'contract'\n\t\t\tif (values.every((value) => value === 'data')) return 'data'\n\t\t}\n\t\tif (node.type === 'Literal') return 'data'\n\t\treturn null\n\t}\n\treturn evaluate\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' | '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';
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{ownershipRules as _}from"./oxlint/ownership.mjs";import{basename as v,dirname as y,relative as b,sep as x}from"node:path";function S(e={}){return t(e)}const C=T({..._,"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`),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(x).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]:v(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(x).includes(`node_modules`)&&(i&&(b(i,c).startsWith(`..${x}`)||c===y(i))?t.report({node:e,messageId:`boundary`}):!i&&a(t,c)&&!/^client(?:\.[cm]?[jt]s)?$/.test(v(c))&&!(r(t)===`convex.config.ts`&&/^convex\.config(?:\.[cm]?[jt]s)?$/.test(v(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)&&v(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(v(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`})}}}}}),w={meta:{name:`cvx`},rules:C};function T(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{S as checkArchitecture,w as default,C as rules};
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};
2
2
  //# sourceMappingURL=oxlint.mjs.map