cvx-kit 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +21 -3
- package/dist/agent-tools.d.mts +2 -1
- package/dist/agent-tools.mjs +1 -1
- package/dist/agent-tools.mjs.map +1 -1
- package/dist/components/approvals/audit.mjs +1 -1
- package/dist/components/foundation/client.d.mts +8 -7
- package/dist/components/foundation/client.mjs +1 -1
- package/dist/components/foundation/client.mjs.map +1 -1
- package/dist/components/foundation/modules/command/command.d.mts +50 -10
- package/dist/components/foundation/modules/command/command.mjs +1 -1
- package/dist/components/foundation/modules/command/command.mjs.map +1 -1
- package/dist/components/foundation/modules/command/lifecycle.d.mts +81 -0
- package/dist/components/foundation/modules/command/lifecycle.mjs +2 -0
- package/dist/components/foundation/modules/command/lifecycle.mjs.map +1 -0
- package/dist/components/foundation/modules/observability/observability.d.mts +8 -0
- package/dist/components/foundation/modules/observability/observability.mjs +1 -1
- package/dist/components/foundation/modules/observability/observability.mjs.map +1 -1
- package/dist/components/foundation/operation.d.mts +6 -6
- package/dist/components/foundation/operation.mjs.map +1 -1
- package/dist/contracts.d.mts +4 -0
- package/dist/contracts.mjs +1 -0
- package/dist/crud.d.mts +2 -2
- package/dist/crud.mjs.map +1 -1
- package/dist/effect.d.mts +12 -0
- package/dist/effect.mjs +1 -0
- package/dist/errors.d.mts +2 -1
- package/dist/errors.mjs +1 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/idempotency.d.mts +2 -0
- package/dist/idempotency.mjs +1 -0
- package/dist/modules/contracts/contract.d.mts +70 -0
- package/dist/modules/contracts/contract.mjs +2 -0
- package/dist/modules/contracts/contract.mjs.map +1 -0
- package/dist/modules/contracts/convex.d.mts +22 -0
- package/dist/modules/contracts/convex.mjs +2 -0
- package/dist/modules/contracts/convex.mjs.map +1 -0
- package/dist/modules/contracts/errors.d.mts +44 -0
- package/dist/modules/contracts/errors.mjs +2 -0
- package/dist/modules/contracts/errors.mjs.map +1 -0
- package/dist/modules/contracts/exposure.d.mts +105 -0
- package/dist/modules/contracts/exposure.mjs +2 -0
- package/dist/modules/contracts/exposure.mjs.map +1 -0
- package/dist/modules/contracts/idempotency.d.mts +87 -0
- package/dist/modules/contracts/idempotency.mjs +2 -0
- package/dist/modules/contracts/idempotency.mjs.map +1 -0
- package/dist/modules/contracts/standard.d.mts +16 -0
- package/dist/modules/contracts/standard.mjs +2 -0
- package/dist/modules/contracts/standard.mjs.map +1 -0
- package/dist/modules/contracts/workflow.d.mts +167 -0
- package/dist/modules/contracts/workflow.mjs +2 -0
- package/dist/modules/contracts/workflow.mjs.map +1 -0
- package/dist/modules/effect/agent-tools.d.mts +2 -0
- package/dist/modules/effect/agent-tools.mjs +1 -0
- package/dist/modules/effect/api-runtime.d.mts +28 -0
- package/dist/modules/effect/api-runtime.mjs +2 -0
- package/dist/modules/effect/api-runtime.mjs.map +1 -0
- package/dist/modules/effect/api-zod.d.mts +35 -0
- package/dist/modules/effect/api-zod.mjs +2 -0
- package/dist/modules/effect/api-zod.mjs.map +1 -0
- package/dist/modules/effect/api.d.mts +21 -0
- package/dist/modules/effect/api.mjs +2 -0
- package/dist/modules/effect/api.mjs.map +1 -0
- package/dist/modules/effect/client.d.mts +11 -0
- package/dist/modules/effect/client.mjs +1 -0
- package/dist/modules/effect/command.d.mts +59 -0
- package/dist/modules/effect/command.mjs +2 -0
- package/dist/modules/effect/command.mjs.map +1 -0
- package/dist/modules/effect/crud.d.mts +785 -0
- package/dist/modules/effect/crud.mjs +2 -0
- package/dist/modules/effect/crud.mjs.map +1 -0
- package/dist/modules/effect/errors.d.mts +8 -0
- package/dist/modules/effect/errors.mjs +2 -0
- package/dist/modules/effect/errors.mjs.map +1 -0
- package/dist/modules/effect/foundation.d.mts +21 -0
- package/dist/modules/effect/foundation.mjs +2 -0
- package/dist/modules/effect/foundation.mjs.map +1 -0
- package/dist/modules/effect/idempotency.d.mts +31 -0
- package/dist/modules/effect/idempotency.mjs +2 -0
- package/dist/modules/effect/idempotency.mjs.map +1 -0
- package/dist/modules/effect/normalize.d.mts +10 -0
- package/dist/modules/effect/normalize.mjs +2 -0
- package/dist/modules/effect/normalize.mjs.map +1 -0
- package/dist/modules/effect/operation.d.mts +141 -0
- package/dist/modules/effect/operation.mjs +2 -0
- package/dist/modules/effect/operation.mjs.map +1 -0
- package/dist/modules/effect/query.d.mts +65 -0
- package/dist/modules/effect/query.mjs +2 -0
- package/dist/modules/effect/query.mjs.map +1 -0
- package/dist/modules/effect/schema.d.mts +33 -0
- package/dist/modules/effect/schema.mjs +2 -0
- package/dist/modules/effect/schema.mjs.map +1 -0
- package/dist/modules/effect/workflow.d.mts +77 -0
- package/dist/modules/effect/workflow.mjs +2 -0
- package/dist/modules/effect/workflow.mjs.map +1 -0
- package/dist/node_modules/@standard-schema/spec/dist/index.d.mts +79 -0
- package/dist/oxlint/architecture.d.mts +20 -0
- package/dist/oxlint/architecture.mjs +2 -0
- package/dist/oxlint/architecture.mjs.map +1 -0
- package/dist/oxlint/ast.d.mts +33 -0
- package/dist/oxlint/ast.mjs +2 -0
- package/dist/oxlint/ast.mjs.map +1 -0
- package/dist/oxlint/ownership.d.mts +62 -0
- package/dist/oxlint/ownership.mjs +2 -0
- package/dist/oxlint/ownership.mjs.map +1 -0
- package/dist/oxlint.d.mts +5 -2
- package/dist/oxlint.mjs +1 -1
- package/dist/oxlint.mjs.map +1 -1
- package/dist/workflow.d.mts +2 -0
- package/dist/workflow.mjs +1 -0
- package/docs/auth.md +65 -0
- package/docs/commands.md +118 -0
- package/docs/conventions.md +49 -21
- package/docs/domain-operations.md +615 -0
- package/docs/effect.md +384 -0
- package/docs/oxlint.md +74 -26
- package/docs/upgrading.md +13 -0
- package/package.json +37 -3
- package/scripts/convex-smoke-env.mjs +33 -0
- package/scripts/smoke-packed-components.mjs +9 -2
- package/scripts/smoke-packed-effect.mjs +439 -0
- package/scripts/test-packed-effect.mjs +457 -0
- package/scripts/test-packed-ids.mjs +1 -0
- package/scripts/test-packed-oxlint.mjs +24 -2
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ContractInput, ContractOutput, ContractSchema } from "../contracts/contract.mjs";
|
|
2
|
+
import { ContractDecoderError, ContractDecoderRequirements } from "./schema.mjs";
|
|
3
|
+
import { CallbackError, CallbackRequirements, EffectValue } from "./operation.mjs";
|
|
4
|
+
import { IdempotencyInvocation } from "../contracts/idempotency.mjs";
|
|
5
|
+
import { EffectIdempotencyPreparation } from "./idempotency.mjs";
|
|
6
|
+
import { WorkflowBindingError, WorkflowExecution, WorkflowHostState, WorkflowNativeStatus, WorkflowOutcome, WorkflowTransition } from "../contracts/workflow.mjs";
|
|
7
|
+
import { Effect } from "effect";
|
|
8
|
+
//#region src/modules/effect/workflow.d.ts
|
|
9
|
+
type Supported<A> = A | PromiseLike<A> | Effect.Effect<A, unknown, unknown>;
|
|
10
|
+
/** Services exist only inside a new native invocation; ordinary throws/rejections remain defects. */
|
|
11
|
+
declare function effectWorkflowAttempt<Args, Authorize, Execute>(configuration: {
|
|
12
|
+
authorize: (execution: WorkflowExecution<Args>) => Authorize;
|
|
13
|
+
execute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute;
|
|
14
|
+
}): (input: WorkflowExecution<Args>) => Effect.Effect<EffectValue<Execute>, WorkflowBindingError | CallbackError<Authorize | Execute>, CallbackRequirements<Authorize | Execute>>;
|
|
15
|
+
/** Native mutation promise rejects outside the child transaction before mapping declared terminal details. */
|
|
16
|
+
declare function effectTerminalWorkflowAttempt<Args, Authorize, const Result extends ContractSchema, const Failure extends ContractSchema, Terminal extends Supported<ContractInput<Failure> | undefined>>(configuration: ({
|
|
17
|
+
kind: 'mutation';
|
|
18
|
+
atomicJournalProof: 'host-verified';
|
|
19
|
+
} | {
|
|
20
|
+
kind: 'action';
|
|
21
|
+
protectedMutation: EffectReceiptProtectedWorkflowMutation<Args, unknown, unknown, unknown>;
|
|
22
|
+
}) & {
|
|
23
|
+
authorize: (execution: WorkflowExecution<Args>) => Authorize;
|
|
24
|
+
invokeMutation: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Promise<ContractInput<Result>>;
|
|
25
|
+
terminal: (error: unknown) => Terminal;
|
|
26
|
+
result: Result;
|
|
27
|
+
failure: Failure;
|
|
28
|
+
}): (input: WorkflowExecution<Args>) => Effect.Effect<WorkflowOutcome<ContractInput<Result>, ContractOutput<Failure>>, WorkflowBindingError | CallbackError<Authorize | Terminal> | ContractDecoderError<Result | Failure>, CallbackRequirements<Authorize | Terminal> | ContractDecoderRequirements<Result | Failure>>;
|
|
29
|
+
declare const protectedMutation: unique symbol;
|
|
30
|
+
interface EffectReceiptProtectedWorkflowMutation<Args, Result, Error, Requirements> {
|
|
31
|
+
readonly [protectedMutation]: {
|
|
32
|
+
args: Args;
|
|
33
|
+
result: Result;
|
|
34
|
+
};
|
|
35
|
+
readonly handler: (execution: WorkflowExecution<Args>) => Effect.Effect<Result, Error, Requirements>;
|
|
36
|
+
}
|
|
37
|
+
type Completion<Prepare> = Extract<EffectValue<Prepare>, {
|
|
38
|
+
kind: 'execute';
|
|
39
|
+
}> extends {
|
|
40
|
+
complete: (...arguments_: never[]) => infer Returned;
|
|
41
|
+
} ? Returned : never;
|
|
42
|
+
/** Host runs the handler in the secured inner native mutation transaction, including receipt completion. */
|
|
43
|
+
declare function effectReceiptWorkflowMutation<Args, Authorize, const Replay extends ContractSchema, Prepare extends Supported<EffectIdempotencyPreparation<ContractOutput<Replay>, unknown, unknown>>, Execute extends Supported<ContractOutput<Replay>>>(configuration: {
|
|
44
|
+
authorize: (execution: WorkflowExecution<Args>) => Authorize;
|
|
45
|
+
receipt: (authority: EffectValue<Authorize>) => {
|
|
46
|
+
replayResult: Replay;
|
|
47
|
+
prepare: (invocation: IdempotencyInvocation) => Prepare;
|
|
48
|
+
};
|
|
49
|
+
invocation: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => IdempotencyInvocation;
|
|
50
|
+
execute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute;
|
|
51
|
+
}): EffectReceiptProtectedWorkflowMutation<Args, ContractOutput<Replay>, WorkflowBindingError | CallbackError<Authorize | Prepare | Execute | Completion<Prepare>> | ContractDecoderError<Replay>, CallbackRequirements<Authorize | Prepare | Execute | Completion<Prepare>> | ContractDecoderRequirements<Replay>>;
|
|
52
|
+
type StateResult<Read> = EffectValue<Read> extends WorkflowHostState<infer Result, unknown> ? Result : never;
|
|
53
|
+
type StateFailure<Read> = EffectValue<Read> extends WorkflowHostState<unknown, infer Failure> ? Failure : never;
|
|
54
|
+
/** The host still owns native manager calls and transactional/CAS writes; each method retains only its used channels. */
|
|
55
|
+
declare function effectWorkflowStatusBindings<Authorize, Read extends Supported<WorkflowHostState>, Write, Native extends Supported<WorkflowNativeStatus>, Receipt extends Supported<WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined>, Cancel, Restart>(configuration: {
|
|
56
|
+
authorize: () => Authorize;
|
|
57
|
+
read: () => Read;
|
|
58
|
+
write: (expectedGeneration: number, state: WorkflowHostState<StateResult<Read>, StateFailure<Read>>) => Write;
|
|
59
|
+
nativeStatus: () => Native;
|
|
60
|
+
receiptOutcome: () => Receipt;
|
|
61
|
+
cancelNative: () => Cancel;
|
|
62
|
+
restartNative: () => Restart;
|
|
63
|
+
}): {
|
|
64
|
+
callback(expectedGeneration: number, nativeStatus: WorkflowNativeStatus, outcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>): Effect.Effect<WorkflowTransition<StateResult<Read>, StateFailure<Read>>, WorkflowBindingError | CallbackError<Authorize> | CallbackError<Read> | CallbackError<Write>, CallbackRequirements<Authorize> | CallbackRequirements<Read> | CallbackRequirements<Write>>;
|
|
65
|
+
reconcile(expectedGeneration: number): Effect.Effect<WorkflowTransition<StateResult<Read>, StateFailure<Read>>, WorkflowBindingError | CallbackError<Authorize> | CallbackError<Native> | CallbackError<Read> | CallbackError<Receipt> | CallbackError<Write>, CallbackRequirements<Authorize> | CallbackRequirements<Native> | CallbackRequirements<Read> | CallbackRequirements<Receipt> | CallbackRequirements<Write>>;
|
|
66
|
+
cancel(expectedGeneration: number): Effect.Effect<WorkflowTransition<StateResult<Read>, StateFailure<Read>>, WorkflowBindingError | CallbackError<Authorize> | CallbackError<Cancel> | CallbackError<Read> | CallbackError<Write>, CallbackRequirements<Authorize> | CallbackRequirements<Cancel> | CallbackRequirements<Read> | CallbackRequirements<Write>>;
|
|
67
|
+
restart(expectedGeneration: number): Effect.Effect<{
|
|
68
|
+
kind: 'ignored';
|
|
69
|
+
state: WorkflowHostState<StateResult<Read>, StateFailure<Read>>;
|
|
70
|
+
} | {
|
|
71
|
+
kind: 'applied';
|
|
72
|
+
state: WorkflowHostState<StateResult<Read>, StateFailure<Read>>;
|
|
73
|
+
}, WorkflowBindingError | CallbackError<Authorize> | CallbackError<Read> | CallbackError<Restart> | CallbackError<Write>, CallbackRequirements<Authorize> | CallbackRequirements<Read> | CallbackRequirements<Restart> | CallbackRequirements<Write>>;
|
|
74
|
+
};
|
|
75
|
+
//#endregion
|
|
76
|
+
export { EffectReceiptProtectedWorkflowMutation, effectReceiptWorkflowMutation, effectTerminalWorkflowAttempt, effectWorkflowAttempt, effectWorkflowStatusBindings };
|
|
77
|
+
//# sourceMappingURL=workflow.d.mts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{decodeEffectContract as e}from"./schema.mjs";import{normalizeEffect as t}from"./normalize.mjs";import{WorkflowBindingError as n,workflowCancel as r,workflowExecution as i,workflowRestart as a,workflowTransition as o}from"../contracts/workflow.mjs";import{Effect as s}from"effect";function c(e){return n=>s.gen(function*(){let r=yield*f(n),i=yield*t(()=>e.authorize(r));return yield*t(()=>e.execute(r,i))})}function l(n){return r=>s.gen(function*(){let i=yield*f(r),a=yield*t(()=>n.authorize(i)),o=yield*s.tryPromise({try:()=>n.invokeMutation(i,a),catch:e=>e}).pipe(s.map(e=>({kind:`success`,value:e})),s.catch(e=>s.succeed({kind:`rejected`,error:e})));if(o.kind===`rejected`){let r=yield*t(()=>n.terminal(o.error));if(r===void 0)return yield*s.die(o.error);let a=yield*e(n.failure,r);return yield*f({...i,args:a}),{version:1,kind:`failed`,error:a}}return yield*e(n.result,o.value),yield*f({...i,args:o.value}),{version:1,kind:`succeeded`,value:o.value}})}function u(n){return{handler:r=>s.gen(function*(){let i=yield*f(r),a=yield*t(()=>n.authorize(i)),o=n.receipt(a),s=yield*t(()=>o.prepare(n.invocation(i,a)));if(s.kind===`replay`)return yield*e(o.replayResult,s.result);let c=yield*t(()=>n.execute(i,a)),l=s.complete;return yield*t(()=>l(c)),c})}}function d(e){function n(){return t(()=>e.read()).pipe(s.map(e=>e))}function i(r,i,a){return s.gen(function*(){let s=yield*n(),c={generation:r,nativeStatus:i},l=yield*p(()=>o(s,a===void 0?c:{...c,outcome:a}));return l.kind===`applied`&&(yield*t(()=>e.write(r,l.state))),l})}return{callback(n,r,a){return t(()=>e.authorize()).pipe(s.flatMap(()=>i(n,r,a)))},reconcile(n){return s.gen(function*(){return yield*t(()=>e.authorize()),yield*i(n,yield*t(()=>e.nativeStatus()),yield*t(()=>e.receiptOutcome()))})},cancel(i){return s.gen(function*(){yield*t(()=>e.authorize());let a=yield*n(),o=yield*p(()=>r(a,i));return o.kind===`applied`&&a.status===`running`&&(yield*t(()=>e.cancelNative()),yield*t(()=>e.write(i,o.state))),o})},restart(r){return s.gen(function*(){yield*t(()=>e.authorize());let i=yield*n();if(i.generation!==r)return{kind:`ignored`,state:i};let o=yield*p(()=>a(i));return yield*t(()=>e.restartNative()),yield*t(()=>e.write(r,o)),{kind:`applied`,state:o}})}}}function f(e){return p(()=>i(e))}function p(e){return s.try({try:e,catch:e=>{if(e instanceof n)return e;throw e}})}export{u as effectReceiptWorkflowMutation,l as effectTerminalWorkflowAttempt,c as effectWorkflowAttempt,d as effectWorkflowStatusBindings};
|
|
2
|
+
//# sourceMappingURL=workflow.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.mjs","names":[],"sources":["../../../src/modules/effect/workflow.ts"],"sourcesContent":["import { Effect } from 'effect'\nimport type { ContractInput, ContractOutput, ContractSchema } from '../contracts/contract'\nimport {\n\tWorkflowBindingError,\n\tworkflowExecution,\n\tworkflowTransition,\n\tworkflowCancel,\n\tworkflowRestart,\n\ttype WorkflowExecution,\n\ttype WorkflowOutcome,\n\ttype WorkflowHostState,\n\ttype WorkflowNativeStatus,\n} from '../contracts/workflow'\nimport type { IdempotencyInvocation } from '../contracts/idempotency'\nimport type { EffectIdempotencyPreparation } from './idempotency'\nimport type { CallbackError, CallbackRequirements, EffectValue } from './operation'\nimport { normalizeEffect } from './normalize'\nimport {\n\tdecodeEffectContract,\n\ttype ContractDecoderError,\n\ttype ContractDecoderRequirements,\n} from './schema'\n\ntype Supported<A> = A | PromiseLike<A> | Effect.Effect<A, unknown, unknown>\n/** Services exist only inside a new native invocation; ordinary throws/rejections remain defects. */\nexport function effectWorkflowAttempt<Args, Authorize, Execute>(configuration: {\n\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\texecute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute\n}) {\n\treturn (\n\t\tinput: WorkflowExecution<Args>,\n\t): Effect.Effect<\n\t\tEffectValue<Execute>,\n\t\tWorkflowBindingError | CallbackError<Authorize | Execute>,\n\t\tCallbackRequirements<Authorize | Execute>\n\t> =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\treturn yield* normalizeEffect(() => configuration.execute(execution, authority))\n\t\t})\n}\n/** Native mutation promise rejects outside the child transaction before mapping declared terminal details. */\nexport function effectTerminalWorkflowAttempt<\n\tArgs,\n\tAuthorize,\n\tconst Result extends ContractSchema,\n\tconst Failure extends ContractSchema,\n\tTerminal extends Supported<ContractInput<Failure> | undefined>,\n>(\n\tconfiguration: (\n\t\t| { kind: 'mutation'; atomicJournalProof: 'host-verified' }\n\t\t| {\n\t\t\t\tkind: 'action'\n\t\t\t\tprotectedMutation: EffectReceiptProtectedWorkflowMutation<Args, unknown, unknown, unknown>\n\t\t }\n\t) & {\n\t\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\t\tinvokeMutation: (\n\t\t\texecution: WorkflowExecution<Args>,\n\t\t\tauthority: EffectValue<Authorize>,\n\t\t) => Promise<ContractInput<Result>>\n\t\t// oxlint-disable-next-line anti-slop/no-unknown-parameters -- A rejected native mutation can throw any value; the host terminal callback classifies it before failure contract validation.\n\t\tterminal: (error: unknown) => Terminal\n\t\tresult: Result\n\t\tfailure: Failure\n\t},\n) {\n\treturn (\n\t\tinput: WorkflowExecution<Args>,\n\t): Effect.Effect<\n\t\tWorkflowOutcome<ContractInput<Result>, ContractOutput<Failure>>,\n\t\t| WorkflowBindingError\n\t\t| CallbackError<Authorize | Terminal>\n\t\t| ContractDecoderError<Result | Failure>,\n\t\tCallbackRequirements<Authorize | Terminal> | ContractDecoderRequirements<Result | Failure>\n\t> =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\tconst native = yield* Effect.tryPromise({\n\t\t\t\ttry: () => configuration.invokeMutation(execution, authority),\n\t\t\t\tcatch: (error) => error,\n\t\t\t}).pipe(\n\t\t\t\tEffect.map((value) => ({ kind: 'success' as const, value })),\n\t\t\t\tEffect.catch((error) => Effect.succeed({ kind: 'rejected' as const, error })),\n\t\t\t)\n\t\t\tif (native.kind === 'rejected') {\n\t\t\t\tconst failure = yield* normalizeEffect(() => configuration.terminal(native.error))\n\t\t\t\tif (failure === undefined) return yield* Effect.die(native.error)\n\t\t\t\t// SAFETY: Terminal is constrained to this exact failure wire input or undefined.\n\t\t\t\tconst error = yield* decodeEffectContract(\n\t\t\t\t\tconfiguration.failure,\n\t\t\t\t\tfailure as ContractInput<Failure>,\n\t\t\t\t)\n\t\t\t\tyield* descriptor({ ...execution, args: error })\n\t\t\t\treturn { version: 1 as const, kind: 'failed' as const, error }\n\t\t\t}\n\t\t\tyield* decodeEffectContract(configuration.result, native.value)\n\t\t\tyield* descriptor({ ...execution, args: native.value })\n\t\t\treturn { version: 1 as const, kind: 'succeeded' as const, value: native.value }\n\t\t})\n}\ndeclare const protectedMutation: unique symbol\nexport interface EffectReceiptProtectedWorkflowMutation<Args, Result, Error, Requirements> {\n\treadonly [protectedMutation]: { args: Args; result: Result }\n\treadonly handler: (\n\t\texecution: WorkflowExecution<Args>,\n\t) => Effect.Effect<Result, Error, Requirements>\n}\ntype Completion<Prepare> =\n\tExtract<EffectValue<Prepare>, { kind: 'execute' }> extends {\n\t\tcomplete: (...arguments_: never[]) => infer Returned\n\t}\n\t\t? Returned\n\t\t: never\n/** Host runs the handler in the secured inner native mutation transaction, including receipt completion. */\nexport function effectReceiptWorkflowMutation<\n\tArgs,\n\tAuthorize,\n\tconst Replay extends ContractSchema,\n\tPrepare extends Supported<EffectIdempotencyPreparation<ContractOutput<Replay>, unknown, unknown>>,\n\tExecute extends Supported<ContractOutput<Replay>>,\n>(configuration: {\n\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\treceipt: (authority: EffectValue<Authorize>) => {\n\t\treplayResult: Replay\n\t\tprepare: (invocation: IdempotencyInvocation) => Prepare\n\t}\n\tinvocation: (\n\t\texecution: WorkflowExecution<Args>,\n\t\tauthority: EffectValue<Authorize>,\n\t) => IdempotencyInvocation\n\texecute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute\n}): EffectReceiptProtectedWorkflowMutation<\n\tArgs,\n\tContractOutput<Replay>,\n\t| WorkflowBindingError\n\t| CallbackError<Authorize | Prepare | Execute | Completion<Prepare>>\n\t| ContractDecoderError<Replay>,\n\t| CallbackRequirements<Authorize | Prepare | Execute | Completion<Prepare>>\n\t| ContractDecoderRequirements<Replay>\n> {\n\tconst handler = (input: WorkflowExecution<Args>) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\tconst adapter = configuration.receipt(authority)\n\t\t\tconst preparation = yield* normalizeEffect(() =>\n\t\t\t\tadapter.prepare(configuration.invocation(execution, authority)),\n\t\t\t)\n\t\t\tif (preparation.kind === 'replay')\n\t\t\t\treturn yield* decodeEffectContract(adapter.replayResult, preparation.result)\n\t\t\tconst value = yield* normalizeEffect(() => configuration.execute(execution, authority))\n\t\t\t// SAFETY: the execute branch came from this exact Prepare value; recover its complete callback rather than the broad constraint.\n\t\t\tconst complete = preparation.complete as (\n\t\t\t\tresult: ContractOutput<Replay>,\n\t\t\t) => Completion<Prepare>\n\t\t\t// SAFETY: Execute's supported success is the exact final replay output contract.\n\t\t\tyield* normalizeEffect(() => complete(value as ContractOutput<Replay>))\n\t\t\t// SAFETY: Execute's supported success is the exact final replay output contract.\n\t\t\treturn value as ContractOutput<Replay>\n\t\t})\n\t// SAFETY: only private receipt evidence is asserted; handler's inferred E/R remain checked against the public return.\n\treturn { handler } as ReceiptEvidence<Args, ContractOutput<Replay>, typeof handler>\n}\ntype ReceiptEvidence<Args, Result, Handler> = {\n\thandler: Handler\n\treadonly [protectedMutation]: { args: Args; result: Result }\n}\ntype StateResult<Read> =\n\tEffectValue<Read> extends WorkflowHostState<infer Result, unknown> ? Result : never\ntype StateFailure<Read> =\n\tEffectValue<Read> extends WorkflowHostState<unknown, infer Failure> ? Failure : never\n/** The host still owns native manager calls and transactional/CAS writes; each method retains only its used channels. */\nexport function effectWorkflowStatusBindings<\n\tAuthorize,\n\tRead extends Supported<WorkflowHostState>,\n\tWrite,\n\tNative extends Supported<WorkflowNativeStatus>,\n\tReceipt extends Supported<WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined>,\n\tCancel,\n\tRestart,\n>(configuration: {\n\tauthorize: () => Authorize\n\tread: () => Read\n\twrite: (\n\t\texpectedGeneration: number,\n\t\tstate: WorkflowHostState<StateResult<Read>, StateFailure<Read>>,\n\t) => Write\n\tnativeStatus: () => Native\n\treceiptOutcome: () => Receipt\n\tcancelNative: () => Cancel\n\trestartNative: () => Restart\n}) {\n\ttype State = WorkflowHostState<StateResult<Read>, StateFailure<Read>>\n\tfunction read() {\n\t\t// SAFETY: Read's supported success is the host state whose outcome types are extracted above.\n\t\treturn normalizeEffect(() => configuration.read()).pipe(Effect.map((state) => state as State))\n\t}\n\tfunction apply(\n\t\texpectedGeneration: number,\n\t\tnativeStatus: WorkflowNativeStatus,\n\t\toutcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>,\n\t) {\n\t\treturn Effect.gen(function* () {\n\t\t\tconst current = yield* read()\n\t\t\tconst update = { generation: expectedGeneration, nativeStatus }\n\t\t\tconst transition = yield* protocol(() =>\n\t\t\t\tworkflowTransition(current, outcome === undefined ? update : { ...update, outcome }),\n\t\t\t)\n\t\t\tif (transition.kind === 'applied')\n\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, transition.state))\n\t\t\treturn transition\n\t\t})\n\t}\n\treturn {\n\t\tcallback(\n\t\t\texpectedGeneration: number,\n\t\t\tnativeStatus: WorkflowNativeStatus,\n\t\t\toutcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>,\n\t\t) {\n\t\t\treturn normalizeEffect(() => configuration.authorize()).pipe(\n\t\t\t\tEffect.flatMap(() => apply(expectedGeneration, nativeStatus, outcome)),\n\t\t\t)\n\t\t},\n\t\treconcile(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst native = yield* normalizeEffect(() => configuration.nativeStatus())\n\t\t\t\tconst outcome = yield* normalizeEffect(() => configuration.receiptOutcome())\n\t\t\t\t// SAFETY: Native and Receipt are constrained to these exact host transport values.\n\t\t\t\treturn yield* apply(\n\t\t\t\t\texpectedGeneration,\n\t\t\t\t\tnative as WorkflowNativeStatus,\n\t\t\t\t\toutcome as WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined,\n\t\t\t\t)\n\t\t\t})\n\t\t},\n\t\tcancel(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst current = yield* read()\n\t\t\t\tconst transition = yield* protocol(() => workflowCancel(current, expectedGeneration))\n\t\t\t\tif (transition.kind === 'applied' && current.status === 'running') {\n\t\t\t\t\tyield* normalizeEffect(() => configuration.cancelNative())\n\t\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, transition.state))\n\t\t\t\t}\n\t\t\t\treturn transition\n\t\t\t})\n\t\t},\n\t\trestart(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst current = yield* read()\n\t\t\t\tif (current.generation !== expectedGeneration)\n\t\t\t\t\treturn { kind: 'ignored' as const, state: current }\n\t\t\t\tconst state = yield* protocol(() => workflowRestart(current))\n\t\t\t\tyield* normalizeEffect(() => configuration.restartNative())\n\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, state))\n\t\t\t\treturn { kind: 'applied' as const, state }\n\t\t\t})\n\t\t},\n\t}\n}\nfunction descriptor<Args>(\n\tvalue: WorkflowExecution<Args>,\n): Effect.Effect<WorkflowExecution<Args>, WorkflowBindingError> {\n\treturn protocol(() => workflowExecution(value))\n}\nfunction protocol<A>(evaluate: () => A): Effect.Effect<A, WorkflowBindingError> {\n\treturn Effect.try({\n\t\ttry: evaluate,\n\t\tcatch: (error) => {\n\t\t\tif (error instanceof WorkflowBindingError) return error\n\t\t\tthrow error\n\t\t},\n\t})\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region node_modules/@standard-schema/spec/dist/index.d.ts
|
|
2
|
+
/** The Standard Typed interface. This is a base type extended by other specs. */
|
|
3
|
+
interface StandardTypedV1<Input = unknown, Output = Input> {
|
|
4
|
+
/** The Standard properties. */
|
|
5
|
+
readonly "~standard": StandardTypedV1.Props<Input, Output>;
|
|
6
|
+
}
|
|
7
|
+
declare namespace StandardTypedV1 {
|
|
8
|
+
/** The Standard Typed properties interface. */
|
|
9
|
+
interface Props<Input = unknown, Output = Input> {
|
|
10
|
+
/** The version number of the standard. */
|
|
11
|
+
readonly version: 1;
|
|
12
|
+
/** The vendor name of the schema library. */
|
|
13
|
+
readonly vendor: string;
|
|
14
|
+
/** Inferred types associated with the schema. */
|
|
15
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** The Standard Typed types interface. */
|
|
18
|
+
interface Types<Input = unknown, Output = Input> {
|
|
19
|
+
/** The input type of the schema. */
|
|
20
|
+
readonly input: Input;
|
|
21
|
+
/** The output type of the schema. */
|
|
22
|
+
readonly output: Output;
|
|
23
|
+
}
|
|
24
|
+
/** Infers the input type of a Standard Typed. */
|
|
25
|
+
type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
26
|
+
/** Infers the output type of a Standard Typed. */
|
|
27
|
+
type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
28
|
+
}
|
|
29
|
+
/** The Standard Schema interface. */
|
|
30
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
31
|
+
/** The Standard Schema properties. */
|
|
32
|
+
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
|
33
|
+
}
|
|
34
|
+
declare namespace StandardSchemaV1 {
|
|
35
|
+
/** The Standard Schema properties interface. */
|
|
36
|
+
interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
|
37
|
+
/** Validates unknown input values. */
|
|
38
|
+
readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
|
|
39
|
+
}
|
|
40
|
+
/** The result interface of the validate function. */
|
|
41
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
42
|
+
/** The result interface if validation succeeds. */
|
|
43
|
+
interface SuccessResult<Output> {
|
|
44
|
+
/** The typed output value. */
|
|
45
|
+
readonly value: Output;
|
|
46
|
+
/** A falsy value for `issues` indicates success. */
|
|
47
|
+
readonly issues?: undefined;
|
|
48
|
+
}
|
|
49
|
+
interface Options {
|
|
50
|
+
/** Explicit support for additional vendor-specific parameters, if needed. */
|
|
51
|
+
readonly libraryOptions?: Record<string, unknown> | undefined;
|
|
52
|
+
}
|
|
53
|
+
/** The result interface if validation fails. */
|
|
54
|
+
interface FailureResult {
|
|
55
|
+
/** The issues of failed validation. */
|
|
56
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
57
|
+
}
|
|
58
|
+
/** The issue interface of the failure output. */
|
|
59
|
+
interface Issue {
|
|
60
|
+
/** The error message of the issue. */
|
|
61
|
+
readonly message: string;
|
|
62
|
+
/** The path of the issue, if any. */
|
|
63
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
64
|
+
}
|
|
65
|
+
/** The path segment interface of the issue. */
|
|
66
|
+
interface PathSegment {
|
|
67
|
+
/** The key representing a path segment. */
|
|
68
|
+
readonly key: PropertyKey;
|
|
69
|
+
}
|
|
70
|
+
/** The Standard types interface. */
|
|
71
|
+
interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
|
|
72
|
+
/** Infers the input type of a Standard. */
|
|
73
|
+
type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
|
74
|
+
/** Infers the output type of a Standard. */
|
|
75
|
+
type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { StandardSchemaV1, StandardTypedV1 };
|
|
79
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ResolverFactory } from "oxc-resolver";
|
|
2
|
+
//#region src/oxlint/architecture.d.ts
|
|
3
|
+
interface ArchitectureOptions {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
convexDir?: string;
|
|
6
|
+
}
|
|
7
|
+
interface ArchitectureDiagnostic {
|
|
8
|
+
code: 'missing-root' | 'root-directory' | 'tests' | 'test-location' | 'parse' | 'cycle' | 'symlink' | 'domain-entry' | 'shared-owner';
|
|
9
|
+
file: string;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
/** Full-project checks, independent of the consumer's test runner. No persistent cache. */
|
|
13
|
+
declare function inspectArchitecture(options?: ArchitectureOptions): ArchitectureDiagnostic[];
|
|
14
|
+
declare function createResolver(): ResolverFactory;
|
|
15
|
+
declare function resolveImport(resolver: ResolverFactory, filename: string, source: string): string | null;
|
|
16
|
+
/** The lint rule runs the project scan on one deterministic source file. */
|
|
17
|
+
declare function architectureAnchor(root: string): string | null;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { ArchitectureDiagnostic, ArchitectureOptions, architectureAnchor, createResolver, inspectArchitecture, resolveImport };
|
|
20
|
+
//# sourceMappingURL=architecture.d.mts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{dirname as e,relative as t,resolve as n,sep as r}from"node:path";import{existsSync as i,readFileSync as a,readdirSync as o,realpathSync as s}from"node:fs";import{Visitor as c,parseSync as l}from"oxc-parser";import{ResolverFactory as u}from"oxc-resolver";function d(o={}){let c=n(o.cwd??process.cwd(),o.convexDir??`convex`),u=i(c)?s(c):c,d=[];if(!i(u))return[{code:`missing-root`,file:`.`,message:`Convex directory does not exist: ${u}`}];let m=h(u,d),y=new Set,w=new Set,T=new Map,E=new Map,D=f();for(let i of m){let o=n(u,i),s=l(o,a(o,`utf8`));if(s.errors.length){d.push({code:`parse`,file:i,message:`Cannot validate ${i}: ${s.errors[0].message}`});continue}if(g(i)){i.includes(`__tests__/`)?e(i).endsWith(`__tests__`)&&v(s.program)&&w.add(e(e(i))):d.push({code:`test-location`,file:i,message:`Place tests in a sibling __tests__/ directory.`});continue}if(i.split(`/`).includes(`__tests__`))continue;/^domain\/[^/]+$/.test(i)&&i!==`domain/table.ts`&&d.push({code:`domain-entry`,file:i,message:`Domain source belongs in domain/<module>/ or domain/shared/. Only domain/table.ts assembles module tables.`}),_(s.program)&&i!==`domain/table.ts`&&y.add(e(i));let c=x(i)??``,f=new Set;E.set(i,f);for(let e of b(s.program)){let n=p(D,o,e);if(!n)continue;let i=t(u,n).split(r).join(`/`);f.add(i);let a=x(i);if(c&&a&&c!==a){let e=T.get(c)??new Set;T.set(c,e),e.add(a)}}}for(let e of y)w.has(e)||d.push({code:`tests`,file:e,message:`${e}/__tests__/ must contain a .test or .spec file with a nonempty, non-skipped test. Parent or child suites do not count.`});d.push(...C(E));for(let e of S(T))d.push({code:`cycle`,file:e[0],message:`Module dependency cycle: ${e.join(` → `)}.`});return d.sort((e,t)=>e.file.localeCompare(t.file)||e.code.localeCompare(t.code))}function f(){return new u({tsconfig:`auto`,extensions:[`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`],extensionAlias:{".js":[`.ts`,`.tsx`,`.js`],".mjs":[`.mts`,`.mjs`],".cjs":[`.cts`,`.cjs`]},conditionNames:[`types`,`import`,`node`,`default`],symlinks:!0})}function p(t,r,i){return t.resolveFileSync(r,i).path||(i.startsWith(`.`)?n(e(r),i):null)}function m(e){if(!i(e))return null;if(i(n(e,`convex.config.ts`)))return s(n(e,`convex.config.ts`));e=s(e);for(let t of h(e,[]))if(!t.includes(`__tests__/`)&&!g(t))return n(e,t);return null}function*h(e,i){let a=new Set([`_generated`,`__tests__`,`api`,`domain`,`application`,`migrations`,`components`]);function*s(c){for(let l of o(c,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let o=n(c,l.name),u=t(e,o).split(r).join(`/`);if(l.isSymbolicLink()){i.push({code:`symlink`,file:u,message:`Keep application source inside its owning directory; symlinked files and folders are not allowed.`});continue}l.isDirectory()?(c===e&&!a.has(l.name)&&i.push({code:`root-directory`,file:u,message:`Root folder ${l.name}/ is not allowed. Use api/, domain/, application/, migrations/, components/, __tests__/, or _generated/.`}),l.name!==`_generated`&&l.name!==`node_modules`&&!l.name.startsWith(`.`)&&(yield*s(o))):/\.[cm]?[jt]sx?$/.test(l.name)&&!/\.d\.[cm]?ts$/.test(l.name)&&(yield u)}}yield*s(e)}function g(e){return/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(e)}function _(e){return e.body.some(e=>{let t=e.type===`ExportNamedDeclaration`?e.declaration:e;return t&&`declare`in t&&t.declare||e.type===`ImportDeclaration`||e.type===`EmptyStatement`?!1:e.type===`ExportNamedDeclaration`?e.exportKind===`type`||!e.declaration?!1:![`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSDeclareFunction`].includes(e.declaration.type):![`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSDeclareFunction`,`ExportAllDeclaration`].includes(e.type)})}function v(e){let t=new Map([[`test`,`test`],[`it`,`it`],[`describe`,`describe`],[`suite`,`suite`]]);for(let n of e.body){let e=n.type===`ExportNamedDeclaration`?n.declaration:n;if(e?.type===`FunctionDeclaration`&&e.id&&t.delete(e.id.name),e?.type===`VariableDeclaration`)for(let n of e.declarations)n.id.type===`Identifier`&&t.delete(n.id.name);if(n.type===`ImportDeclaration`)for(let e of n.specifiers)t.delete(e.local.name),[`vitest`,`vite-plus/test`,`bun:test`,`node:test`,`@jest/globals`].includes(n.source.value)&&(e.type===`ImportNamespaceSpecifier`?t.set(e.local.name,`*`):e.type===`ImportDefaultSpecifier`?t.set(e.local.name,`test`):e.imported.type===`Identifier`&&t.set(e.local.name,e.imported.name))}let n=[];new c({CallExpression(e){n.push(e)}}).visit(e);let r=n.filter(e=>{let n=y(e.callee,t);return[`test`,`it`,`describe`,`suite`].includes(n[0])&&(n.some(e=>[`skip`,`todo`,`skipIf`,`runIf`].includes(e))||e.arguments.some(e=>e.type===`ObjectExpression`&&e.properties.some(e=>e.type===`Property`&&[`skip`,`todo`].includes(e.key.type===`Identifier`?e.key.name:e.key.type===`Literal`?String(e.key.value):``)&&(e.value.type!==`Literal`||e.value.value!==!1))))});return n.some(e=>{let n=y(e.callee,t);return![`test`,`it`].includes(n[0])||r.some(t=>e.start>=t.start&&e.end<=t.end)?!1:e.arguments.some(e=>(e.type===`ArrowFunctionExpression`||e.type===`FunctionExpression`)&&e.body&&(e.body.type!==`BlockStatement`||e.body.body.some(e=>e.type!==`EmptyStatement`)))})}function y(e,t){if(e.type===`Identifier`){let n=t.get(e.name);return n?[n]:[]}if(e.type===`CallExpression`)return y(e.callee,t);if(e.type===`MemberExpression`){let n=y(e.object,t),r=!e.computed&&e.property.type===`Identifier`?e.property.name:e.property.type===`Literal`?String(e.property.value):``;return!n.length||!r?[]:n[0]===`*`?[r]:[...n,r]}return[]}function b(e){let t=[];return new c({ImportDeclaration(e){e.importKind!==`type`&&(e.specifiers.length===0||e.specifiers.some(e=>e.type!==`ImportSpecifier`||e.importKind!==`type`))&&t.push(e.source.value)},ExportNamedDeclaration(e){e.source&&e.exportKind!==`type`&&e.specifiers.some(e=>e.exportKind!==`type`)&&t.push(e.source.value)},ExportAllDeclaration(e){e.exportKind!==`type`&&t.push(e.source.value)},ImportExpression(e){e.source.type===`Literal`&&String(e.source.value)===e.source.value&&t.push(String(e.source.value))}}).visit(e),t}function x(e){let t=e.split(`/`);return t[0]===`domain`&&t.length>=3&&t[1]!==`__tests__`?`domain/${t[1]}`:null}function S(e){let t=new Set,n=[],r=[];function i(a){let o=n.indexOf(a);if(o>=0){r.push([...n.slice(o),a]);return}if(!t.has(a)){n.push(a);for(let t of e.get(a)??[])i(t);n.pop(),t.add(a)}}for(let t of e.keys())i(t);return r}function C(e){let t=new Map;for(let[n,r]of e){let i=x(n)??``;if(!i||i===`domain/shared`)continue;let a=new Set;function o(n){if(!n.startsWith(`domain/shared/`)||a.has(n))return;a.add(n);let r=t.get(n)??new Set;r.add(i),t.set(n,r);for(let t of e.get(n)??[])o(t)}for(let e of r)o(e)}let n=[];for(let[e,r]of t)r.size===1&&n.push({code:`shared-owner`,file:e,message:`This shared implementation is used only by ${[...r][0]}. Move it into that module until another module needs it.`});return n}export{m as architectureAnchor,f as createResolver,d as inspectArchitecture,p as resolveImport};
|
|
2
|
+
//# sourceMappingURL=architecture.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.mjs","names":[],"sources":["../../src/oxlint/architecture.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport { parseSync, Visitor, type Program, type Node, type CallExpression } from 'oxc-parser'\nimport { ResolverFactory } from 'oxc-resolver'\n\nexport interface ArchitectureOptions {\n\tcwd?: string\n\tconvexDir?: string\n}\nexport interface ArchitectureDiagnostic {\n\tcode:\n\t\t| 'missing-root'\n\t\t| 'root-directory'\n\t\t| 'tests'\n\t\t| 'test-location'\n\t\t| 'parse'\n\t\t| 'cycle'\n\t\t| 'symlink'\n\t\t| 'domain-entry'\n\t\t| 'shared-owner'\n\tfile: string\n\tmessage: string\n}\n\n/** Full-project checks, independent of the consumer's test runner. No persistent cache. */\nexport function inspectArchitecture(options: ArchitectureOptions = {}): ArchitectureDiagnostic[] {\n\tconst requestedRoot = resolve(options.cwd ?? process.cwd(), options.convexDir ?? 'convex')\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst diagnostics: ArchitectureDiagnostic[] = []\n\tif (!existsSync(root))\n\t\treturn [\n\t\t\t{ code: 'missing-root', file: '.', message: `Convex directory does not exist: ${root}` },\n\t\t]\n\tconst files = sourceFiles(root, diagnostics)\n\tconst required = new Set<string>()\n\tconst tested = new Set<string>()\n\tconst graph = new Map<string, Set<string>>()\n\tconst dependencies = new Map<string, Set<string>>()\n\tconst resolver = createResolver()\n\tfor (const file of files) {\n\t\tconst filename = resolve(root, file)\n\t\tconst parsed = parseSync(filename, readFileSync(filename, 'utf8'))\n\t\tif (parsed.errors.length) {\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'parse',\n\t\t\t\tfile,\n\t\t\t\tmessage: `Cannot validate ${file}: ${parsed.errors[0].message}`,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif (testFile(file)) {\n\t\t\tif (!file.includes('__tests__/'))\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tcode: 'test-location',\n\t\t\t\t\tfile,\n\t\t\t\t\tmessage: 'Place tests in a sibling __tests__/ directory.',\n\t\t\t\t})\n\t\t\telse if (dirname(file).endsWith('__tests__') && hasRunnableTest(parsed.program))\n\t\t\t\ttested.add(dirname(dirname(file)))\n\t\t\tcontinue\n\t\t}\n\t\tif (file.split('/').includes('__tests__')) continue\n\t\tif (/^domain\\/[^/]+$/.test(file) && file !== 'domain/table.ts')\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'domain-entry',\n\t\t\t\tfile,\n\t\t\t\tmessage:\n\t\t\t\t\t'Domain source belongs in domain/<module>/ or domain/shared/. Only domain/table.ts assembles module tables.',\n\t\t\t})\n\t\tif (executable(parsed.program) && file !== 'domain/table.ts') required.add(dirname(file))\n\t\tconst owner = moduleOwner(file) ?? ''\n\t\tconst targets = new Set<string>()\n\t\tdependencies.set(file, targets)\n\t\tfor (const source of runtimeImports(parsed.program)) {\n\t\t\tconst target = resolveImport(resolver, filename, source)\n\t\t\tif (!target) continue\n\t\t\tconst targetFile = relative(root, target).split(sep).join('/')\n\t\t\ttargets.add(targetFile)\n\t\t\tconst targetOwner = moduleOwner(targetFile)\n\t\t\tif (owner && targetOwner && owner !== targetOwner) {\n\t\t\t\tconst edges = graph.get(owner) ?? new Set<string>()\n\t\t\t\tgraph.set(owner, edges)\n\t\t\t\tedges.add(targetOwner)\n\t\t\t}\n\t\t}\n\t}\n\tfor (const directory of required) {\n\t\tif (!tested.has(directory))\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'tests',\n\t\t\t\tfile: directory,\n\t\t\t\tmessage: `${directory}/__tests__/ must contain a .test or .spec file with a nonempty, non-skipped test. Parent or child suites do not count.`,\n\t\t\t})\n\t}\n\tdiagnostics.push(...sharedOwnership(dependencies))\n\tfor (const cycle of cycles(graph))\n\t\tdiagnostics.push({\n\t\t\tcode: 'cycle',\n\t\t\tfile: cycle[0],\n\t\t\tmessage: `Module dependency cycle: ${cycle.join(' → ')}.`,\n\t\t})\n\treturn diagnostics.sort((a, b) => a.file.localeCompare(b.file) || a.code.localeCompare(b.code))\n}\n\nexport function createResolver() {\n\treturn new ResolverFactory({\n\t\ttsconfig: 'auto',\n\t\textensions: ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs', '.json'],\n\t\textensionAlias: {\n\t\t\t'.js': ['.ts', '.tsx', '.js'],\n\t\t\t'.mjs': ['.mts', '.mjs'],\n\t\t\t'.cjs': ['.cts', '.cjs'],\n\t\t},\n\t\tconditionNames: ['types', 'import', 'node', 'default'],\n\t\tsymlinks: true,\n\t})\n}\n\nexport function resolveImport(resolver: ResolverFactory, filename: string, source: string) {\n\tconst found = resolver.resolveFileSync(filename, source).path\n\tif (found) return found\n\t// Keep path checks useful in unsaved/editor fixtures and before Convex codegen.\n\treturn source.startsWith('.') ? resolve(dirname(filename), source) : null\n}\n\n/** The lint rule runs the project scan on one deterministic source file. */\nexport function architectureAnchor(root: string) {\n\tif (!existsSync(root)) return null\n\tif (existsSync(resolve(root, 'convex.config.ts')))\n\t\treturn realpathSync(resolve(root, 'convex.config.ts'))\n\troot = realpathSync(root)\n\tfor (const file of sourceFiles(root, []))\n\t\tif (!file.includes('__tests__/') && !testFile(file)) return resolve(root, file)\n\treturn null\n}\n\nfunction* sourceFiles(root: string, diagnostics: ArchitectureDiagnostic[]): Generator<string> {\n\tconst allowed = new Set([\n\t\t'_generated',\n\t\t'__tests__',\n\t\t'api',\n\t\t'domain',\n\t\t'application',\n\t\t'migrations',\n\t\t'components',\n\t])\n\tfunction* scan(directory: string): Generator<string> {\n\t\tfor (const entry of readdirSync(directory, { withFileTypes: true }).sort((a, b) =>\n\t\t\ta.name.localeCompare(b.name),\n\t\t)) {\n\t\t\tconst path = resolve(directory, entry.name)\n\t\t\tconst file = relative(root, path).split(sep).join('/')\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tcode: 'symlink',\n\t\t\t\t\tfile,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'Keep application source inside its owning directory; symlinked files and folders are not allowed.',\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (directory === root && !allowed.has(entry.name))\n\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\tcode: 'root-directory',\n\t\t\t\t\t\tfile,\n\t\t\t\t\t\tmessage: `Root folder ${entry.name}/ is not allowed. Use api/, domain/, application/, migrations/, components/, __tests__/, or _generated/.`,\n\t\t\t\t\t})\n\t\t\t\tif (\n\t\t\t\t\tentry.name !== '_generated' &&\n\t\t\t\t\tentry.name !== 'node_modules' &&\n\t\t\t\t\t!entry.name.startsWith('.')\n\t\t\t\t)\n\t\t\t\t\tyield* scan(path)\n\t\t\t} else if (/\\.[cm]?[jt]sx?$/.test(entry.name) && !/\\.d\\.[cm]?ts$/.test(entry.name)) yield file\n\t\t}\n\t}\n\tyield* scan(root)\n}\n\nfunction testFile(file: string) {\n\treturn /\\.(?:test|spec)\\.[cm]?[jt]sx?$/.test(file)\n}\n\nfunction executable(program: Program) {\n\treturn program.body.some((statement) => {\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration && 'declare' in declaration && declaration.declare) return false\n\t\tif (statement.type === 'ImportDeclaration' || statement.type === 'EmptyStatement') return false\n\t\tif (statement.type === 'ExportNamedDeclaration') {\n\t\t\tif (statement.exportKind === 'type' || !statement.declaration) return false\n\t\t\treturn !['TSInterfaceDeclaration', 'TSTypeAliasDeclaration', 'TSDeclareFunction'].includes(\n\t\t\t\tstatement.declaration.type,\n\t\t\t)\n\t\t}\n\t\treturn ![\n\t\t\t'TSInterfaceDeclaration',\n\t\t\t'TSTypeAliasDeclaration',\n\t\t\t'TSDeclareFunction',\n\t\t\t'ExportAllDeclaration',\n\t\t].includes(statement.type)\n\t})\n}\n\nfunction hasRunnableTest(program: Program) {\n\tconst names = new Map([\n\t\t['test', 'test'],\n\t\t['it', 'it'],\n\t\t['describe', 'describe'],\n\t\t['suite', 'suite'],\n\t])\n\tfor (const statement of program.body) {\n\t\tconst declaration =\n\t\t\tstatement.type === 'ExportNamedDeclaration' ? statement.declaration : statement\n\t\tif (declaration?.type === 'FunctionDeclaration' && declaration.id)\n\t\t\tnames.delete(declaration.id.name)\n\t\tif (declaration?.type === 'VariableDeclaration')\n\t\t\tfor (const item of declaration.declarations) {\n\t\t\t\tif (item.id.type === 'Identifier') names.delete(item.id.name)\n\t\t\t}\n\t\tif (statement.type !== 'ImportDeclaration') continue\n\t\tfor (const specifier of statement.specifiers) {\n\t\t\tnames.delete(specifier.local.name)\n\t\t\tif (\n\t\t\t\t!['vitest', 'vite-plus/test', 'bun:test', 'node:test', '@jest/globals'].includes(\n\t\t\t\t\tstatement.source.value,\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tcontinue\n\t\t\tif (specifier.type === 'ImportNamespaceSpecifier') names.set(specifier.local.name, '*')\n\t\t\telse if (specifier.type === 'ImportDefaultSpecifier') names.set(specifier.local.name, 'test')\n\t\t\telse if (specifier.imported.type === 'Identifier')\n\t\t\t\tnames.set(specifier.local.name, specifier.imported.name)\n\t\t}\n\t}\n\tconst calls: CallExpression[] = []\n\tnew Visitor({\n\t\tCallExpression(node) {\n\t\t\tcalls.push(node)\n\t\t},\n\t}).visit(program)\n\tconst skipped = calls.filter((node) => {\n\t\tconst parts = testCallee(node.callee, names)\n\t\treturn (\n\t\t\t['test', 'it', 'describe', 'suite'].includes(parts[0]) &&\n\t\t\t(parts.some((part) => ['skip', 'todo', 'skipIf', 'runIf'].includes(part)) ||\n\t\t\t\tnode.arguments.some(\n\t\t\t\t\t(argument) =>\n\t\t\t\t\t\targument.type === 'ObjectExpression' &&\n\t\t\t\t\t\targument.properties.some(\n\t\t\t\t\t\t\t(property) =>\n\t\t\t\t\t\t\t\tproperty.type === 'Property' &&\n\t\t\t\t\t\t\t\t['skip', 'todo'].includes(\n\t\t\t\t\t\t\t\t\tproperty.key.type === 'Identifier'\n\t\t\t\t\t\t\t\t\t\t? property.key.name\n\t\t\t\t\t\t\t\t\t\t: property.key.type === 'Literal'\n\t\t\t\t\t\t\t\t\t\t\t? String(property.key.value)\n\t\t\t\t\t\t\t\t\t\t\t: '',\n\t\t\t\t\t\t\t\t) &&\n\t\t\t\t\t\t\t\t!(property.value.type === 'Literal' && property.value.value === false),\n\t\t\t\t\t\t),\n\t\t\t\t))\n\t\t)\n\t})\n\treturn calls.some((node) => {\n\t\tconst parts = testCallee(node.callee, names)\n\t\tif (\n\t\t\t!['test', 'it'].includes(parts[0]) ||\n\t\t\tskipped.some((skip) => node.start >= skip.start && node.end <= skip.end)\n\t\t)\n\t\t\treturn false\n\t\t// each(...) is a factory; only the outer call has the test callback.\n\t\treturn node.arguments.some(\n\t\t\t(argument) =>\n\t\t\t\t(argument.type === 'ArrowFunctionExpression' || argument.type === 'FunctionExpression') &&\n\t\t\t\targument.body &&\n\t\t\t\t(argument.body.type !== 'BlockStatement' ||\n\t\t\t\t\targument.body.body.some((statement) => statement.type !== 'EmptyStatement')),\n\t\t)\n\t})\n}\n\nfunction testCallee(node: Node, names: Map<string, string>): string[] {\n\tif (node.type === 'Identifier') {\n\t\tconst name = names.get(node.name)\n\t\treturn name ? [name] : []\n\t}\n\tif (node.type === 'CallExpression') return testCallee(node.callee, names)\n\tif (node.type === 'MemberExpression') {\n\t\tconst base = testCallee(node.object, names)\n\t\tconst property =\n\t\t\t!node.computed && node.property.type === 'Identifier'\n\t\t\t\t? node.property.name\n\t\t\t\t: node.property.type === 'Literal'\n\t\t\t\t\t? String(node.property.value)\n\t\t\t\t\t: ''\n\t\tif (!base.length || !property) return []\n\t\treturn base[0] === '*' ? [property] : [...base, property]\n\t}\n\treturn []\n}\n\nfunction runtimeImports(program: Program) {\n\tconst imports: string[] = []\n\tnew Visitor({\n\t\tImportDeclaration(node) {\n\t\t\tif (\n\t\t\t\tnode.importKind !== 'type' &&\n\t\t\t\t(node.specifiers.length === 0 ||\n\t\t\t\t\tnode.specifiers.some((s) => s.type !== 'ImportSpecifier' || s.importKind !== 'type'))\n\t\t\t)\n\t\t\t\timports.push(node.source.value)\n\t\t},\n\t\tExportNamedDeclaration(node) {\n\t\t\tif (\n\t\t\t\tnode.source &&\n\t\t\t\tnode.exportKind !== 'type' &&\n\t\t\t\tnode.specifiers.some((specifier) => specifier.exportKind !== 'type')\n\t\t\t)\n\t\t\t\timports.push(node.source.value)\n\t\t},\n\t\tExportAllDeclaration(node) {\n\t\t\tif (node.exportKind !== 'type') imports.push(node.source.value)\n\t\t},\n\t\tImportExpression(node) {\n\t\t\tif (node.source.type === 'Literal' && String(node.source.value) === node.source.value)\n\t\t\t\timports.push(String(node.source.value))\n\t\t},\n\t}).visit(program)\n\treturn imports\n}\n\nfunction moduleOwner(file: string) {\n\tconst parts = file.split('/')\n\treturn parts[0] === 'domain' && parts.length >= 3 && parts[1] !== '__tests__'\n\t\t? `domain/${parts[1]}`\n\t\t: null\n}\n\nfunction cycles(graph: Map<string, Set<string>>) {\n\tconst completed = new Set<string>()\n\tconst stack: string[] = []\n\tconst found: string[][] = []\n\tfunction visit(owner: string) {\n\t\tconst index = stack.indexOf(owner)\n\t\tif (index >= 0) {\n\t\t\tfound.push([...stack.slice(index), owner])\n\t\t\treturn\n\t\t}\n\t\tif (completed.has(owner)) return\n\t\tstack.push(owner)\n\t\tfor (const dependency of graph.get(owner) ?? []) visit(dependency)\n\t\tstack.pop()\n\t\tcompleted.add(owner)\n\t}\n\tfor (const owner of graph.keys()) visit(owner)\n\treturn found\n}\n\nfunction sharedOwnership(dependencies: Map<string, Set<string>>): ArchitectureDiagnostic[] {\n\tconst consumers = new Map<string, Set<string>>()\n\tfor (const [file, targets] of dependencies) {\n\t\tconst owner = moduleOwner(file) ?? ''\n\t\tif (!owner || owner === 'domain/shared') continue\n\t\tconst visited = new Set<string>()\n\t\tfunction visit(target: string) {\n\t\t\tif (!target.startsWith('domain/shared/') || visited.has(target)) return\n\t\t\tvisited.add(target)\n\t\t\tconst owners = consumers.get(target) ?? new Set<string>()\n\t\t\towners.add(owner)\n\t\t\tconsumers.set(target, owners)\n\t\t\tfor (const next of dependencies.get(target) ?? []) visit(next)\n\t\t}\n\t\tfor (const target of targets) visit(target)\n\t}\n\tconst diagnostics: ArchitectureDiagnostic[] = []\n\tfor (const [file, owners] of consumers) {\n\t\tif (owners.size === 1)\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'shared-owner',\n\t\t\t\tfile,\n\t\t\t\tmessage: `This shared implementation is used only by ${[...owners][0]}. Move it into that module until another module needs it.`,\n\t\t\t})\n\t}\n\treturn diagnostics\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Context, ESTree, RuleMeta, Visitor } from "@oxlint/plugins";
|
|
3
|
+
//#region src/oxlint/ast.d.ts
|
|
4
|
+
declare const consumerOptions: z.ZodObject<{
|
|
5
|
+
convexDir: z.ZodDefault<z.ZodString>;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
declare function appFile(context: Context, filename?: string): string | null;
|
|
8
|
+
declare function imported(context: Context, node: ESTree.Node): {
|
|
9
|
+
source: string;
|
|
10
|
+
name: string;
|
|
11
|
+
} | null;
|
|
12
|
+
declare function sourceVisitors(context: Context, check: (node: ESTree.Node, source: string) => void): Visitor;
|
|
13
|
+
declare function isFunctionsImport(context: Context, source: string): boolean;
|
|
14
|
+
declare function typeOnlySource(node: ESTree.Node): boolean;
|
|
15
|
+
declare function isDbAccess(node: ESTree.CallExpression): boolean;
|
|
16
|
+
declare function isExternalCall(context: Context, node: ESTree.CallExpression): boolean;
|
|
17
|
+
declare function containsComponentReference(context: Context, node: ESTree.Node): boolean;
|
|
18
|
+
declare function rootMember(node: ESTree.Node): ESTree.Node;
|
|
19
|
+
declare function memberPath(node: ESTree.Node): string[];
|
|
20
|
+
declare function isTableChain(node: ESTree.Node): boolean;
|
|
21
|
+
declare function isDbWrite(node: ESTree.CallExpression): boolean;
|
|
22
|
+
declare function hasCall(node: ESTree.Node, name: string): boolean;
|
|
23
|
+
declare function metadata(description: string, messages: Record<string, string>): RuleMeta;
|
|
24
|
+
declare function componentRoot(context: Context, filename: string): string | null;
|
|
25
|
+
declare function staticString(node: ESTree.Node | null | undefined): string | null;
|
|
26
|
+
declare function propertyName(node: ESTree.Node): string | null;
|
|
27
|
+
declare function binding(context: Context, node: ESTree.Node): import("@oxlint/plugins").Variable | null;
|
|
28
|
+
declare function exportedNames(program: ESTree.Program): Set<string>;
|
|
29
|
+
declare function exportName(node: ESTree.Node): string | null;
|
|
30
|
+
declare function delegatingBody(node: ESTree.Node): boolean;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { appFile, binding, componentRoot, consumerOptions, containsComponentReference, delegatingBody, exportName, exportedNames, hasCall, imported, isDbAccess, isDbWrite, isExternalCall, isFunctionsImport, isTableChain, memberPath, metadata, propertyName, rootMember, sourceVisitors, staticString, typeOnlySource };
|
|
33
|
+
//# sourceMappingURL=ast.d.mts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createResolver as e,resolveImport as t}from"./architecture.mjs";import{z as n}from"zod";import{dirname as r,relative as i,resolve as a,sep as o}from"node:path";import{existsSync as s,realpathSync as c}from"node:fs";const l=n.object({convexDir:n.string().min(1).default(`convex`)});function u(e,t=e.filename){let n=a(e.cwd,l.parse(e.options[0]??{}).convexDir),r=s(n)?c(n):n,u=i(r,s(t)?c(t):t).split(o).join(`/`);return u===`..`||u.startsWith(`../`)||u.startsWith(`/`)?null:u}function d(e,t){if(t.type===`CallExpression`)return d(e,t.callee);if(t.type===`MemberExpression`){let n=d(e,t.object),r=E(t);return n&&r&&[`*`,`z`,`default`].includes(n.name)?{source:n.source,name:r}:null}if(t.type!==`Identifier`)return null;for(let n of D(e,t)?.defs??[]){if(n.type!==`ImportBinding`||n.parent?.type!==`ImportDeclaration`||n.parent.importKind===`type`)continue;let e=n.node;if(e.type!==`ImportSpecifier`||e.importKind!==`type`)return{source:n.parent.source.value,name:e.type===`ImportSpecifier`?k(e.imported)??``:e.type===`ImportDefaultSpecifier`?`default`:`*`}}return null}function f(e,t){function n(e,n){let r=T(n);r&&t(e,r)}return{ImportDeclaration(e){n(e,e.source)},ExportNamedDeclaration(e){n(e,e.source)},ExportAllDeclaration(e){n(e,e.source)},ImportExpression(e){n(e,e.source)},TSImportType(e){n(e,e.source)},CallExpression(t){t.callee.type===`Identifier`&&t.callee.name===`require`&&!D(e,t.callee)?.defs.length&&n(t,t.arguments[0])}}}function p(n,i){let o=i.startsWith(`.`)?a(r(n.filename),i):t(e(),n.filename,i);return o!==null&&u(n,o)?.replace(/\.[cm]?[jt]s$/,``)===`functions`}function m(e){return e.type===`TSImportType`||e.type===`ImportDeclaration`&&(e.importKind===`type`||e.specifiers.length>0&&e.specifiers.every(e=>e.type===`ImportSpecifier`&&e.importKind===`type`))||(e.type===`ExportNamedDeclaration`||e.type===`ExportAllDeclaration`)&&e.exportKind===`type`}function h(e){return e.callee.type===`MemberExpression`&&e.callee.object.type===`MemberExpression`&&E(e.callee.object)===`db`}function g(e,t){let n=d(e,t.callee);return n&&/^(?:node:)?(?:https?|net|tls|fs)(?:\/|$)|^(?:undici|axios)(?:\/|$)/.test(n.source)?!0:t.callee.type===`Identifier`&&t.callee.name===`fetch`&&!D(e,t.callee)?.defs.length||t.callee.type===`MemberExpression`&&E(t.callee)===`fetch`&&t.callee.object.type===`Identifier`&&t.callee.object.name===`globalThis`&&!D(e,t.callee.object)?.defs.length}function _(e,t){if(t.type===`MemberExpression`){let n=d(e,t.object);return n?.name===`components`&&/_generated\/api/.test(n.source)?!0:_(e,t.object)}return t.type===`ObjectExpression`&&t.properties.some(t=>t.type===`Property`&&_(e,t.value))}function v(e){return e.type===`MemberExpression`?v(e.object):e}function y(e){return e.type===`Identifier`?[e.name]:e.type===`MemberExpression`?[...y(e.object),E(e)??``]:[]}function b(e){return e.type===`MemberExpression`?E(e)===`table`||b(e.object):e.type===`CallExpression`&&b(e.callee)}function x(e){return e.callee.type===`MemberExpression`&&[`insert`,`patch`,`replace`,`delete`].includes(E(e.callee)??``)&&e.callee.object.type===`MemberExpression`&&E(e.callee.object)===`db`}function S(e,t){return e.type===`CallExpression`?e.callee.type===`MemberExpression`&&E(e.callee)===t&&(t!==`query`||E(e.callee.object)===`db`)||S(e.callee,t):e.type===`MemberExpression`&&S(e.object,t)}function C(e,t){return{type:`problem`,docs:{description:e},schema:[],messages:t}}function w(e,t){let n=a(e.cwd,l.parse(e.options[0]??{}).convexDir),r=s(n)?c(n):n,u=i(r,s(t)?c(t):t).split(o).join(`/`).match(/^components\/([^/]+)(?:\/|$)/);return u?a(r,`components`,u[1]):null}function T(e){return e?.type===`Literal`&&`value`in e&&String(e.value)===e.value?String(e.value):e?.type===`TemplateLiteral`&&e.expressions.length===0?e.quasis[0].value.cooked:null}function E(e){return e.type===`MemberExpression`?e.computed?T(e.property):e.property.name:null}function D(e,t){if(t.type!==`Identifier`)return null;let n=e.sourceCode.getScope(t);for(;n;){let e=n.set.get(t.name);if(e)return e;n=n.upper}return null}function O(e){let t=new Set;for(let n of e.body)if(n.type===`ExportNamedDeclaration`&&!n.source)for(let e of n.specifiers)t.add(k(e.local)??``);else n.type===`ExportDefaultDeclaration`&&n.declaration.type===`Identifier`&&t.add(n.declaration.name);return t}function k(e){return e.type===`Identifier`?e.name:T(e)}function A(e){return e.type===`CallExpression`?!0:e.type===`AwaitExpression`?A(e.argument):e.type===`BlockStatement`&&e.body.length>0&&e.body.every(e=>e.type===`ReturnStatement`&&e.argument!==null&&A(e.argument)||e.type===`ExpressionStatement`&&A(e.expression))}export{u as appFile,D as binding,w as componentRoot,l as consumerOptions,_ as containsComponentReference,A as delegatingBody,k as exportName,O as exportedNames,S as hasCall,d as imported,h as isDbAccess,x as isDbWrite,g as isExternalCall,p as isFunctionsImport,b as isTableChain,y as memberPath,C as metadata,E as propertyName,v as rootMember,f as sourceVisitors,T as staticString,m as typeOnlySource};
|
|
2
|
+
//# sourceMappingURL=ast.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.mjs","names":[],"sources":["../../src/oxlint/ast.ts"],"sourcesContent":["import { existsSync, realpathSync } from 'node:fs'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport type { Context, ESTree, RuleMeta, Scope, Visitor } from '@oxlint/plugins'\nimport { z } from 'zod'\nimport { createResolver, resolveImport } from './architecture'\n\nexport const consumerOptions = z.object({ convexDir: z.string().min(1).default('convex') })\n\nexport function appFile(context: Context, filename = context.filename) {\n\tconst requestedRoot = resolve(\n\t\tcontext.cwd,\n\t\tconsumerOptions.parse(context.options[0] ?? {}).convexDir,\n\t)\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst file = relative(root, existsSync(filename) ? realpathSync(filename) : filename)\n\t\t.split(sep)\n\t\t.join('/')\n\treturn file === '..' || file.startsWith('../') || file.startsWith('/') ? null : file\n}\n\nexport function imported(\n\tcontext: Context,\n\tnode: ESTree.Node,\n): { source: string; name: string } | null {\n\tif (node.type === 'CallExpression') return imported(context, node.callee)\n\tif (node.type === 'MemberExpression') {\n\t\tconst owner = imported(context, node.object)\n\t\tconst name = propertyName(node)\n\t\treturn owner && name && ['*', 'z', 'default'].includes(owner.name)\n\t\t\t? { source: owner.source, name }\n\t\t\t: null\n\t}\n\tif (node.type !== 'Identifier') return null\n\tfor (const def of binding(context, node)?.defs ?? []) {\n\t\tif (\n\t\t\tdef.type !== 'ImportBinding' ||\n\t\t\tdef.parent?.type !== 'ImportDeclaration' ||\n\t\t\tdef.parent.importKind === 'type'\n\t\t)\n\t\t\tcontinue\n\t\tconst specifier = def.node\n\t\tif (specifier.type === 'ImportSpecifier' && specifier.importKind === 'type') continue\n\t\treturn {\n\t\t\tsource: def.parent.source.value,\n\t\t\tname:\n\t\t\t\tspecifier.type === 'ImportSpecifier'\n\t\t\t\t\t? (exportName(specifier.imported) ?? '')\n\t\t\t\t\t: specifier.type === 'ImportDefaultSpecifier'\n\t\t\t\t\t\t? 'default'\n\t\t\t\t\t\t: '*',\n\t\t}\n\t}\n\treturn null\n}\n\nexport function sourceVisitors(\n\tcontext: Context,\n\tcheck: (node: ESTree.Node, source: string) => void,\n): Visitor {\n\tfunction visit(node: ESTree.Node, source: ESTree.Node | null | undefined) {\n\t\tconst text = staticString(source)\n\t\tif (text) check(node, text)\n\t}\n\treturn {\n\t\tImportDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tExportNamedDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tExportAllDeclaration(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tImportExpression(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tTSImportType(node) {\n\t\t\tvisit(node, node.source)\n\t\t},\n\t\tCallExpression(node) {\n\t\t\tif (\n\t\t\t\tnode.callee.type === 'Identifier' &&\n\t\t\t\tnode.callee.name === 'require' &&\n\t\t\t\t!binding(context, node.callee)?.defs.length\n\t\t\t)\n\t\t\t\tvisit(node, node.arguments[0])\n\t\t},\n\t}\n}\n\nexport function isFunctionsImport(context: Context, source: string) {\n\tconst target = source.startsWith('.')\n\t\t? resolve(dirname(context.filename), source)\n\t\t: resolveImport(createResolver(), context.filename, source)\n\treturn target !== null && appFile(context, target)?.replace(/\\.[cm]?[jt]s$/, '') === 'functions'\n}\n\nexport function typeOnlySource(node: ESTree.Node) {\n\treturn (\n\t\tnode.type === 'TSImportType' ||\n\t\t(node.type === 'ImportDeclaration' &&\n\t\t\t(node.importKind === 'type' ||\n\t\t\t\t(node.specifiers.length > 0 &&\n\t\t\t\t\tnode.specifiers.every(\n\t\t\t\t\t\t(specifier) => specifier.type === 'ImportSpecifier' && specifier.importKind === 'type',\n\t\t\t\t\t)))) ||\n\t\t((node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') &&\n\t\t\tnode.exportKind === 'type')\n\t)\n}\n\nexport function isDbAccess(node: ESTree.CallExpression) {\n\treturn (\n\t\tnode.callee.type === 'MemberExpression' &&\n\t\tnode.callee.object.type === 'MemberExpression' &&\n\t\tpropertyName(node.callee.object) === 'db'\n\t)\n}\n\nexport function isExternalCall(context: Context, node: ESTree.CallExpression) {\n\tconst ref = imported(context, node.callee)\n\tif (ref && /^(?:node:)?(?:https?|net|tls|fs)(?:\\/|$)|^(?:undici|axios)(?:\\/|$)/.test(ref.source))\n\t\treturn true\n\treturn (\n\t\t(node.callee.type === 'Identifier' &&\n\t\t\tnode.callee.name === 'fetch' &&\n\t\t\t!binding(context, node.callee)?.defs.length) ||\n\t\t(node.callee.type === 'MemberExpression' &&\n\t\t\tpropertyName(node.callee) === 'fetch' &&\n\t\t\tnode.callee.object.type === 'Identifier' &&\n\t\t\tnode.callee.object.name === 'globalThis' &&\n\t\t\t!binding(context, node.callee.object)?.defs.length)\n\t)\n}\n\nexport function containsComponentReference(context: Context, node: ESTree.Node): boolean {\n\tif (node.type === 'MemberExpression') {\n\t\tconst owner = imported(context, node.object)\n\t\tif (owner?.name === 'components' && /_generated\\/api/.test(owner.source)) return true\n\t\treturn containsComponentReference(context, node.object)\n\t}\n\tif (node.type === 'ObjectExpression')\n\t\treturn node.properties.some(\n\t\t\t(property) =>\n\t\t\t\tproperty.type === 'Property' && containsComponentReference(context, property.value),\n\t\t)\n\treturn false\n}\n\nexport function rootMember(node: ESTree.Node): ESTree.Node {\n\treturn node.type === 'MemberExpression' ? rootMember(node.object) : node\n}\n\nexport function memberPath(node: ESTree.Node): string[] {\n\tif (node.type === 'Identifier') return [node.name]\n\tif (node.type === 'MemberExpression')\n\t\treturn [...memberPath(node.object), propertyName(node) ?? '']\n\treturn []\n}\n\nexport function isTableChain(node: ESTree.Node): boolean {\n\tif (node.type === 'MemberExpression')\n\t\treturn propertyName(node) === 'table' || isTableChain(node.object)\n\treturn node.type === 'CallExpression' && isTableChain(node.callee)\n}\n\nexport function isDbWrite(node: ESTree.CallExpression) {\n\treturn (\n\t\tnode.callee.type === 'MemberExpression' &&\n\t\t['insert', 'patch', 'replace', 'delete'].includes(propertyName(node.callee) ?? '') &&\n\t\tnode.callee.object.type === 'MemberExpression' &&\n\t\tpropertyName(node.callee.object) === 'db'\n\t)\n}\n\nexport function hasCall(node: ESTree.Node, name: string): boolean {\n\tif (node.type === 'CallExpression')\n\t\treturn (\n\t\t\t(node.callee.type === 'MemberExpression' &&\n\t\t\t\tpropertyName(node.callee) === name &&\n\t\t\t\t(name !== 'query' || propertyName(node.callee.object) === 'db')) ||\n\t\t\thasCall(node.callee, name)\n\t\t)\n\tif (node.type === 'MemberExpression') return hasCall(node.object, name)\n\treturn false\n}\n\nexport function metadata(description: string, messages: Record<string, string>): RuleMeta {\n\treturn { type: 'problem', docs: { description }, schema: [], messages }\n}\n\nexport function componentRoot(context: Context, filename: string) {\n\tconst requestedRoot = resolve(\n\t\tcontext.cwd,\n\t\tconsumerOptions.parse(context.options[0] ?? {}).convexDir,\n\t)\n\tconst root = existsSync(requestedRoot) ? realpathSync(requestedRoot) : requestedRoot\n\tconst file = relative(root, existsSync(filename) ? realpathSync(filename) : filename)\n\t\t.split(sep)\n\t\t.join('/')\n\tconst match = file.match(/^components\\/([^/]+)(?:\\/|$)/)\n\treturn match ? resolve(root, 'components', match[1]) : null\n}\n\nexport function staticString(node: ESTree.Node | null | undefined) {\n\tif (node?.type === 'Literal' && 'value' in node && String(node.value) === node.value)\n\t\treturn String(node.value)\n\tif (node?.type === 'TemplateLiteral' && node.expressions.length === 0)\n\t\treturn node.quasis[0].value.cooked\n\treturn null\n}\n\nexport function propertyName(node: ESTree.Node): string | null {\n\tif (node.type !== 'MemberExpression') return null\n\treturn node.computed ? staticString(node.property) : node.property.name\n}\n\nexport function binding(context: Context, node: ESTree.Node) {\n\tif (node.type !== 'Identifier') return null\n\tlet scope: Scope | null = context.sourceCode.getScope(node)\n\twhile (scope) {\n\t\tconst variable = scope.set.get(node.name)\n\t\tif (variable) return variable\n\t\tscope = scope.upper\n\t}\n\treturn null\n}\n\nexport function exportedNames(program: ESTree.Program) {\n\tconst names = new Set<string>()\n\tfor (const statement of program.body) {\n\t\tif (statement.type === 'ExportNamedDeclaration' && !statement.source) {\n\t\t\tfor (const specifier of statement.specifiers) names.add(exportName(specifier.local) ?? '')\n\t\t} else if (\n\t\t\tstatement.type === 'ExportDefaultDeclaration' &&\n\t\t\tstatement.declaration.type === 'Identifier'\n\t\t) {\n\t\t\tnames.add(statement.declaration.name)\n\t\t}\n\t}\n\treturn names\n}\n\nexport function exportName(node: ESTree.Node): string | null {\n\treturn node.type === 'Identifier' ? node.name : staticString(node)\n}\n\nexport function delegatingBody(node: ESTree.Node): boolean {\n\tif (node.type === 'CallExpression') return true\n\tif (node.type === 'AwaitExpression') return delegatingBody(node.argument)\n\tif (node.type === 'BlockStatement')\n\t\treturn (\n\t\t\tnode.body.length > 0 &&\n\t\t\tnode.body.every(\n\t\t\t\t(statement) =>\n\t\t\t\t\t(statement.type === 'ReturnStatement' &&\n\t\t\t\t\t\tstatement.argument !== null &&\n\t\t\t\t\t\tdelegatingBody(statement.argument)) ||\n\t\t\t\t\t(statement.type === 'ExpressionStatement' && delegatingBody(statement.expression)),\n\t\t\t)\n\t\t)\n\treturn false\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ESTree } from "@oxlint/plugins";
|
|
2
|
+
//#region src/oxlint/ownership.d.ts
|
|
3
|
+
declare const ownershipRules: {
|
|
4
|
+
'project-structure': {
|
|
5
|
+
meta: import("@oxlint/plugins").RuleMeta;
|
|
6
|
+
create(context: import("@oxlint/plugins").Context): {
|
|
7
|
+
Program?: undefined;
|
|
8
|
+
} | {
|
|
9
|
+
Program(node: ESTree.Program): void;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
'root-wiring-only': {
|
|
13
|
+
meta: import("@oxlint/plugins").RuleMeta;
|
|
14
|
+
create(context: import("@oxlint/plugins").Context): {
|
|
15
|
+
Program?: undefined;
|
|
16
|
+
NewExpression?: undefined;
|
|
17
|
+
CallExpression?: undefined;
|
|
18
|
+
ArrowFunctionExpression?: undefined;
|
|
19
|
+
FunctionExpression?: undefined;
|
|
20
|
+
IfStatement?: undefined;
|
|
21
|
+
SwitchStatement?: undefined;
|
|
22
|
+
ConditionalExpression?: undefined;
|
|
23
|
+
ForStatement?: undefined;
|
|
24
|
+
ForOfStatement?: undefined;
|
|
25
|
+
WhileStatement?: undefined;
|
|
26
|
+
'Program:exit'?: undefined;
|
|
27
|
+
} | {
|
|
28
|
+
Program(node: ESTree.Program): void;
|
|
29
|
+
NewExpression(node: ESTree.NewExpression): void;
|
|
30
|
+
CallExpression(node: ESTree.CallExpression): void;
|
|
31
|
+
ArrowFunctionExpression(node: ESTree.ArrowFunctionExpression): void;
|
|
32
|
+
FunctionExpression(node: ESTree.Function): void;
|
|
33
|
+
IfStatement: (node: ESTree.Node) => void;
|
|
34
|
+
SwitchStatement: (node: ESTree.Node) => void;
|
|
35
|
+
ConditionalExpression: (node: ESTree.Node) => void;
|
|
36
|
+
ForStatement: (node: ESTree.Node) => void;
|
|
37
|
+
ForOfStatement: (node: ESTree.Node) => void;
|
|
38
|
+
WhileStatement: (node: ESTree.Node) => void;
|
|
39
|
+
'Program:exit'(node: ESTree.Program): void;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
'application-orchestration': {
|
|
43
|
+
meta: import("@oxlint/plugins").RuleMeta;
|
|
44
|
+
create(context: import("@oxlint/plugins").Context): {};
|
|
45
|
+
};
|
|
46
|
+
'internal-function-ownership': {
|
|
47
|
+
meta: import("@oxlint/plugins").RuleMeta;
|
|
48
|
+
create(context: import("@oxlint/plugins").Context): {
|
|
49
|
+
CallExpression?: undefined;
|
|
50
|
+
} | {
|
|
51
|
+
CallExpression(node: ESTree.CallExpression): void;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
'domain-file-responsibilities': {
|
|
55
|
+
meta: import("@oxlint/plugins").RuleMeta;
|
|
56
|
+
create(context: import("@oxlint/plugins").Context): {};
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
type OwnershipRuleName = keyof typeof ownershipRules;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { OwnershipRuleName, ownershipRules };
|
|
62
|
+
//# sourceMappingURL=ownership.d.mts.map
|
|
@@ -0,0 +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=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};
|
|
2
|
+
//# sourceMappingURL=ownership.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership.mjs","names":[],"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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"}
|
package/dist/oxlint.d.mts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { ArchitectureDiagnostic, ArchitectureOptions } from "./oxlint/architecture.mjs";
|
|
2
|
+
import { OwnershipRuleName } from "./oxlint/ownership.mjs";
|
|
1
3
|
import { Plugin, Rule } from "@oxlint/plugins";
|
|
2
4
|
//#region src/oxlint.d.ts
|
|
3
|
-
|
|
5
|
+
declare function checkArchitecture(options?: ArchitectureOptions): ArchitectureDiagnostic[];
|
|
6
|
+
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';
|
|
4
7
|
declare const rules: Record<RuleName, Rule>;
|
|
5
8
|
declare const plugin: Plugin;
|
|
6
9
|
//#endregion
|
|
7
|
-
export { RuleName, plugin as default, rules };
|
|
10
|
+
export { type ArchitectureDiagnostic, type ArchitectureOptions, RuleName, checkArchitecture, plugin as default, rules };
|
|
8
11
|
//# sourceMappingURL=oxlint.d.mts.map
|