@geonosis/oxlint-plugin-biological-architecture 2.2.0 → 2.3.1
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/RULES.md +37 -18
- package/corpus/.oxlintrc.json +48 -10
- package/corpus/affordances/bad-dead-control.tsx +6 -0
- package/corpus/affordances/good-live-control.tsx +12 -0
- package/corpus/api/store/history/find-orders.ts +8 -0
- package/corpus/api/store/history/route.ts +7 -0
- package/corpus/api/store/track/find-tracked-order.ts +12 -0
- package/corpus/api/store/track/route.ts +10 -0
- package/corpus/dates/bad-string-order.ts +7 -0
- package/corpus/dates/good-time-order.ts +7 -0
- package/corpus/engine/good-durable-read-through-step-proxy.ts +13 -0
- package/corpus/failure/good-refresh.ts +17 -0
- package/corpus/failure/logged.ts +6 -0
- package/corpus/failure/refresh.ts +4 -0
- package/corpus/failure/reload.ts +6 -0
- package/corpus/manifest.json +6 -0
- package/corpus/medusa/queries/bad-unordered-page.ts +20 -0
- package/corpus/medusa/queries/good-ordered-page.ts +23 -0
- package/corpus/messaging/providers/email-gmail.ts +2 -0
- package/corpus/messaging/providers/sms-twilio.ts +2 -0
- package/corpus/messaging/providers/whatsapp-360dialog.ts +2 -0
- package/corpus/messaging/registry.ts +5 -0
- package/corpus/packages/pricing/package.json +5 -0
- package/corpus/packages/pricing/src/index.ts +2 -0
- package/corpus/packages/utils/package.json +5 -0
- package/corpus/packages/utils/src/index.ts +4 -0
- package/corpus/suites/__tests__/awaits.ts +17 -0
- package/corpus/suites/__tests__/settles.ts +14 -0
- package/dist/{chunk-LTDP2733.js → chunk-KV7JRNAP.js} +7 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +812 -61
- package/dist/presets.d.ts +3 -0
- package/dist/presets.js +1 -1
- package/package.json +2 -2
- /package/corpus/api/store/orders/{scoped.route.ts → scoped/route.ts} +0 -0
package/RULES.md
CHANGED
|
@@ -9,11 +9,13 @@ Read from the two source trees on 2026-08-29:
|
|
|
9
9
|
One plugin name, two rule sets, no shared code. **33 rules had the same filename in both trees; only
|
|
10
10
|
3 of those 33 were byte-identical.** A fix in one never reached the other.
|
|
11
11
|
|
|
12
|
-
The union here is **54 rules**, plus twenty-
|
|
13
|
-
`emit-declares-attempts`, `cell-no-cross-feature-organelles`, the `backend-medusa` ten
|
|
12
|
+
The union here is **54 rules**, plus twenty-eight the kit wrote for itself — `layer-walls`,
|
|
13
|
+
`emit-declares-attempts`, `cell-no-cross-feature-organelles`, the `backend-medusa` ten,
|
|
14
14
|
`no-unregistered-plugin-dir` + `router-schema-parity`, the `themekit` two,
|
|
15
15
|
`no-mock-db-in-integration`, `todo-names-its-plan`, `boundary-time-is-primitive`,
|
|
16
|
-
`durable-body-reads-through-steps
|
|
16
|
+
`durable-body-reads-through-steps`, `subpath-over-barrel` and the six of the W67 batch — **82**.
|
|
17
|
+
Every one of the twenty-eight is marked **written here** in the inventory, and the table below is
|
|
18
|
+
held against that column rather than kept by hand.
|
|
17
19
|
|
|
18
20
|
| | count |
|
|
19
21
|
|---|---|
|
|
@@ -22,13 +24,8 @@ The union here is **54 rules**, plus twenty-two the kit wrote for itself — `la
|
|
|
22
24
|
| dielime only | 3 |
|
|
23
25
|
| during.day only | 18 |
|
|
24
26
|
| **union** | **54** |
|
|
25
|
-
| written here
|
|
26
|
-
|
|
|
27
|
-
| written here, the integration seam (1.0.0) | 2 |
|
|
28
|
-
| **total** | **66** |
|
|
29
|
-
| written here, `backend-medusa` (1.0.0) | 10 |
|
|
30
|
-
| **total** | **67** |
|
|
31
|
-
| written here, `themekit` (1.0.0) | 2 |
|
|
27
|
+
| written here | 28 |
|
|
28
|
+
| **total** | **82** |
|
|
32
29
|
|
|
33
30
|
## How divergence was resolved
|
|
34
31
|
|
|
@@ -88,6 +85,16 @@ decided the boundary or counts what accumulated on the far side — a consumer's
|
|
|
88
85
|
took on seven unchartered exports, one of them a write, lint-free, in eleven commits. A list of
|
|
89
86
|
module names is a number a reader can hold: a repo has one door, or it has three and knows it.
|
|
90
87
|
|
|
88
|
+
Every other rule that grants by path now takes the same enumeration beside its pattern (#139).
|
|
89
|
+
`time-through-the-door`'s `exempt`, `font-roles-only`'s `allow` and `tokens-only-colors`' `allow` —
|
|
90
|
+
measured from the option table, and the only three path GRANTS the plugin has; `within`, `paths`,
|
|
91
|
+
`roots` and `routers` are scopes — each accept `exemptModules`, a list of modules named in full,
|
|
92
|
+
matched by path or by the tail a repo writes them as and never as a pattern. The patterns still
|
|
93
|
+
work. What changed is that they are counted: each of those rules declares `meta.grants`
|
|
94
|
+
(`{ paths, modules }`), and `geonosis-doctor`'s `exercised` line WARNs with the number of files the
|
|
95
|
+
pattern exempts in THIS tree beside the number the enumeration names — so a grant nobody decided
|
|
96
|
+
stops being a grant nobody can see.
|
|
97
|
+
|
|
91
98
|
### An enabled rule that cannot fire **refuses the run** (0.2.0)
|
|
92
99
|
|
|
93
100
|
This replaces the "does nothing until configured" posture below, and it is the one breaking change
|
|
@@ -710,20 +717,23 @@ has, and one a kit that guessed at it would keep stale on somebody else's behalf
|
|
|
710
717
|
| `emit-declares-attempts` | backend-medusa | — | `options` | — | — | **written here** |
|
|
711
718
|
| `font-roles-only` | themekit | `roles` | `paths` + `options` + `styling` | — | — | **written here** (U2) |
|
|
712
719
|
| `layer-walls` | tooling | `layers` | `onImportSource` + `imports` + `paths` + `options` | — | — | **written here** |
|
|
720
|
+
| `list-take-without-order` | backend-medusa | — | `nodes` + `options` | — | — | **written here** (#21) |
|
|
713
721
|
| `max-comment-density` | comment-ceiling | — | `paths` | — | yes | during only |
|
|
714
722
|
| `molecule-atoms-only` | frontend | — | `directionRule` | yes | yes | diverged |
|
|
715
723
|
| `molecule-must-compose` | frontend | — | — | yes | yes | diverged |
|
|
716
724
|
| `mutating-step-declares-retry` | backend-medusa + backend-workflows | — | `nodes` + `objects` + `steps` + `options` | — | — | **written here** (dielime scan R5.2) |
|
|
717
725
|
| `named-when-block` | backend-medusa | — | `nodes` + `options` | — | — | **written here** (dielime scan R5.5) |
|
|
718
726
|
| `next-route-segment-is-thin-delegate` | frontend | — | `paths` | yes | yes | diverged |
|
|
719
|
-
| `no-unregistered-plugin-dir` | integrations | `roots` | `options` + `paths` | — | — | **written here** (Midday's 8 dead dirs) |
|
|
727
|
+
| `no-unregistered-plugin-dir` | integrations | `roots` | `options` + `paths` | — | — | **written here** (Midday's 8 dead dirs; flat seam #36) |
|
|
720
728
|
| `no-mock-db-in-integration` | testbed | `integrationDirs` | `options` + `paths` | — | — | **written here** (Midday's 35 mocked router suites) |
|
|
721
729
|
| `router-schema-parity` | backend-trpc | `routers` | `options` + `paths` | — | — | **written here** (during.day's mirror) |
|
|
722
730
|
| `no-brand-names` | frontend | `brands` | `paths` + `options` | yes | — | dielime only |
|
|
723
731
|
| `no-card-shaped-div` | frontend | — | — | yes | yes | diverged |
|
|
724
732
|
| `no-cross-feature-stores` | frontend | — | `directionRule` | yes | yes | diverged |
|
|
725
733
|
| `no-d1-transaction` | backend-d1 | — | `paths` | — | yes | during only |
|
|
734
|
+
| `no-date-string-compare` | backend-workflows | — | `nodes` + `options` | — | — | **written here** (#20) |
|
|
726
735
|
| `no-duplicate-jsx-patterns` | frontend | — | `paths` | yes | yes | diverged |
|
|
736
|
+
| `no-generic-utility-package` | tooling | — | `paths` + `options` | — | — | **written here** (#171) |
|
|
727
737
|
| `no-hook-in-component-disguise` | frontend | — | `paths` | yes | yes | diverged |
|
|
728
738
|
| `no-index-count-as-exact` | backend-medusa | — | `nodes` + `objects` + `options` | — | — | **written here** (Medusa source) |
|
|
729
739
|
| `no-inert-hidden-jsx` | frontend | — | `paths` | yes | yes | diverged |
|
|
@@ -738,6 +748,8 @@ has, and one a kit that guessed at it would keep stale on somebody else's behalf
|
|
|
738
748
|
| `no-react-namespace` | frontend | — | — | yes | yes | **identical** |
|
|
739
749
|
| `no-renamed-html-props` | frontend | — | — | yes | yes | **identical** |
|
|
740
750
|
| `no-render-prop-reader` | frontend | — | `paths` | yes | yes | diverged |
|
|
751
|
+
| `no-swallowed-catch` | failure-paths | — | `nodes` + `paths` + `options` | — | — | **written here** (#3) |
|
|
752
|
+
| `no-runtime-dead-affordance` | frontend | — | `options` | — | — | **written here** (#5) |
|
|
741
753
|
| `no-trivial-wrapper-component` | frontend | — | `paths` | yes | yes | diverged |
|
|
742
754
|
| `no-ts-in-bio-folders` | frontend | — | `paths` | yes | yes | diverged |
|
|
743
755
|
| `no-type-definitions-in-components` | frontend | — | `paths` | yes | yes | diverged |
|
|
@@ -752,11 +764,12 @@ has, and one a kit that guessed at it would keep stale on somebody else's behalf
|
|
|
752
764
|
| `ssot-no-process-env` | backend-workflows | — | `paths` | — | yes | during only |
|
|
753
765
|
| `step-declares-compensation-or-none` | backend-medusa + backend-workflows | — | `nodes` + `objects` + `steps` + `options` | — | — | **written here** (Medusa source) |
|
|
754
766
|
| `step-opens-its-own-cell` | backend-workflows-cf | `within` | `nodes` + `objects` + `paths` + `options` | — | yes | during only, re-targeted |
|
|
755
|
-
| `store-route-scopes-tenant-data` | backend-medusa + tenant-scoping | — | `paths` | yes | — | dielime only |
|
|
767
|
+
| `store-route-scopes-tenant-data` | backend-medusa + tenant-scoping | — | `nodes` + `imports` + `paths` + `options` | yes | — | dielime only, de-hardcoded |
|
|
756
768
|
| `subpath-over-barrel` | package-subpaths | `packages` | `nodes` + `options` | — | — | **written here** (#180, during.day asked) |
|
|
757
769
|
| `subscriber-declares-id` | backend-medusa | — | `objects` + `paths` + `options` | — | — | **written here** (dielime scan R5.4) |
|
|
758
770
|
| `tables-declare-their-plane` | backend-workflows + tenant-scoping | — | `paths` + `literal-call` | — | yes | during only |
|
|
759
771
|
| `tenant-tables-carry-org-id` | tenant-scoping | — | `paths` + `literal-call` | — | yes | during only |
|
|
772
|
+
| `test-no-clock-polling-for-promise-flips` | testbed | — | `nodes` + `paths` + `options` | — | — | **written here** (#4) |
|
|
760
773
|
| `tokens-only-colors` | themekit | `tokenPrefix` | `paths` + `options` + `styling` + `colors` | — | — | **written here** (U2) |
|
|
761
774
|
| `time-through-the-door` | backend-workflows | `door` | `paths` + `options` | — | yes | during only, de-hardcoded |
|
|
762
775
|
| `tissue-must-compose` | frontend | — | `paths` | yes | yes | diverged |
|
|
@@ -856,11 +869,12 @@ option not named here is one no rule reads.
|
|
|
856
869
|
| `dialect-through-the-seam` | — |
|
|
857
870
|
| `document-sagas-are-generic` | `factories`, `perKindPrefixes`, `within` |
|
|
858
871
|
| `documents-share-one-table` | `perKindTables` |
|
|
859
|
-
| `durable-body-reads-through-steps` | `durableKey`, `durableValue`, `ports`, `stepFactories`, `workflowFactories` |
|
|
872
|
+
| `durable-body-reads-through-steps` | `durableKey`, `durableValue`, `ports`, `stepFactories`, `stepProxies`, `workflowFactories` |
|
|
860
873
|
| `effect-hook-naming` | — |
|
|
861
874
|
| `emit-declares-attempts` | `budgetHelpers`, `emitters` |
|
|
862
|
-
| `font-roles-only` | `allow`, `prefix`, `roles` |
|
|
875
|
+
| `font-roles-only` | `allow`, `exemptModules`, `prefix`, `roles` |
|
|
863
876
|
| `layer-walls` | `externals`, `layers`, `typeOnly` |
|
|
877
|
+
| `list-take-without-order` | `callees`, `orderKeys` |
|
|
864
878
|
| `max-comment-density` | — |
|
|
865
879
|
| `molecule-atoms-only` | — |
|
|
866
880
|
| `molecule-must-compose` | — |
|
|
@@ -871,7 +885,9 @@ option not named here is one no rule reads.
|
|
|
871
885
|
| `no-card-shaped-div` | — |
|
|
872
886
|
| `no-cross-feature-stores` | — |
|
|
873
887
|
| `no-d1-transaction` | — |
|
|
888
|
+
| `no-date-string-compare` | `fieldPattern` |
|
|
874
889
|
| `no-duplicate-jsx-patterns` | — |
|
|
890
|
+
| `no-generic-utility-package` | `entries`, `names` |
|
|
875
891
|
| `no-hook-in-component-disguise` | — |
|
|
876
892
|
| `no-index-count-as-exact` | `estimateFields`, `labelKey` |
|
|
877
893
|
| `no-inert-hidden-jsx` | — |
|
|
@@ -886,6 +902,8 @@ option not named here is one no rule reads.
|
|
|
886
902
|
| `no-react-namespace` | — |
|
|
887
903
|
| `no-renamed-html-props` | — |
|
|
888
904
|
| `no-render-prop-reader` | — |
|
|
905
|
+
| `no-runtime-dead-affordance` | (a positional list) |
|
|
906
|
+
| `no-swallowed-catch` | `paths` |
|
|
889
907
|
| `no-trivial-wrapper-component` | — |
|
|
890
908
|
| `no-ts-in-bio-folders` | — |
|
|
891
909
|
| `no-type-definitions-in-components` | — |
|
|
@@ -899,23 +917,24 @@ option not named here is one no rule reads.
|
|
|
899
917
|
| `route-no-inline-mutation` | `inlineMutationOk`, `mutationPrefixes`, `paths` |
|
|
900
918
|
| `router-schema-parity` | `ignore`, `mounts`, `routers`, `schemas`, `suffix` |
|
|
901
919
|
| `service-name-not-reserved` | `moduleFactories`, `reserved` |
|
|
902
|
-
| `ssot-no-inline-facts` |
|
|
920
|
+
| `ssot-no-inline-facts` | `declarationCallees` |
|
|
903
921
|
| `ssot-no-process-env` | — |
|
|
904
922
|
| `step-declares-compensation-or-none` | `stepFactories` |
|
|
905
923
|
| `step-opens-its-own-cell` | `engine`, `hosts`, `scopeKey`, `within`, `wrapper` |
|
|
906
|
-
| `store-route-scopes-tenant-data` |
|
|
924
|
+
| `store-route-scopes-tenant-data` | `entities`, `evidenceCalls`, `routes`, `scopingCalls` |
|
|
907
925
|
| `subpath-over-barrel` | `packages` |
|
|
908
926
|
| `subscriber-declares-id` | `paths` |
|
|
909
927
|
| `tables-declare-their-plane` | — |
|
|
910
928
|
| `tenant-tables-carry-org-id` | — |
|
|
911
|
-
| `
|
|
929
|
+
| `test-no-clock-polling-for-promise-flips` | `pollers`, `testGlobs` |
|
|
930
|
+
| `time-through-the-door` | `door`, `exempt`, `exemptModules`, `libraries` |
|
|
912
931
|
| `tissue-must-compose` | — |
|
|
913
932
|
| `tissue-no-data-props` | — |
|
|
914
933
|
| `tissue-no-hooks` | — |
|
|
915
934
|
| `tissue-no-organelles` | — |
|
|
916
935
|
| `tissue-no-stores` | — |
|
|
917
936
|
| `todo-names-its-plan` | `id`, `markers` |
|
|
918
|
-
| `tokens-only-colors` | `allow`, `tokenPrefix` |
|
|
937
|
+
| `tokens-only-colors` | `allow`, `exemptModules`, `tokenPrefix` |
|
|
919
938
|
| `unique-query-step-name` | `queryStepCalls`, `workflowFactories` |
|
|
920
939
|
| `worker-handles-are-scoped` | `within`, `wrapper` |
|
|
921
940
|
| `zustand-v5-best-practices` | — |
|
package/corpus/.oxlintrc.json
CHANGED
|
@@ -60,7 +60,11 @@
|
|
|
60
60
|
{
|
|
61
61
|
"ports": [
|
|
62
62
|
"store",
|
|
63
|
-
"billing"
|
|
63
|
+
"billing",
|
|
64
|
+
"q"
|
|
65
|
+
],
|
|
66
|
+
"stepProxies": [
|
|
67
|
+
"q"
|
|
64
68
|
]
|
|
65
69
|
}
|
|
66
70
|
],
|
|
@@ -106,6 +110,7 @@
|
|
|
106
110
|
]
|
|
107
111
|
}
|
|
108
112
|
],
|
|
113
|
+
"biological-architecture/list-take-without-order": "error",
|
|
109
114
|
"biological-architecture/max-comment-density": "error",
|
|
110
115
|
"biological-architecture/molecule-atoms-only": "error",
|
|
111
116
|
"biological-architecture/molecule-must-compose": "error",
|
|
@@ -126,7 +131,9 @@
|
|
|
126
131
|
"biological-architecture/no-card-shaped-div": "error",
|
|
127
132
|
"biological-architecture/no-cross-feature-stores": "error",
|
|
128
133
|
"biological-architecture/no-d1-transaction": "error",
|
|
134
|
+
"biological-architecture/no-date-string-compare": "error",
|
|
129
135
|
"biological-architecture/no-duplicate-jsx-patterns": "error",
|
|
136
|
+
"biological-architecture/no-generic-utility-package": "error",
|
|
130
137
|
"biological-architecture/no-hook-in-component-disguise": "error",
|
|
131
138
|
"biological-architecture/no-index-count-as-exact": "error",
|
|
132
139
|
"biological-architecture/no-inert-hidden-jsx": "error",
|
|
@@ -149,6 +156,14 @@
|
|
|
149
156
|
}
|
|
150
157
|
],
|
|
151
158
|
"biological-architecture/no-orm-outside-db": "error",
|
|
159
|
+
"biological-architecture/no-swallowed-catch": [
|
|
160
|
+
"error",
|
|
161
|
+
{
|
|
162
|
+
"paths": [
|
|
163
|
+
"(?:__fixtures__|corpus)/failure/"
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
],
|
|
152
167
|
"biological-architecture/no-raw-html-atoms": [
|
|
153
168
|
"error",
|
|
154
169
|
[
|
|
@@ -161,6 +176,16 @@
|
|
|
161
176
|
],
|
|
162
177
|
"biological-architecture/no-raw-sql-outside-allowed": "error",
|
|
163
178
|
"biological-architecture/no-react-namespace": "error",
|
|
179
|
+
"biological-architecture/no-runtime-dead-affordance": [
|
|
180
|
+
"error",
|
|
181
|
+
[
|
|
182
|
+
{
|
|
183
|
+
"element": "button",
|
|
184
|
+
"atom": "Button",
|
|
185
|
+
"importPath": "@kit/ui/atoms/button"
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
],
|
|
164
189
|
"biological-architecture/no-renamed-html-props": "error",
|
|
165
190
|
"biological-architecture/no-render-prop-reader": "error",
|
|
166
191
|
"biological-architecture/no-trivial-wrapper-component": "error",
|
|
@@ -170,11 +195,16 @@
|
|
|
170
195
|
"error",
|
|
171
196
|
{
|
|
172
197
|
"roots": [
|
|
173
|
-
"integrations/providers"
|
|
198
|
+
"integrations/providers",
|
|
199
|
+
{
|
|
200
|
+
"path": "messaging/providers",
|
|
201
|
+
"files": true
|
|
202
|
+
}
|
|
174
203
|
],
|
|
175
204
|
"registry": [
|
|
176
205
|
"integrations/registry.ts",
|
|
177
|
-
"integrations/registry.fulfillment.ts"
|
|
206
|
+
"integrations/registry.fulfillment.ts",
|
|
207
|
+
"messaging/registry.ts"
|
|
178
208
|
],
|
|
179
209
|
"manifests": [
|
|
180
210
|
"index.ts"
|
|
@@ -235,7 +265,14 @@
|
|
|
235
265
|
"wrapper": "(?:__fixtures__|corpus)/workflows/step\\.ts$"
|
|
236
266
|
}
|
|
237
267
|
],
|
|
238
|
-
"biological-architecture/store-route-scopes-tenant-data":
|
|
268
|
+
"biological-architecture/store-route-scopes-tenant-data": [
|
|
269
|
+
"error",
|
|
270
|
+
{
|
|
271
|
+
"evidenceCalls": [
|
|
272
|
+
"assertTrackingEvidence"
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
],
|
|
239
276
|
"biological-architecture/subpath-over-barrel": [
|
|
240
277
|
"error",
|
|
241
278
|
{
|
|
@@ -260,12 +297,13 @@
|
|
|
260
297
|
"biological-architecture/subscriber-declares-id": "error",
|
|
261
298
|
"biological-architecture/tables-declare-their-plane": "error",
|
|
262
299
|
"biological-architecture/tenant-tables-carry-org-id": "error",
|
|
300
|
+
"biological-architecture/test-no-clock-polling-for-promise-flips": "error",
|
|
263
301
|
"biological-architecture/time-through-the-door": [
|
|
264
302
|
"error",
|
|
265
303
|
{
|
|
266
304
|
"door": "(?:__fixtures__|corpus)/time/door\\.ts$",
|
|
267
|
-
"
|
|
268
|
-
"
|
|
305
|
+
"exemptModules": [
|
|
306
|
+
"time/generated/from-openapi.ts"
|
|
269
307
|
]
|
|
270
308
|
}
|
|
271
309
|
],
|
|
@@ -310,8 +348,8 @@
|
|
|
310
348
|
"body",
|
|
311
349
|
"display"
|
|
312
350
|
],
|
|
313
|
-
"
|
|
314
|
-
"
|
|
351
|
+
"exemptModules": [
|
|
352
|
+
"tokens/theme/palette.tsx"
|
|
315
353
|
]
|
|
316
354
|
}
|
|
317
355
|
],
|
|
@@ -322,8 +360,8 @@
|
|
|
322
360
|
"--mc-",
|
|
323
361
|
"--theme-"
|
|
324
362
|
],
|
|
325
|
-
"
|
|
326
|
-
"
|
|
363
|
+
"exemptModules": [
|
|
364
|
+
"tokens/theme/palette.tsx"
|
|
327
365
|
]
|
|
328
366
|
}
|
|
329
367
|
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// ACCEPTED: one carries a handler, one hands the press to the child, one is the form's submit.
|
|
2
|
+
import { Button } from '@kit/ui/atoms/button'
|
|
3
|
+
|
|
4
|
+
export const Downloads = ({ download }: { download: () => void }): JSX.Element => (
|
|
5
|
+
<form>
|
|
6
|
+
<Button onClick={download}>Download</Button>
|
|
7
|
+
<Button asChild>
|
|
8
|
+
<a href="/dieline.pdf">Open</a>
|
|
9
|
+
</Button>
|
|
10
|
+
<Button type="submit">Save</Button>
|
|
11
|
+
</form>
|
|
12
|
+
)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// BREACH, one file sideways: the read the route delegates, narrowed to nobody.
|
|
2
|
+
export const findOrders = async (query: {
|
|
3
|
+
graph: (c: unknown) => Promise<{ data: unknown[] }>
|
|
4
|
+
}): Promise<unknown[]> => {
|
|
5
|
+
const { data } = await query.graph({ entity: 'order', fields: ['id'] })
|
|
6
|
+
|
|
7
|
+
return data
|
|
8
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// BREACH: the route itself names no entity — the read is in the module beside it.
|
|
2
|
+
import { findOrders } from './find-orders'
|
|
3
|
+
|
|
4
|
+
export async function GET(req: unknown, res: { json: (b: unknown) => void }): Promise<void> {
|
|
5
|
+
const query = { graph: async (_c: unknown) => ({ data: [] as unknown[] }) }
|
|
6
|
+
res.json({ orders: await findOrders(query) })
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// ACCEPTED: a public route scoped by caller-supplied evidence — a reference and an email.
|
|
2
|
+
export const findTrackedOrder = async (
|
|
3
|
+
query: { graph: (c: unknown) => Promise<{ data: unknown[] }> },
|
|
4
|
+
input: { email: string; reference: string },
|
|
5
|
+
): Promise<unknown> => {
|
|
6
|
+
assertTrackingEvidence(input)
|
|
7
|
+
const { data } = await query.graph({ entity: 'order', fields: ['id'] })
|
|
8
|
+
|
|
9
|
+
return data[0]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare function assertTrackingEvidence(input: { email: string; reference: string }): void
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// ACCEPTED: the evidence check the config names stands in for a session.
|
|
2
|
+
import { findTrackedOrder } from './find-tracked-order'
|
|
3
|
+
|
|
4
|
+
export async function GET(
|
|
5
|
+
req: { body: { email: string; reference: string } },
|
|
6
|
+
res: { json: (b: unknown) => void },
|
|
7
|
+
): Promise<void> {
|
|
8
|
+
const query = { graph: async (_c: unknown) => ({ data: [] as unknown[] }) }
|
|
9
|
+
res.json({ order: await findTrackedOrder(query, req.body) })
|
|
10
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// BREACH: "newest first" becomes "starts with F" — the sort is stable, plausible and wrong.
|
|
2
|
+
type Load = { created_at: Date; id: string; updatedAt: Date }
|
|
3
|
+
|
|
4
|
+
export const newestFirst = (loads: Load[]): Load[] =>
|
|
5
|
+
[...loads].sort((a, b) => String(b.created_at).localeCompare(String(a.created_at)))
|
|
6
|
+
|
|
7
|
+
export const changedSince = (load: Load, cut: string): boolean => `${load.updatedAt}` > cut
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// ACCEPTED: one orders by the time, the other by the ISO string the API returned.
|
|
2
|
+
type Load = { created_at: Date; id: string; shipped_at: string }
|
|
3
|
+
|
|
4
|
+
export const newestFirst = (loads: Load[]): Load[] =>
|
|
5
|
+
[...loads].sort((a, b) => b.created_at.getTime() - a.created_at.getTime())
|
|
6
|
+
|
|
7
|
+
export const shippedSince = (load: Load, cut: string): boolean => load.shipped_at > cut
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createWorkflow } from '@corpus/workflows'
|
|
2
|
+
|
|
3
|
+
// ACCEPTED: `q` is the engine's step proxy, so every call through it is a step — journalled under
|
|
4
|
+
// its own name and answered from the record on a replay.
|
|
5
|
+
export const settle = createWorkflow(
|
|
6
|
+
'invoice.settle',
|
|
7
|
+
async (id: string, ctx: { q: { getInvoice: (id: string) => Promise<{ status: string }> } }) => {
|
|
8
|
+
const doc = await ctx.q.getInvoice(id)
|
|
9
|
+
|
|
10
|
+
return doc.status
|
|
11
|
+
},
|
|
12
|
+
{ durable: true },
|
|
13
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// ACCEPTED: the failure is written where the caller reads it, and the other one is rethrown.
|
|
2
|
+
export const refresh = (
|
|
3
|
+
load: () => Promise<void>,
|
|
4
|
+
setError: (message: string) => void,
|
|
5
|
+
): void => {
|
|
6
|
+
load().catch((error: Error) => {
|
|
7
|
+
setError(error.message)
|
|
8
|
+
})
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const reload = async (load: () => Promise<void>): Promise<void> => {
|
|
12
|
+
try {
|
|
13
|
+
await load()
|
|
14
|
+
} catch (error) {
|
|
15
|
+
throw error
|
|
16
|
+
}
|
|
17
|
+
}
|
package/corpus/manifest.json
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"biological-architecture/emit-declares-attempts",
|
|
20
20
|
"biological-architecture/font-roles-only",
|
|
21
21
|
"biological-architecture/layer-walls",
|
|
22
|
+
"biological-architecture/list-take-without-order",
|
|
22
23
|
"biological-architecture/max-comment-density",
|
|
23
24
|
"biological-architecture/molecule-atoms-only",
|
|
24
25
|
"biological-architecture/molecule-must-compose",
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
"biological-architecture/no-card-shaped-div",
|
|
30
31
|
"biological-architecture/no-cross-feature-stores",
|
|
31
32
|
"biological-architecture/no-d1-transaction",
|
|
33
|
+
"biological-architecture/no-date-string-compare",
|
|
32
34
|
"biological-architecture/no-duplicate-jsx-patterns",
|
|
35
|
+
"biological-architecture/no-generic-utility-package",
|
|
33
36
|
"biological-architecture/no-hook-in-component-disguise",
|
|
34
37
|
"biological-architecture/no-index-count-as-exact",
|
|
35
38
|
"biological-architecture/no-inert-hidden-jsx",
|
|
@@ -44,6 +47,8 @@
|
|
|
44
47
|
"biological-architecture/no-react-namespace",
|
|
45
48
|
"biological-architecture/no-renamed-html-props",
|
|
46
49
|
"biological-architecture/no-render-prop-reader",
|
|
50
|
+
"biological-architecture/no-runtime-dead-affordance",
|
|
51
|
+
"biological-architecture/no-swallowed-catch",
|
|
47
52
|
"biological-architecture/no-trivial-wrapper-component",
|
|
48
53
|
"biological-architecture/no-ts-in-bio-folders",
|
|
49
54
|
"biological-architecture/no-type-definitions-in-components",
|
|
@@ -66,6 +71,7 @@
|
|
|
66
71
|
"biological-architecture/subscriber-declares-id",
|
|
67
72
|
"biological-architecture/tables-declare-their-plane",
|
|
68
73
|
"biological-architecture/tenant-tables-carry-org-id",
|
|
74
|
+
"biological-architecture/test-no-clock-polling-for-promise-flips",
|
|
69
75
|
"biological-architecture/time-through-the-door",
|
|
70
76
|
"biological-architecture/tissue-must-compose",
|
|
71
77
|
"biological-architecture/tissue-no-data-props",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// BREACH: the stage before this one wrote the plan, and this page never sees it.
|
|
2
|
+
declare const query: { graph: (config: unknown) => Promise<{ data: unknown[] }> }
|
|
3
|
+
declare function listPlannedOrders(filters: unknown, config: unknown): Promise<unknown[]>
|
|
4
|
+
|
|
5
|
+
export const latestPlan = async (orderId: string): Promise<unknown> => {
|
|
6
|
+
const { data } = await query.graph({
|
|
7
|
+
entity: 'planned_order',
|
|
8
|
+
fields: ['id'],
|
|
9
|
+
filters: { order_id: orderId },
|
|
10
|
+
pagination: { take: 1 },
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
return data[0]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const firstOpen = async (orderId: string): Promise<unknown> => {
|
|
17
|
+
const rows = await listPlannedOrders({ order_id: orderId }, { take: 1 })
|
|
18
|
+
|
|
19
|
+
return rows[0]
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// ACCEPTED: the page names the column it is a page of, so the first row is the first row.
|
|
2
|
+
declare const query: { graph: (config: unknown) => Promise<{ data: unknown[] }> }
|
|
3
|
+
declare function listPlannedOrders(filters: unknown, config: unknown): Promise<unknown[]>
|
|
4
|
+
|
|
5
|
+
export const latestPlan = async (orderId: string): Promise<unknown> => {
|
|
6
|
+
const { data } = await query.graph({
|
|
7
|
+
entity: 'planned_order',
|
|
8
|
+
fields: ['id'],
|
|
9
|
+
filters: { order_id: orderId },
|
|
10
|
+
pagination: { order: { created_at: 'DESC' }, take: 1 },
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
return data[0]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const firstOpen = async (orderId: string): Promise<unknown> => {
|
|
17
|
+
const rows = await listPlannedOrders(
|
|
18
|
+
{ order_id: orderId },
|
|
19
|
+
{ order: { created_at: 'ASC' }, take: 1 },
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return rows[0]
|
|
23
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// BREACH: named for nothing, so nothing can be refused entry and everything arrived.
|
|
2
|
+
export const formatMoney = (cents: number): string => `${(cents / 100).toFixed(2)}`
|
|
3
|
+
export const SUPPORT_EMAIL = 'support@corpus.example'
|
|
4
|
+
export const slugify = (value: string): string => value.toLowerCase().replaceAll(' ', '-')
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// ACCEPTED: the promise is awaited where it was created, and the assertion runs once after it.
|
|
2
|
+
declare function waitFor(check: () => void): Promise<void>
|
|
3
|
+
declare function expect(value: unknown): { toBe: (other: unknown) => void }
|
|
4
|
+
|
|
5
|
+
export const savesTheCart = async (
|
|
6
|
+
save: () => Promise<void>,
|
|
7
|
+
subject: { done: boolean },
|
|
8
|
+
): Promise<void> => {
|
|
9
|
+
await save()
|
|
10
|
+
expect(subject.done).toBe(true)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const rendersTheRow = async (subject: { done: boolean }): Promise<void> => {
|
|
14
|
+
await waitFor(() => {
|
|
15
|
+
expect(subject.done).toBe(true)
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// BREACH: the test holds the promise and polls the clock for the flip it decides.
|
|
2
|
+
declare function waitFor(check: () => void): Promise<void>
|
|
3
|
+
declare function expect(value: unknown): { toBe: (other: unknown) => void }
|
|
4
|
+
|
|
5
|
+
export const savesTheCart = async (
|
|
6
|
+
save: () => Promise<void>,
|
|
7
|
+
subject: { done: boolean },
|
|
8
|
+
): Promise<void> => {
|
|
9
|
+
const settled = save()
|
|
10
|
+
await waitFor(() => {
|
|
11
|
+
expect(subject.done).toBe(true)
|
|
12
|
+
})
|
|
13
|
+
await settled
|
|
14
|
+
}
|
|
@@ -25,6 +25,7 @@ var FRONTEND = [
|
|
|
25
25
|
"no-react-namespace",
|
|
26
26
|
"no-renamed-html-props",
|
|
27
27
|
"no-render-prop-reader",
|
|
28
|
+
"no-runtime-dead-affordance",
|
|
28
29
|
"no-trivial-wrapper-component",
|
|
29
30
|
"no-ts-in-bio-folders",
|
|
30
31
|
"no-type-definitions-in-components",
|
|
@@ -45,6 +46,7 @@ var BACKEND_WORKFLOWS = [
|
|
|
45
46
|
"documents-share-one-table",
|
|
46
47
|
"durable-body-reads-through-steps",
|
|
47
48
|
"mutating-step-declares-retry",
|
|
49
|
+
"no-date-string-compare",
|
|
48
50
|
"no-orm-outside-db",
|
|
49
51
|
"no-raw-sql-outside-allowed",
|
|
50
52
|
"no-void-port",
|
|
@@ -71,6 +73,7 @@ var announceRename = (from) => {
|
|
|
71
73
|
};
|
|
72
74
|
var BACKEND_MEDUSA = [
|
|
73
75
|
"emit-declares-attempts",
|
|
76
|
+
"list-take-without-order",
|
|
74
77
|
"mutating-step-declares-retry",
|
|
75
78
|
"named-when-block",
|
|
76
79
|
"no-index-count-as-exact",
|
|
@@ -83,6 +86,7 @@ var BACKEND_MEDUSA = [
|
|
|
83
86
|
"subscriber-declares-id",
|
|
84
87
|
"unique-query-step-name"
|
|
85
88
|
];
|
|
89
|
+
var FAILURE_PATHS = ["no-swallowed-catch"];
|
|
86
90
|
var INTEGRATIONS = ["no-unregistered-plugin-dir"];
|
|
87
91
|
var BACKEND_TRPC = ["router-schema-parity"];
|
|
88
92
|
var TENANT_SCOPING = [
|
|
@@ -91,9 +95,9 @@ var TENANT_SCOPING = [
|
|
|
91
95
|
"tables-declare-their-plane",
|
|
92
96
|
"tenant-tables-carry-org-id"
|
|
93
97
|
];
|
|
94
|
-
var TOOLING = ["layer-walls", "todo-names-its-plan"];
|
|
98
|
+
var TOOLING = ["layer-walls", "no-generic-utility-package", "todo-names-its-plan"];
|
|
95
99
|
var THEMEKIT = ["font-roles-only", "tokens-only-colors"];
|
|
96
|
-
var TESTBED = ["no-mock-db-in-integration"];
|
|
100
|
+
var TESTBED = ["no-mock-db-in-integration", "test-no-clock-polling-for-promise-flips"];
|
|
97
101
|
var PACKAGE_SUBPATHS = ["subpath-over-barrel"];
|
|
98
102
|
var RULE_PREFIX = "biological-architecture";
|
|
99
103
|
var asRules = (names) => Object.fromEntries(names.map((name) => [`${RULE_PREFIX}/${name}`, "error"]));
|
|
@@ -123,6 +127,7 @@ var PRESETS = {
|
|
|
123
127
|
"backend-workflows": { rules: asRules(BACKEND_WORKFLOWS) },
|
|
124
128
|
"backend-workflows-cf": { rules: asRules(BACKEND_WORKFLOWS_CF) },
|
|
125
129
|
"comment-ceiling": COMMENT_CEILING,
|
|
130
|
+
"failure-paths": { rules: asRules(FAILURE_PATHS) },
|
|
126
131
|
frontend: { rules: asRules(FRONTEND) },
|
|
127
132
|
integrations: { rules: asRules(INTEGRATIONS) },
|
|
128
133
|
"package-subpaths": { rules: asRules(PACKAGE_SUBPATHS) },
|