@geonosis/oxlint-plugin-biological-architecture 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +48 -5
- package/RULES.md +201 -98
- package/corpus/.oxlintrc.json +6 -0
- package/corpus/data/bad-dynamic-orm.ts +5 -0
- package/corpus/data/bad-type-only-orm.ts +3 -0
- package/corpus/e2e/bad-list-response.spec.ts +5 -0
- package/corpus/e2e/bad-timeout.spec.ts +5 -0
- package/corpus/e2e/good-detail-response.spec.ts +5 -0
- package/corpus/e2e/good-state.spec.ts +5 -0
- package/corpus/icon-controls/bad-unnamed-icon-button.tsx +8 -0
- package/corpus/icon-controls/good-named-icon-button.tsx +19 -0
- package/corpus/manifest.json +3 -0
- package/corpus/tissues/bad-awaits-data.tsx +8 -0
- package/corpus/tissues/bad-fetches-data.tsx +7 -0
- package/corpus/tissues/good-takes-products.tsx +5 -0
- package/dist/discover-atoms.d.ts +2 -37
- package/dist/discover-atoms.js +1 -104
- package/dist/index.d.ts +3 -12
- package/dist/index.js +19 -174
- package/dist/presets.d.ts +11 -19
- package/dist/presets.js +89 -3
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +172 -0
- package/dist/rules/atom-no-deps.d.ts +1 -0
- package/dist/rules/atom-no-deps.js +10 -11
- package/dist/rules/boundary-time-is-primitive.d.ts +0 -7
- package/dist/rules/cell-must-be-stateful.d.ts +2 -2
- package/dist/rules/cell-must-be-stateful.js +24 -23
- package/dist/rules/cell-must-not-compose-cell.d.ts +1 -0
- package/dist/rules/cell-must-not-compose-cell.js +10 -3
- package/dist/rules/cell-no-cross-feature-organelles.d.ts +1 -0
- package/dist/rules/cell-no-cross-feature-organelles.js +7 -0
- package/dist/rules/cell-no-tissues.d.ts +1 -0
- package/dist/rules/cell-no-tissues.js +11 -7
- package/dist/rules/cells-folder-index-is-barrel.d.ts +12 -10
- package/dist/rules/cells-folder-index-is-barrel.js +66 -34
- package/dist/rules/compound-must-be-stateless.d.ts +2 -0
- package/dist/rules/compound-must-be-stateless.js +24 -26
- package/dist/rules/compound-no-stores.d.ts +1 -0
- package/dist/rules/compound-no-stores.js +12 -10
- package/dist/rules/constants-in-constants-file.d.ts +2 -8
- package/dist/rules/constants-in-constants-file.js +5 -6
- package/dist/rules/dialect-through-the-seam.d.ts +0 -13
- package/dist/rules/durable-body-reads-through-steps.d.ts +0 -14
- package/dist/rules/durable-body-reads-through-steps.js +8 -3
- package/dist/rules/effect-hook-naming.d.ts +9 -11
- package/dist/rules/effect-hook-naming.js +33 -31
- package/dist/rules/emit-declares-attempts.d.ts +0 -17
- package/dist/rules/emit-declares-attempts.js +5 -10
- package/dist/rules/font-roles-only.d.ts +0 -18
- package/dist/rules/font-roles-only.js +19 -22
- package/dist/rules/hermetic-e2e-no-wall-clock-waits.d.ts +53 -0
- package/dist/rules/hermetic-e2e-no-wall-clock-waits.js +100 -0
- package/dist/rules/icon-control-has-name.d.ts +53 -0
- package/dist/rules/icon-control-has-name.js +71 -0
- package/dist/rules/layer-walls.d.ts +0 -25
- package/dist/rules/layer-walls.js +7 -13
- package/dist/rules/lib/atom-map.d.ts +24 -0
- package/dist/rules/lib/atom-map.js +16 -0
- package/dist/rules/lib/cells-barrel.d.ts +0 -1
- package/dist/rules/lib/colors.d.ts +0 -19
- package/dist/rules/lib/colors.js +10 -243
- package/dist/rules/lib/comments.d.ts +19 -0
- package/dist/rules/lib/comments.js +5 -0
- package/dist/rules/lib/context.d.ts +0 -10
- package/dist/rules/lib/direction-rule.d.ts +3 -21
- package/dist/rules/lib/direction-rule.js +12 -3
- package/dist/rules/lib/doors.d.ts +2 -18
- package/dist/rules/lib/doors.js +79 -41
- package/dist/rules/lib/hooks.d.ts +2 -17
- package/dist/rules/lib/hooks.js +14 -9
- package/dist/rules/lib/imports.d.ts +2 -23
- package/dist/rules/lib/imports.js +7 -2
- package/dist/rules/lib/jsx.d.ts +31 -0
- package/dist/rules/lib/jsx.js +11 -0
- package/dist/rules/lib/landing.d.ts +0 -40
- package/dist/rules/lib/literal-call.d.ts +1 -0
- package/dist/rules/lib/literal-call.js +2 -0
- package/dist/rules/lib/module-text.d.ts +3 -27
- package/dist/rules/lib/module-text.js +19 -4
- package/dist/rules/lib/mutations.d.ts +0 -14
- package/dist/rules/lib/nodes.d.ts +1 -18
- package/dist/rules/lib/nodes.js +1 -0
- package/dist/rules/lib/objects.d.ts +2 -11
- package/dist/rules/lib/objects.js +21 -0
- package/dist/rules/lib/options.d.ts +2 -52
- package/dist/rules/lib/options.js +44 -18
- package/dist/rules/lib/package-imports.d.ts +0 -5
- package/dist/rules/lib/package-imports.js +4 -10
- package/dist/rules/lib/paths.d.ts +15 -41
- package/dist/rules/lib/paths.js +34 -1
- package/dist/rules/lib/pattern-match.d.ts +2 -12
- package/dist/rules/lib/pattern-match.js +5 -1
- package/dist/rules/lib/probe.d.ts +0 -43
- package/dist/rules/lib/reexports.d.ts +0 -18
- package/dist/rules/lib/render-tracking.d.ts +0 -8
- package/dist/rules/lib/shared-features.d.ts +0 -8
- package/dist/rules/lib/shared-features.js +2 -9
- package/dist/rules/lib/state-sources.d.ts +8 -0
- package/dist/rules/lib/state-sources.js +55 -0
- package/dist/rules/lib/steps.d.ts +3 -5
- package/dist/rules/lib/steps.js +6 -1
- package/dist/rules/lib/styling.d.ts +9 -42
- package/dist/rules/lib/styling.js +36 -10
- package/dist/rules/lib/tiers.d.ts +11 -24
- package/dist/rules/lib/tiers.js +41 -1
- package/dist/rules/lib/tissue-entrypoint.d.ts +0 -1
- package/dist/rules/lib/tissue-entrypoint.js +4 -5
- package/dist/rules/lib/tsconfig-paths.d.ts +0 -4
- package/dist/rules/lib/tsconfig-paths.js +47 -15
- package/dist/rules/lib/type-members.d.ts +6 -0
- package/dist/rules/lib/type-members.js +165 -0
- package/dist/rules/lib/visitors.d.ts +0 -22
- package/dist/rules/lib/workspace-members.d.ts +2 -0
- package/dist/rules/lib/workspace-members.js +115 -0
- package/dist/rules/list-take-without-order.js +2 -8
- package/dist/rules/max-comment-density.d.ts +3 -18
- package/dist/rules/max-comment-density.js +3 -3
- package/dist/rules/molecule-atoms-only.d.ts +1 -0
- package/dist/rules/molecule-atoms-only.js +11 -7
- package/dist/rules/molecule-must-compose.d.ts +3 -1
- package/dist/rules/molecule-must-compose.js +17 -21
- package/dist/rules/mutating-step-declares-retry.d.ts +2 -7
- package/dist/rules/mutating-step-declares-retry.js +29 -11
- package/dist/rules/named-when-block.d.ts +0 -2
- package/dist/rules/named-when-block.js +2 -8
- package/dist/rules/next-route-segment-is-thin-delegate.d.ts +4 -19
- package/dist/rules/next-route-segment-is-thin-delegate.js +47 -71
- package/dist/rules/no-brand-names.d.ts +0 -9
- package/dist/rules/no-brand-names.js +1 -1
- package/dist/rules/no-card-shaped-div.d.ts +4 -42
- package/dist/rules/no-card-shaped-div.js +12 -4
- package/dist/rules/no-cross-feature-stores.d.ts +1 -0
- package/dist/rules/no-cross-feature-stores.js +9 -5
- package/dist/rules/no-d1-transaction.d.ts +2 -5
- package/dist/rules/no-d1-transaction.js +7 -0
- package/dist/rules/no-date-string-compare.d.ts +2 -0
- package/dist/rules/no-date-string-compare.js +14 -8
- package/dist/rules/no-duplicate-jsx-patterns.d.ts +2 -0
- package/dist/rules/no-duplicate-jsx-patterns.js +16 -1
- package/dist/rules/no-generic-utility-package.d.ts +48 -2
- package/dist/rules/no-generic-utility-package.js +48 -9
- package/dist/rules/no-hook-in-component-disguise.d.ts +27 -13
- package/dist/rules/no-hook-in-component-disguise.js +38 -30
- package/dist/rules/no-index-count-as-exact.d.ts +0 -3
- package/dist/rules/no-inert-hidden-jsx.d.ts +4 -21
- package/dist/rules/no-inert-hidden-jsx.js +13 -12
- package/dist/rules/no-inline-data-in-jsx.d.ts +2 -0
- package/dist/rules/no-inline-data-in-jsx.js +17 -2
- package/dist/rules/no-invalid-feature-folders.d.ts +2 -0
- package/dist/rules/no-invalid-feature-folders.js +12 -4
- package/dist/rules/no-loader-side-effect-in-index-file.d.ts +0 -7
- package/dist/rules/no-logic-in-component-files.d.ts +6 -5
- package/dist/rules/no-logic-in-component-files.js +52 -31
- package/dist/rules/no-mock-db-in-integration.d.ts +0 -15
- package/dist/rules/no-mock-db-in-integration.js +3 -4
- package/dist/rules/no-orm-outside-db.d.ts +1 -0
- package/dist/rules/no-orm-outside-db.js +9 -7
- package/dist/rules/no-raw-html-atoms.d.ts +3 -22
- package/dist/rules/no-raw-html-atoms.js +5 -17
- package/dist/rules/no-raw-sql-outside-allowed.d.ts +2 -0
- package/dist/rules/no-raw-sql-outside-allowed.js +10 -15
- package/dist/rules/no-react-namespace.d.ts +2 -0
- package/dist/rules/no-react-namespace.js +13 -0
- package/dist/rules/no-renamed-html-props.d.ts +2 -0
- package/dist/rules/no-renamed-html-props.js +11 -2
- package/dist/rules/no-render-prop-reader.d.ts +4 -20
- package/dist/rules/no-render-prop-reader.js +13 -5
- package/dist/rules/no-runtime-dead-affordance.d.ts +3 -26
- package/dist/rules/no-runtime-dead-affordance.js +7 -20
- package/dist/rules/no-swallowed-catch.js +2 -8
- package/dist/rules/no-trivial-wrapper-component.d.ts +4 -19
- package/dist/rules/no-trivial-wrapper-component.js +24 -33
- package/dist/rules/no-ts-in-bio-folders.d.ts +2 -13
- package/dist/rules/no-ts-in-bio-folders.js +9 -7
- package/dist/rules/no-type-definitions-in-components.d.ts +2 -0
- package/dist/rules/no-type-definitions-in-components.js +12 -1
- package/dist/rules/no-unregistered-plugin-dir.d.ts +0 -41
- package/dist/rules/no-unregistered-plugin-dir.js +1 -9
- package/dist/rules/no-void-port.d.ts +2 -4
- package/dist/rules/no-void-port.js +7 -0
- package/dist/rules/organelle-dependency.d.ts +1 -0
- package/dist/rules/organelle-dependency.js +10 -8
- package/dist/rules/organelle-single-source.d.ts +2 -0
- package/dist/rules/organelle-single-source.js +58 -9
- package/dist/rules/plugin-route-namespaced.d.ts +0 -11
- package/dist/rules/plugin-route-namespaced.js +2 -2
- package/dist/rules/queries-require-org-scope.d.ts +0 -3
- package/dist/rules/queries-require-org-scope.js +3 -10
- package/dist/rules/queue-loop-is-the-library.js +3 -2
- package/dist/rules/route-no-inline-mutation.d.ts +1 -25
- package/dist/rules/route-no-inline-mutation.js +2 -7
- package/dist/rules/router-schema-parity.d.ts +0 -9
- package/dist/rules/router-schema-parity.js +5 -9
- package/dist/rules/service-name-not-reserved.d.ts +0 -3
- package/dist/rules/service-name-not-reserved.js +1 -34
- package/dist/rules/ssot-no-inline-facts.js +2 -5
- package/dist/rules/ssot-no-process-env.js +4 -12
- package/dist/rules/step-declares-compensation-or-none.d.ts +2 -1
- package/dist/rules/step-declares-compensation-or-none.js +17 -1
- package/dist/rules/step-opens-its-own-cell.d.ts +2 -25
- package/dist/rules/step-opens-its-own-cell.js +8 -13
- package/dist/rules/store-route-scopes-tenant-data.js +8 -26
- package/dist/rules/subpath-over-barrel.d.ts +2 -10
- package/dist/rules/subpath-over-barrel.js +48 -9
- package/dist/rules/subscriber-declares-id.d.ts +0 -2
- package/dist/rules/subscriber-declares-id.js +2 -8
- package/dist/rules/tables-declare-their-plane.d.ts +0 -2
- package/dist/rules/tables-declare-their-plane.js +4 -10
- package/dist/rules/tenant-tables-carry-org-id.d.ts +1 -4
- package/dist/rules/tenant-tables-carry-org-id.js +5 -12
- package/dist/rules/test-no-clock-polling-for-promise-flips.d.ts +2 -0
- package/dist/rules/test-no-clock-polling-for-promise-flips.js +18 -1
- package/dist/rules/time-through-the-door.d.ts +0 -24
- package/dist/rules/time-through-the-door.js +5 -5
- package/dist/rules/tissue-must-compose.d.ts +4 -2
- package/dist/rules/tissue-must-compose.js +25 -20
- package/dist/rules/tissue-no-data-props.d.ts +56 -0
- package/dist/rules/tissue-no-data-props.js +114 -32
- package/dist/rules/tissue-no-fetch.d.ts +26 -0
- package/dist/rules/tissue-no-fetch.js +57 -0
- package/dist/rules/tissue-no-hooks.d.ts +20 -22
- package/dist/rules/tissue-no-hooks.js +22 -4
- package/dist/rules/tissue-no-organelles.d.ts +1 -0
- package/dist/rules/tissue-no-organelles.js +9 -1
- package/dist/rules/tissue-no-stores.d.ts +1 -0
- package/dist/rules/tissue-no-stores.js +9 -1
- package/dist/rules/todo-names-its-plan.d.ts +1 -28
- package/dist/rules/todo-names-its-plan.js +2 -2
- package/dist/rules/tokens-only-colors.d.ts +2 -37
- package/dist/rules/tokens-only-colors.js +33 -18
- package/dist/rules/unique-query-step-name.d.ts +0 -7
- package/dist/rules/unique-query-step-name.js +6 -10
- package/dist/rules/worker-handles-are-scoped.d.ts +11 -8
- package/dist/rules/worker-handles-are-scoped.js +12 -5
- package/dist/rules/zustand-v5-best-practices.d.ts +8 -18
- package/dist/rules/zustand-v5-best-practices.js +32 -56
- package/package.json +2 -2
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// src/rules/lib/workspace-members.ts
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { readManifest } from "./module-text.js";
|
|
5
|
+
var MARKERS = ["pnpm-workspace.yaml", "package.json"];
|
|
6
|
+
var SKIPPED = new Set(["node_modules", ".git"]);
|
|
7
|
+
var listed = (text) => {
|
|
8
|
+
const lines = text.split(`
|
|
9
|
+
`);
|
|
10
|
+
const start = lines.findIndex((line) => /^packages\s*:/.test(line));
|
|
11
|
+
if (start === -1)
|
|
12
|
+
return [];
|
|
13
|
+
const globs = [];
|
|
14
|
+
for (const line of lines.slice(start + 1)) {
|
|
15
|
+
if (line.trim() === "" || line.trim().startsWith("#"))
|
|
16
|
+
continue;
|
|
17
|
+
const item = /^\s*-\s*(.+?)\s*(?:\s#.*)?$/.exec(line)?.[1];
|
|
18
|
+
if (item === undefined)
|
|
19
|
+
break;
|
|
20
|
+
globs.push(item.replace(/^(["'])(.*)\1$/, "$2"));
|
|
21
|
+
}
|
|
22
|
+
return globs;
|
|
23
|
+
};
|
|
24
|
+
var globsOf = (marker, text) => {
|
|
25
|
+
if (marker === "pnpm-workspace.yaml")
|
|
26
|
+
return listed(text);
|
|
27
|
+
let manifest;
|
|
28
|
+
try {
|
|
29
|
+
manifest = JSON.parse(text);
|
|
30
|
+
} catch {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const declared = manifest.workspaces;
|
|
34
|
+
const globs = Array.isArray(declared) ? declared : typeof declared === "object" && declared !== null ? declared.packages : undefined;
|
|
35
|
+
return Array.isArray(globs) ? globs.filter((one) => typeof one === "string") : undefined;
|
|
36
|
+
};
|
|
37
|
+
var directoriesIn = (dir) => {
|
|
38
|
+
try {
|
|
39
|
+
return readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !SKIPPED.has(entry.name)).map((entry) => entry.name);
|
|
40
|
+
} catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var expand = (base, segments) => {
|
|
45
|
+
const [head, ...rest] = segments;
|
|
46
|
+
if (head === undefined)
|
|
47
|
+
return [base];
|
|
48
|
+
if (head === "**") {
|
|
49
|
+
const here = expand(base, rest);
|
|
50
|
+
const below = directoriesIn(base).flatMap((name) => expand(join(base, name), segments));
|
|
51
|
+
return [...here, ...below];
|
|
52
|
+
}
|
|
53
|
+
if (head === "*")
|
|
54
|
+
return directoriesIn(base).flatMap((name) => expand(join(base, name), rest));
|
|
55
|
+
return expand(join(base, head), rest);
|
|
56
|
+
};
|
|
57
|
+
var memberDirs = (root, globs) => {
|
|
58
|
+
const excluded = new Set(globs.filter((one) => one.startsWith("!")).flatMap((one) => expand(root, one.slice(1).replace(/^\.\//, "").split("/"))));
|
|
59
|
+
return globs.filter((one) => !one.startsWith("!")).flatMap((one) => expand(root, one.replace(/^\.\//, "").replace(/\/$/, "").split("/"))).filter((dir) => !excluded.has(dir));
|
|
60
|
+
};
|
|
61
|
+
var nameOf = (manifest) => {
|
|
62
|
+
const name = readManifest(manifest)?.name;
|
|
63
|
+
return typeof name === "string" ? name : undefined;
|
|
64
|
+
};
|
|
65
|
+
var cache = new Map;
|
|
66
|
+
var rootAbove = (from) => {
|
|
67
|
+
let dir = dirname(from);
|
|
68
|
+
for (;; ) {
|
|
69
|
+
for (const marker of MARKERS) {
|
|
70
|
+
const path = join(dir, marker);
|
|
71
|
+
if (!existsSync(path))
|
|
72
|
+
continue;
|
|
73
|
+
let text;
|
|
74
|
+
try {
|
|
75
|
+
text = readFileSync(path, "utf8");
|
|
76
|
+
} catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const globs = globsOf(marker, text);
|
|
80
|
+
if (globs !== undefined && globs.length > 0)
|
|
81
|
+
return { marker, root: dir };
|
|
82
|
+
}
|
|
83
|
+
const parent = dirname(dir);
|
|
84
|
+
if (parent === dir)
|
|
85
|
+
return;
|
|
86
|
+
dir = parent;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var membersFrom = (from) => {
|
|
90
|
+
const found = rootAbove(from);
|
|
91
|
+
if (found === undefined)
|
|
92
|
+
return;
|
|
93
|
+
const marker = join(found.root, found.marker);
|
|
94
|
+
const stamp = statSync(marker).mtimeMs;
|
|
95
|
+
const held = cache.get(marker);
|
|
96
|
+
if (held?.stamp === stamp)
|
|
97
|
+
return held.members;
|
|
98
|
+
const globs = globsOf(found.marker, readFileSync(marker, "utf8")) ?? [];
|
|
99
|
+
const names = new Map;
|
|
100
|
+
for (const dir of memberDirs(found.root, globs)) {
|
|
101
|
+
const manifest = join(dir, "package.json");
|
|
102
|
+
const name = existsSync(manifest) ? nameOf(manifest) : undefined;
|
|
103
|
+
if (name !== undefined && !names.has(name))
|
|
104
|
+
names.set(name, manifest);
|
|
105
|
+
}
|
|
106
|
+
const members = { names, root: found.root };
|
|
107
|
+
cache.set(marker, { members, stamp });
|
|
108
|
+
return members;
|
|
109
|
+
};
|
|
110
|
+
var workspaceMemberNamed = (from, name) => membersFrom(from)?.names.get(name);
|
|
111
|
+
var hasWorkspaceAbove = (from) => rootAbove(from) !== undefined;
|
|
112
|
+
export {
|
|
113
|
+
hasWorkspaceAbove,
|
|
114
|
+
workspaceMemberNamed
|
|
115
|
+
};
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
// src/rules/list-take-without-order.ts
|
|
2
2
|
import { propertyNameOf, walkNode } from "./lib/nodes.js";
|
|
3
|
+
import { keyNameOf } from "./lib/objects.js";
|
|
3
4
|
import { bagOf } from "./lib/probe.js";
|
|
4
5
|
import { optionsBag, STRINGS } from "./lib/schema.js";
|
|
5
6
|
var CALLEES = [String.raw`^(?:\w+\.)?list[A-Z]`, String.raw`^(?:\w+\.)?graph$`];
|
|
6
7
|
var ORDER_KEYS = ["order", "orderBy"];
|
|
7
|
-
var TAKE = "take";
|
|
8
|
-
var keyNameOf = (node) => {
|
|
9
|
-
const key = node.key;
|
|
10
|
-
if (key?.type === "Identifier" && typeof key.name === "string")
|
|
11
|
-
return key.name;
|
|
12
|
-
return key?.type === "Literal" && typeof key.value === "string" ? key.value : null;
|
|
13
|
-
};
|
|
14
8
|
var spellingOf = (callee) => {
|
|
15
9
|
if (callee === undefined)
|
|
16
10
|
return null;
|
|
@@ -42,7 +36,7 @@ var listTakeWithoutOrder = {
|
|
|
42
36
|
if (inner.type !== "Property")
|
|
43
37
|
return;
|
|
44
38
|
const key = keyNameOf(inner);
|
|
45
|
-
if (key ===
|
|
39
|
+
if (key === "take")
|
|
46
40
|
takes = true;
|
|
47
41
|
if (key !== null && orderKeys.includes(key))
|
|
48
42
|
orders = true;
|
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
value: string;
|
|
4
|
-
loc: {
|
|
5
|
-
start: {
|
|
6
|
-
line: number;
|
|
7
|
-
};
|
|
8
|
-
end: {
|
|
9
|
-
line: number;
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
type SourceCode = {
|
|
14
|
-
text?: string;
|
|
1
|
+
import { type SourceCode as CommentSource } from './lib/comments.js';
|
|
2
|
+
type SourceCode = CommentSource & {
|
|
15
3
|
lines?: string[];
|
|
16
|
-
|
|
17
|
-
ast?: {
|
|
18
|
-
comments?: Comment[];
|
|
19
|
-
};
|
|
4
|
+
text?: string;
|
|
20
5
|
};
|
|
21
6
|
declare const maxCommentDensity: {
|
|
22
7
|
create(context: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/rules/max-comment-density.ts
|
|
2
|
-
import {
|
|
2
|
+
import { commentsOf } from "./lib/comments.js";
|
|
3
|
+
import { matchesAny, normalise } from "./lib/paths.js";
|
|
3
4
|
var exemptFiles = [
|
|
4
5
|
/\/__tests__\//,
|
|
5
6
|
/\.config\.(ts|mjs|js)$/,
|
|
@@ -11,13 +12,12 @@ var commentCeilingPercent = 10;
|
|
|
11
12
|
var commentBlockCeilingLines = 3;
|
|
12
13
|
var commentLinesAlwaysAllowed = 3;
|
|
13
14
|
var directive = /^\s*(eslint|oxlint|biome|prettier|@ts-|c8 |v8 |istanbul )/;
|
|
14
|
-
var commentsOf = (sourceCode) => sourceCode.getAllComments?.() ?? sourceCode.ast?.comments ?? [];
|
|
15
15
|
var lineCount = (sourceCode) => sourceCode.lines?.length ?? (sourceCode.text ?? "").split(`
|
|
16
16
|
`).length;
|
|
17
17
|
var maxCommentDensity = {
|
|
18
18
|
create(context) {
|
|
19
19
|
const normalized = normalise(context.filename);
|
|
20
|
-
if (exemptFiles
|
|
20
|
+
if (matchesAny(exemptFiles, normalized))
|
|
21
21
|
return {};
|
|
22
22
|
return {
|
|
23
23
|
Program(node) {
|
|
@@ -9,6 +9,7 @@ declare const moleculeAtomsOnly: {
|
|
|
9
9
|
}) => void;
|
|
10
10
|
}): import('./lib/visitors.js').Visitor;
|
|
11
11
|
fixShape: string;
|
|
12
|
+
probe?: ((options: readonly unknown[]) => import('./lib/probe.js').Probe | import('./lib/probe.js').ProbeTree) | undefined;
|
|
12
13
|
meta: {
|
|
13
14
|
docs: {
|
|
14
15
|
description: string;
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
// src/rules/molecule-atoms-only.ts
|
|
2
2
|
import { directionRule } from "./lib/direction-rule.js";
|
|
3
|
+
import { inTiersAbove, APP_FOLDER, STORES_FOLDER } from "./lib/tiers.js";
|
|
3
4
|
var FORBIDDEN_PATTERNS = [
|
|
4
5
|
/(?:^|\/)components\/ui\//,
|
|
5
|
-
|
|
6
|
-
/(?:^|\/)organelles\//,
|
|
7
|
-
/(?:^|\/)cells\//,
|
|
8
|
-
/(?:^|\/)tissues\//,
|
|
9
|
-
/(?:^|\/)stores\//,
|
|
6
|
+
STORES_FOLDER,
|
|
10
7
|
/(?:^|[/@])domains(?:\/|$)/,
|
|
11
|
-
|
|
8
|
+
APP_FOLDER
|
|
12
9
|
];
|
|
13
10
|
var moleculeAtomsOnly = directionRule({
|
|
14
11
|
description: "Molecules are inert combinations of atoms. They must not import compounds, organelles, cells, tissues, stores, domains, or the raw state-bearing components/ui primitives — composing a stateful primitive makes the file a cell.",
|
|
15
12
|
fixShape: `A molecule combines atoms and other molecules and nothing else — no compound, organelle, cell,
|
|
16
13
|
tissue, store or domain, and no state-bearing \`components/ui\` primitive (Calendar, Popover, Carousel).
|
|
17
14
|
Composing a stateful primitive makes the file a cell. \`export … from\` is checked like an import.`,
|
|
18
|
-
forbidden: (target) => FORBIDDEN_PATTERNS.some((pattern) => pattern.test(target.path)),
|
|
15
|
+
forbidden: (target) => inTiersAbove(target.path, "molecules") || FORBIDDEN_PATTERNS.some((pattern) => pattern.test(target.path)),
|
|
19
16
|
messages: {
|
|
20
17
|
forbidden: "Molecules cannot import from {{source}}. Molecules are inert atom-combinations — state-bearing primitives (components/ui) and higher tiers belong in a cell."
|
|
21
18
|
},
|
|
19
|
+
probe: () => ({
|
|
20
|
+
path: "src/molecules/geonosis-probe.tsx",
|
|
21
|
+
source: `import { Up } from '../compounds/geonosis-up'
|
|
22
|
+
|
|
23
|
+
export const GeonosisProbe = Up
|
|
24
|
+
`
|
|
25
|
+
}),
|
|
22
26
|
scope: "molecules",
|
|
23
27
|
typeOnly: "visit"
|
|
24
28
|
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { type RuleContext } from './lib/context.js';
|
|
2
|
+
import { type Probe } from './lib/probe.js';
|
|
2
3
|
import { type CompositionImportNode, type JsxOpeningElementNode } from './lib/render-tracking.js';
|
|
3
4
|
declare const moleculeMustCompose: {
|
|
4
5
|
create(context: RuleContext): {
|
|
5
|
-
'Program:exit'?: undefined;
|
|
6
6
|
ImportDeclaration?: undefined;
|
|
7
7
|
JSXOpeningElement?: undefined;
|
|
8
|
+
'Program:exit'?: undefined;
|
|
8
9
|
} | {
|
|
9
10
|
ImportDeclaration(node: CompositionImportNode): void;
|
|
10
11
|
JSXOpeningElement(node: JsxOpeningElementNode): void;
|
|
@@ -21,5 +22,6 @@ declare const moleculeMustCompose: {
|
|
|
21
22
|
schema: never[];
|
|
22
23
|
type: 'problem';
|
|
23
24
|
};
|
|
25
|
+
probe(): Probe;
|
|
24
26
|
};
|
|
25
27
|
export default moleculeMustCompose;
|
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
// src/rules/molecule-must-compose.ts
|
|
2
|
-
import { normalise } from "./lib/paths.js";
|
|
2
|
+
import { normalise, fileOf } from "./lib/paths.js";
|
|
3
3
|
import { launderedHomesOf } from "./lib/reexports.js";
|
|
4
4
|
import {
|
|
5
5
|
collectCompositionLocals,
|
|
6
6
|
rendersAnyOf,
|
|
7
7
|
rootTagNameOf
|
|
8
8
|
} from "./lib/render-tracking.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return true;
|
|
12
|
-
if (/^\.\/[^/]+$/.test(src))
|
|
13
|
-
return true;
|
|
14
|
-
if (src.startsWith("@radix-ui/") || src === "radix-ui" || src.startsWith("radix-ui/"))
|
|
15
|
-
return true;
|
|
16
|
-
if (src.startsWith("@react-email/"))
|
|
17
|
-
return true;
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
9
|
+
import { folderOf, tierFolderOf } from "./lib/tiers.js";
|
|
10
|
+
var isCompositionSource = (src) => folderOf(src, ["atoms", "molecules"]) !== undefined || /^\.\/[^/]+$/.test(src) || src.startsWith("@radix-ui/") || src === "radix-ui" || src.startsWith("radix-ui/") || src.startsWith("@react-email/");
|
|
20
11
|
var moleculeMustCompose = {
|
|
21
12
|
create(context) {
|
|
22
13
|
const filename = normalise(context.filename);
|
|
23
|
-
const
|
|
14
|
+
const basename = fileOf(filename);
|
|
15
|
+
const isMolecule = tierFolderOf(filename) === "molecules" && !basename.startsWith("index.") && /\.tsx?$/.test(basename) && !basename.endsWith(".types.ts");
|
|
24
16
|
if (!isMolecule)
|
|
25
17
|
return {};
|
|
26
18
|
const laundered = launderedHomesOf(filename);
|
|
@@ -28,7 +20,6 @@ var moleculeMustCompose = {
|
|
|
28
20
|
return {};
|
|
29
21
|
const bioImportLocals = new Set;
|
|
30
22
|
const renderedTagNames = new Set;
|
|
31
|
-
let programNode = null;
|
|
32
23
|
return {
|
|
33
24
|
ImportDeclaration(node) {
|
|
34
25
|
collectCompositionLocals(node, isCompositionSource, bioImportLocals);
|
|
@@ -39,14 +30,8 @@ var moleculeMustCompose = {
|
|
|
39
30
|
renderedTagNames.add(root);
|
|
40
31
|
},
|
|
41
32
|
"Program:exit"(node) {
|
|
42
|
-
programNode = node;
|
|
43
33
|
if (!rendersAnyOf(bioImportLocals, renderedTagNames)) {
|
|
44
|
-
|
|
45
|
-
context.report({
|
|
46
|
-
data: { filename: shortName },
|
|
47
|
-
messageId: "missingComposition",
|
|
48
|
-
node: programNode
|
|
49
|
-
});
|
|
34
|
+
context.report({ data: { filename: basename }, messageId: "missingComposition", node });
|
|
50
35
|
}
|
|
51
36
|
}
|
|
52
37
|
};
|
|
@@ -65,6 +50,17 @@ of a molecule that moved is not a second molecule, and one line re-exporting an
|
|
|
65
50
|
},
|
|
66
51
|
schema: [],
|
|
67
52
|
type: "problem"
|
|
53
|
+
},
|
|
54
|
+
probe() {
|
|
55
|
+
return {
|
|
56
|
+
path: "src/molecules/geonosis-probe.tsx",
|
|
57
|
+
source: `import { Atom } from '../atoms/geonosis-atom'
|
|
58
|
+
|
|
59
|
+
export function GeonosisProbe() {
|
|
60
|
+
return <div>{String(Atom)}</div>
|
|
61
|
+
}
|
|
62
|
+
`
|
|
63
|
+
};
|
|
68
64
|
}
|
|
69
65
|
};
|
|
70
66
|
var molecule_must_compose_default = moleculeMustCompose;
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { type RuleContextWithOptions } from './lib/context.js';
|
|
2
2
|
import { type AnyNode } from './lib/nodes.js';
|
|
3
|
+
import { type Probe } from './lib/probe.js';
|
|
3
4
|
interface Options {
|
|
4
|
-
/** The call names that generate a service write. Default: what `MedusaService` generates. */
|
|
5
5
|
mutationPrefixes?: string[];
|
|
6
|
-
/** The config key a step's retry budget is written under. Default: Medusa's `maxRetries`. */
|
|
7
6
|
retryKey?: string;
|
|
8
|
-
/**
|
|
9
|
-
* The key that holds the NUMBER when the budget is an object. Default: `limit`, which is how
|
|
10
|
-
* `@geonosis/workflows` spells it (`retry: { limit, backoff }`).
|
|
11
|
-
*/
|
|
12
7
|
retryLimitKey?: string;
|
|
13
|
-
/** The call names that define a step. Default: Medusa's `createStep`. */
|
|
14
8
|
stepFactories?: string[];
|
|
15
9
|
}
|
|
16
10
|
declare const mutatingStepDeclaresRetry: {
|
|
@@ -53,5 +47,6 @@ declare const mutatingStepDeclaresRetry: {
|
|
|
53
47
|
}[];
|
|
54
48
|
type: 'problem';
|
|
55
49
|
};
|
|
50
|
+
probe(options: readonly unknown[]): Probe;
|
|
56
51
|
};
|
|
57
52
|
export default mutatingStepDeclaresRetry;
|
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
// src/rules/mutating-step-declares-retry.ts
|
|
2
|
-
import { mutationPrefixesOf, writesWith } from "./lib/mutations.js";
|
|
2
|
+
import { DEFAULT_MUTATION_PREFIXES, mutationPrefixesOf, writesWith } from "./lib/mutations.js";
|
|
3
3
|
import { walkNode } from "./lib/nodes.js";
|
|
4
4
|
import { propertiesOf, valueOf } from "./lib/objects.js";
|
|
5
5
|
import { requireOption } from "./lib/options.js";
|
|
6
|
+
import { bagOf, firstOf } from "./lib/probe.js";
|
|
6
7
|
import { optionsBag, STRING, STRINGS } from "./lib/schema.js";
|
|
7
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
argumentsOf,
|
|
10
|
+
configOf,
|
|
11
|
+
DEFAULT_STEP_FACTORIES,
|
|
12
|
+
isStepCall,
|
|
13
|
+
stepFactoriesOf,
|
|
14
|
+
stepNameOf
|
|
15
|
+
} from "./lib/steps.js";
|
|
8
16
|
var RULE = "mutating-step-declares-retry";
|
|
9
17
|
var DEFAULT_RETRY_KEY = "maxRetries";
|
|
10
18
|
var DEFAULT_RETRY_LIMIT_KEY = "limit";
|
|
11
|
-
var NO_RETRY = 0;
|
|
12
19
|
var mutatingStepDeclaresRetry = {
|
|
13
20
|
create(context) {
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
21
|
+
const bag = context.options?.[0] ?? {};
|
|
22
|
+
const factories = stepFactoriesOf(RULE, bag.stepFactories);
|
|
23
|
+
const isWrite = writesWith(mutationPrefixesOf(RULE, bag.mutationPrefixes));
|
|
24
|
+
const retryKey = requireOption(RULE, bag.retryKey ?? DEFAULT_RETRY_KEY, "retryKey");
|
|
25
|
+
const retryLimitKey = requireOption(RULE, bag.retryLimitKey ?? DEFAULT_RETRY_LIMIT_KEY, "retryLimitKey");
|
|
18
26
|
return {
|
|
19
27
|
CallExpression(node) {
|
|
20
28
|
if (!isStepCall(node, factories))
|
|
@@ -43,11 +51,9 @@ var mutatingStepDeclaresRetry = {
|
|
|
43
51
|
}
|
|
44
52
|
const nested = propertiesOf(budget);
|
|
45
53
|
const declared = nested === null ? budget : valueOf(nested, retryLimitKey);
|
|
46
|
-
if (declared
|
|
54
|
+
if (declared?.type !== "Literal" || typeof declared.value !== "number")
|
|
47
55
|
return;
|
|
48
|
-
if (declared.
|
|
49
|
-
return;
|
|
50
|
-
if (declared.value > NO_RETRY)
|
|
56
|
+
if (declared.value > 0)
|
|
51
57
|
return;
|
|
52
58
|
context.report({
|
|
53
59
|
data: { budget: String(declared.value), key: retryKey, step },
|
|
@@ -84,6 +90,18 @@ if the repo wraps \`createStep\`, and \`mutationPrefixes\` if its writes are nam
|
|
|
84
90
|
stepFactories: STRINGS
|
|
85
91
|
}),
|
|
86
92
|
type: "problem"
|
|
93
|
+
},
|
|
94
|
+
probe(options) {
|
|
95
|
+
const bag = bagOf(options);
|
|
96
|
+
const factory = firstOf(bag.stepFactories, DEFAULT_STEP_FACTORIES);
|
|
97
|
+
const write = firstOf(bag.mutationPrefixes, DEFAULT_MUTATION_PREFIXES);
|
|
98
|
+
return {
|
|
99
|
+
path: "geonosis-probe-step.ts",
|
|
100
|
+
source: `export const geonosisProbe = ${factory}('geonosis-probe', async () => {
|
|
101
|
+
await service.${write}Probe()
|
|
102
|
+
})
|
|
103
|
+
`
|
|
104
|
+
};
|
|
87
105
|
}
|
|
88
106
|
};
|
|
89
107
|
var mutating_step_declares_retry_default = mutatingStepDeclaresRetry;
|
|
@@ -2,7 +2,6 @@ import { type RuleContextWithOptions } from './lib/context.js';
|
|
|
2
2
|
import { type AnyNode } from './lib/nodes.js';
|
|
3
3
|
import { type Probe } from './lib/probe.js';
|
|
4
4
|
interface Options {
|
|
5
|
-
/** The call names that open a conditional block. Default: Medusa's `when`. */
|
|
6
5
|
blocks?: string[];
|
|
7
6
|
}
|
|
8
7
|
declare const namedWhenBlock: {
|
|
@@ -31,7 +30,6 @@ declare const namedWhenBlock: {
|
|
|
31
30
|
}[];
|
|
32
31
|
type: 'problem';
|
|
33
32
|
};
|
|
34
|
-
/** The unnamed overload, told by ARITY — two arguments, which is the shape that fires. */
|
|
35
33
|
probe(options: readonly unknown[]): Probe;
|
|
36
34
|
};
|
|
37
35
|
export default namedWhenBlock;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { calleeNameOf } from "./lib/nodes.js";
|
|
3
3
|
import { requireOption } from "./lib/options.js";
|
|
4
4
|
import { bagOf, firstOf } from "./lib/probe.js";
|
|
5
|
-
import { STRINGS } from "./lib/schema.js";
|
|
5
|
+
import { optionsBag, STRINGS } from "./lib/schema.js";
|
|
6
6
|
var RULE = "named-when-block";
|
|
7
7
|
var DEFAULT_BLOCKS = ["when"];
|
|
8
8
|
var NAMED = 3;
|
|
@@ -35,13 +35,7 @@ name.`,
|
|
|
35
35
|
messages: {
|
|
36
36
|
unnamed: "`{{block}}()` is called without a name, so its step is registered as `when-then-{ulid}` — a fresh identity every process. A run resumed after a restart cannot find the checkpoint it was at. Pass a stable name as the first argument."
|
|
37
37
|
},
|
|
38
|
-
schema:
|
|
39
|
-
{
|
|
40
|
-
additionalProperties: false,
|
|
41
|
-
properties: { blocks: STRINGS },
|
|
42
|
-
type: "object"
|
|
43
|
-
}
|
|
44
|
-
],
|
|
38
|
+
schema: optionsBag({ blocks: STRINGS }),
|
|
45
39
|
type: "problem"
|
|
46
40
|
},
|
|
47
41
|
probe(options) {
|
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
import { type RuleContext } from './lib/context.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
name?: string;
|
|
5
|
-
type: string;
|
|
6
|
-
};
|
|
7
|
-
local?: {
|
|
8
|
-
name?: string;
|
|
9
|
-
type: string;
|
|
10
|
-
};
|
|
11
|
-
type: string;
|
|
12
|
-
}
|
|
13
|
-
interface ImportNode {
|
|
14
|
-
source: {
|
|
15
|
-
value: string;
|
|
16
|
-
};
|
|
17
|
-
specifiers?: ImportSpecifier[];
|
|
18
|
-
type: string;
|
|
19
|
-
}
|
|
2
|
+
import { type ModuleNode } from './lib/imports.js';
|
|
3
|
+
import { type Probe } from './lib/probe.js';
|
|
20
4
|
interface FunctionDeclLike {
|
|
21
5
|
body?: {
|
|
22
6
|
body?: unknown[];
|
|
@@ -37,7 +21,7 @@ declare const nextRouteSegmentIsThinDelegate: {
|
|
|
37
21
|
ExportDefaultDeclaration?: undefined;
|
|
38
22
|
} | {
|
|
39
23
|
ExportDefaultDeclaration(node: ExportDefaultDeclNode): void;
|
|
40
|
-
ImportDeclaration(node:
|
|
24
|
+
ImportDeclaration(node: ModuleNode): void;
|
|
41
25
|
};
|
|
42
26
|
fixShape: string;
|
|
43
27
|
meta: {
|
|
@@ -52,5 +36,6 @@ declare const nextRouteSegmentIsThinDelegate: {
|
|
|
52
36
|
schema: never[];
|
|
53
37
|
type: 'problem';
|
|
54
38
|
};
|
|
39
|
+
probe(): Probe;
|
|
55
40
|
};
|
|
56
41
|
export default nextRouteSegmentIsThinDelegate;
|