History

Add real protocol testing fixtures

Rhys Sullivan committed 6 months ago

Commit ac6b02a1 parent 64c2eb725 files · +702 −197Browse files

Showing the changes to scripts (2 of 25 files). Show all

Unified · Split

2 files
  1. scripts/oxlint-plugin-executor.js +2 −0
  2. scripts/oxlint-plugin-executor/rules/no-raw-fetch.js +76 −0
scripts/oxlint-plugin-executor.js+2−0
@@ -12,6 +12,7 @@ import noManualTagCheck from "./oxlint-plugin-executor/rules/no-manual-tag-check · 11 unmodified lines
12import noPromiseCatch from "./oxlint-plugin-executor/rules/no-promise-catch.js";12import noPromiseCatch from "./oxlint-plugin-executor/rules/no-promise-catch.js";
13import noPromiseClientSurface from "./oxlint-plugin-executor/rules/no-promise-client-surface.js";13import noPromiseClientSurface from "./oxlint-plugin-executor/rules/no-promise-client-surface.js";
14import noPromiseReject from "./oxlint-plugin-executor/rules/no-promise-reject.js";14import noPromiseReject from "./oxlint-plugin-executor/rules/no-promise-reject.js";
15import noRawFetch from "./oxlint-plugin-executor/rules/no-raw-fetch.js";
15import noRawErrorThrow from "./oxlint-plugin-executor/rules/no-raw-error-throw.js";16import noRawErrorThrow from "./oxlint-plugin-executor/rules/no-raw-error-throw.js";
16import noRedundantPrimitiveCast from "./oxlint-plugin-executor/rules/no-redundant-primitive-cast.js";17import noRedundantPrimitiveCast from "./oxlint-plugin-executor/rules/no-redundant-primitive-cast.js";
17import noRedundantErrorFactory from "./oxlint-plugin-executor/rules/no-redundant-error-factory.js";18import noRedundantErrorFactory from "./oxlint-plugin-executor/rules/no-redundant-error-factory.js";
@@ -48,6 +49,7 @@ export default { · 30 unmodified lines
48 "no-promise-catch": noPromiseCatch,49 "no-promise-catch": noPromiseCatch,
49 "no-promise-client-surface": noPromiseClientSurface,50 "no-promise-client-surface": noPromiseClientSurface,
50 "no-promise-reject": noPromiseReject,51 "no-promise-reject": noPromiseReject,
52 "no-raw-fetch": noRawFetch,
51 "no-raw-error-throw": noRawErrorThrow,53 "no-raw-error-throw": noRawErrorThrow,
52 "no-redundant-primitive-cast": noRedundantPrimitiveCast,54 "no-redundant-primitive-cast": noRedundantPrimitiveCast,
53 "no-redundant-error-factory": noRedundantErrorFactory,55 "no-redundant-error-factory": noRedundantErrorFactory,
scripts/oxlint-plugin-executor/rules/no-raw-fetch.js+76−0
@@ -0,0 +1,76 @@
1import {
2 getPropertyName,
3 isDeclarationFile,
4 isIdentifier,
5 toRepoRelative,
6 unwrapExpression,
7} from "../utils.js";
8
9const message =
10 "Do not call raw fetch in core/plugin code. Route HTTP through Effect HttpClient or an explicit package-local boundary. Skill: wrdn-effect-raw-fetch-boundary.";
11
12const checkedPrefixes = [
13 "packages/core/sdk/src/",
14 "packages/plugins/graphql/src/",
15 "packages/plugins/mcp/src/",
16 "packages/plugins/openapi/src/",
17];
18
19const temporaryAllowedFiles = new Set([
20 "packages/core/sdk/src/oauth-discovery.ts",
21 "packages/core/sdk/src/oauth-discovery.test.ts",
22 "packages/core/sdk/src/oauth-helpers.test.ts",
23 "packages/core/sdk/src/oauth-service.ts",
24 "packages/plugins/mcp/src/sdk/probe-shape.ts",
25 "packages/plugins/openapi/src/sdk/client-credentials-oauth.test.ts",
26 "packages/plugins/openapi/src/sdk/multi-scope-oauth.test.ts",
27 "packages/plugins/openapi/src/sdk/oauth-refresh.test.ts",
28]);
29
30const shouldCheck = (filename) => {
31 const normalized = toRepoRelative(filename);
32 if (isDeclarationFile(filename)) return false;
33 if (temporaryAllowedFiles.has(normalized)) return false;
34 return checkedPrefixes.some((prefix) => normalized.startsWith(prefix));
35};
36
37const isGlobalFetchMember = (node) => {
38 const expression = unwrapExpression(node);
39 if (expression?.type !== "MemberExpression") return false;
40 const object = unwrapExpression(expression.object);
41 const property = getPropertyName(expression.property);
42 return (
43 property === "fetch" &&
44 (isIdentifier(object, "globalThis") ||
45 isIdentifier(object, "window") ||
46 isIdentifier(object, "self"))
47 );
48};
49
50const isBareFetchCall = (node) => isIdentifier(unwrapExpression(node), "fetch");
51
52export default {
53 meta: {
54 type: "problem",
55 docs: {
56 description: "Disallow raw fetch outside approved Effect HTTP boundaries.",
57 },
58 },
59 create(context) {
60 if (!shouldCheck(context.filename)) return {};
61
62 return {
63 CallExpression(node) {
64 if (isBareFetchCall(node.callee) || isGlobalFetchMember(node.callee)) {
65 context.report({ node: node.callee, message });
66 }
67 },
68 MemberExpression(node) {
69 if (node.parent?.type === "CallExpression" && node.parent.callee === node) return;
70 if (isGlobalFetchMember(node)) {
71 context.report({ node, message });
72 }
73 },
74 };
75 },
76};