@geonosis/oxlint-plugin-biological-architecture 0.5.0 → 1.1.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.
Files changed (68) hide show
  1. package/README.md +13 -1
  2. package/corpus/.oxlintrc.json +97 -2
  3. package/corpus/emits/bad-opaque-budget.ts +13 -0
  4. package/corpus/emits/good-budget-helper.ts +12 -0
  5. package/corpus/emits/retry.ts +10 -0
  6. package/corpus/integrations/providers/attio/index.ts +1 -0
  7. package/corpus/integrations/providers/dead-cal/index.ts +3 -0
  8. package/corpus/integrations/providers/email-gmail.ts +3 -0
  9. package/corpus/integrations/providers/hubspot/index.ts +1 -0
  10. package/corpus/integrations/registry.ts +9 -0
  11. package/corpus/manifest.json +15 -0
  12. package/corpus/medusa/api/admin/labelled/route.ts +12 -0
  13. package/corpus/medusa/api/admin/orders/route.ts +11 -0
  14. package/corpus/medusa/jobs/index.ts +1 -0
  15. package/corpus/medusa/jobs/reconcile-nightly.ts +7 -0
  16. package/corpus/medusa/modules/catalog/index.ts +7 -0
  17. package/corpus/medusa/modules/search/index.ts +7 -0
  18. package/corpus/medusa/plugins/b2b/src/api/admin/b2b/notes/route.ts +12 -0
  19. package/corpus/medusa/plugins/b2b/src/api/admin/b2b/orders/route.ts +9 -0
  20. package/corpus/medusa/plugins/b2b/src/api/admin/b2b/quotes/route.ts +6 -0
  21. package/corpus/medusa/plugins/b2b/src/api/hooks/stripe/route.ts +3 -0
  22. package/corpus/medusa/plugins/b2b/src/api/store/b2b/companies/route.ts +6 -0
  23. package/corpus/medusa/plugins/b2b/src/api/store/route.ts +3 -0
  24. package/corpus/medusa/subscribers/bad-inferred-id.ts +7 -0
  25. package/corpus/medusa/subscribers/good-declared-id.ts +10 -0
  26. package/corpus/medusa/subscribers/index.ts +10 -0
  27. package/corpus/medusa/workflows/bad-duplicate-query-step.ts +8 -0
  28. package/corpus/medusa/workflows/bad-place-order.ts +7 -0
  29. package/corpus/medusa/workflows/bad-shared-query-step-name.ts +8 -0
  30. package/corpus/medusa/workflows/bad-unnamed-when.ts +7 -0
  31. package/corpus/medusa/workflows/good-flagged-step.ts +10 -0
  32. package/corpus/medusa/workflows/good-named-query-steps.ts +8 -0
  33. package/corpus/medusa/workflows/good-named-when.ts +7 -0
  34. package/corpus/medusa/workflows/good-place-order.ts +15 -0
  35. package/corpus/medusa/workflows/good-single-query-step.ts +7 -0
  36. package/corpus/testbed/__tests__/integration/checkout/tests.ts +11 -0
  37. package/corpus/testbed/__tests__/integration/orders/tests.ts +9 -0
  38. package/corpus/testbed/__tests__/unit/checkout/tests.ts +10 -0
  39. package/corpus/tokens/bad-arbitrary-class.tsx +3 -0
  40. package/corpus/tokens/bad-asserted-style.tsx +5 -0
  41. package/corpus/tokens/bad-font-literal.tsx +5 -0
  42. package/corpus/tokens/bad-font-undeclared-role.tsx +3 -0
  43. package/corpus/tokens/bad-foreign-variable.tsx +3 -0
  44. package/corpus/tokens/bad-literal-style.tsx +3 -0
  45. package/corpus/tokens/bad-shorthand-style.tsx +5 -0
  46. package/corpus/tokens/good-arbitrary-non-color.tsx +3 -0
  47. package/corpus/tokens/good-font-role.tsx +5 -0
  48. package/corpus/tokens/good-local-variable.tsx +11 -0
  49. package/corpus/tokens/good-token-style.tsx +8 -0
  50. package/corpus/tokens/order-status.tsx +217 -0
  51. package/corpus/tokens/theme/palette.tsx +7 -0
  52. package/corpus/trpc/routers/_app.ts +2 -0
  53. package/corpus/trpc/routers/documents-mounted.ts +7 -0
  54. package/corpus/trpc/routers/health.ts +3 -0
  55. package/corpus/trpc/routers/orphan.ts +2 -0
  56. package/corpus/trpc/routers/vault.ts +3 -0
  57. package/corpus/trpc/schemas/health.ts +1 -0
  58. package/corpus/trpc/schemas/index.ts +1 -0
  59. package/corpus/trpc/schemas/invoice.ts +1 -0
  60. package/corpus/trpc/schemas/purchase-order.ts +1 -0
  61. package/corpus/trpc/schemas/unserved.ts +2 -0
  62. package/corpus/trpc/schemas/vault.ts +1 -0
  63. package/dist/{chunk-RQQKQPIU.js → chunk-UVENNNFM.js} +22 -1
  64. package/dist/index.d.ts +41 -0
  65. package/dist/index.js +2004 -30
  66. package/dist/presets.d.ts +12 -0
  67. package/dist/presets.js +1 -1
  68. package/package.json +15 -5
package/README.md CHANGED
@@ -154,7 +154,19 @@ Two more facts a fork's config will trip on:
154
154
  namespace is the plugin's identity, not the package's, so renaming or re-scoping the package does
155
155
  not rename a single rule id in a single consumer config.
156
156
 
157
- ### Last step of every bump — verify the loaded version, per workspace
157
+ ### Last step of every bump — `geonosis-doctor`
158
+
159
+ ```bash
160
+ pnpm add -D @geonosis/doctor
161
+ npx geonosis-doctor
162
+ ```
163
+
164
+ It answers everything below for every config in the tree, and three more questions besides — see
165
+ [`@geonosis/doctor`](https://www.npmjs.com/package/@geonosis/doctor). Run it after every bump and in
166
+ CI. What follows is the reasoning it automates, kept because a check nobody understands is a check
167
+ nobody trusts.
168
+
169
+ #### Why: declared is not loaded
158
170
 
159
171
  **Declared is not loaded.** oxlint resolves a `jsPlugins` specifier from the CONFIG FILE's
160
172
  directory, so a nested `apps/<ws>/node_modules/@geonosis/…` left behind at the old version means
@@ -43,7 +43,14 @@
43
43
  }
44
44
  ],
45
45
  "biological-architecture/effect-hook-naming": "error",
46
- "biological-architecture/emit-declares-attempts": "error",
46
+ "biological-architecture/emit-declares-attempts": [
47
+ "error",
48
+ {
49
+ "budgetHelpers": [
50
+ "retryableEvent"
51
+ ]
52
+ }
53
+ ],
47
54
  "biological-architecture/layer-walls": [
48
55
  "error",
49
56
  {
@@ -80,6 +87,8 @@
80
87
  "biological-architecture/max-comment-density": "error",
81
88
  "biological-architecture/molecule-atoms-only": "error",
82
89
  "biological-architecture/molecule-must-compose": "error",
90
+ "biological-architecture/mutating-step-declares-retry": "error",
91
+ "biological-architecture/named-when-block": "error",
83
92
  "biological-architecture/next-route-segment-is-thin-delegate": "error",
84
93
  "biological-architecture/no-brand-names": [
85
94
  "error",
@@ -97,10 +106,26 @@
97
106
  "biological-architecture/no-d1-transaction": "error",
98
107
  "biological-architecture/no-duplicate-jsx-patterns": "error",
99
108
  "biological-architecture/no-hook-in-component-disguise": "error",
109
+ "biological-architecture/no-index-count-as-exact": "error",
100
110
  "biological-architecture/no-inert-hidden-jsx": "error",
101
111
  "biological-architecture/no-inline-data-in-jsx": "error",
102
112
  "biological-architecture/no-invalid-feature-folders": "error",
113
+ "biological-architecture/no-loader-side-effect-in-index-file": "error",
103
114
  "biological-architecture/no-logic-in-component-files": "error",
115
+ "biological-architecture/no-mock-db-in-integration": [
116
+ "error",
117
+ {
118
+ "dbModules": [
119
+ "@fixture/db"
120
+ ],
121
+ "integrationDirs": [
122
+ "__tests__/integration"
123
+ ],
124
+ "mockNames": [
125
+ "mockDb"
126
+ ]
127
+ }
128
+ ],
104
129
  "biological-architecture/no-orm-outside-db": "error",
105
130
  "biological-architecture/no-raw-html-atoms": [
106
131
  "error",
@@ -119,6 +144,18 @@
119
144
  "biological-architecture/no-trivial-wrapper-component": "error",
120
145
  "biological-architecture/no-ts-in-bio-folders": "error",
121
146
  "biological-architecture/no-type-definitions-in-components": "error",
147
+ "biological-architecture/no-unregistered-plugin-dir": [
148
+ "error",
149
+ {
150
+ "roots": [
151
+ "integrations/providers"
152
+ ],
153
+ "registry": "integrations/registry.ts",
154
+ "manifests": [
155
+ "index.ts"
156
+ ]
157
+ }
158
+ ],
122
159
  "biological-architecture/no-void-port": "error",
123
160
  "biological-architecture/organelle-dependency": [
124
161
  "error",
@@ -129,10 +166,42 @@
129
166
  }
130
167
  ],
131
168
  "biological-architecture/organelle-single-source": "error",
169
+ "biological-architecture/plugin-route-namespaced": [
170
+ "error",
171
+ {
172
+ "packages": [
173
+ {
174
+ "under": "medusa/plugins",
175
+ "name": "@acme/{dir}",
176
+ "namespaced": true
177
+ }
178
+ ]
179
+ }
180
+ ],
132
181
  "biological-architecture/queries-require-org-scope": "error",
133
182
  "biological-architecture/queue-loop-is-the-library": "error",
183
+ "biological-architecture/route-no-inline-mutation": "error",
184
+ "biological-architecture/router-schema-parity": [
185
+ "error",
186
+ {
187
+ "routers": "trpc/routers",
188
+ "schemas": "trpc/schemas",
189
+ "ignore": [
190
+ "_app",
191
+ "index"
192
+ ],
193
+ "mounts": {
194
+ "documents-mounted": [
195
+ "invoice",
196
+ "purchase-order"
197
+ ]
198
+ }
199
+ }
200
+ ],
201
+ "biological-architecture/service-name-not-reserved": "error",
134
202
  "biological-architecture/ssot-no-inline-facts": "error",
135
203
  "biological-architecture/ssot-no-process-env": "error",
204
+ "biological-architecture/step-declares-compensation-or-none": "error",
136
205
  "biological-architecture/step-opens-its-own-cell": [
137
206
  "error",
138
207
  {
@@ -142,6 +211,7 @@
142
211
  }
143
212
  ],
144
213
  "biological-architecture/store-route-scopes-tenant-data": "error",
214
+ "biological-architecture/subscriber-declares-id": "error",
145
215
  "biological-architecture/tables-declare-their-plane": "error",
146
216
  "biological-architecture/tenant-tables-carry-org-id": "error",
147
217
  "biological-architecture/time-through-the-door": "error",
@@ -150,7 +220,32 @@
150
220
  "biological-architecture/tissue-no-hooks": "error",
151
221
  "biological-architecture/tissue-no-organelles": "error",
152
222
  "biological-architecture/tissue-no-stores": "error",
223
+ "biological-architecture/unique-query-step-name": "error",
153
224
  "biological-architecture/worker-handles-are-scoped": "error",
154
- "biological-architecture/zustand-v5-best-practices": "error"
225
+ "biological-architecture/zustand-v5-best-practices": "error",
226
+ "biological-architecture/font-roles-only": [
227
+ "error",
228
+ {
229
+ "roles": [
230
+ "body",
231
+ "display"
232
+ ],
233
+ "allow": [
234
+ "__fixtures__/tokens/theme/"
235
+ ]
236
+ }
237
+ ],
238
+ "biological-architecture/tokens-only-colors": [
239
+ "error",
240
+ {
241
+ "tokenPrefix": [
242
+ "--mc-",
243
+ "--theme-"
244
+ ],
245
+ "allow": [
246
+ "__fixtures__/tokens/theme/"
247
+ ]
248
+ }
249
+ ]
155
250
  }
156
251
  }
@@ -0,0 +1,13 @@
1
+ import { emitEventStep } from '@medusajs/medusa/core-flows'
2
+
3
+ import { withDefaults } from './retry'
4
+
5
+ // A call the repo has NOT named as a budget builder. Nothing here can tell whether it produces
6
+ // `attempts > 1`, and before `budgetHelpers` existed this passed silently along with every other
7
+ // helper call — which is how a workspace of 54 wrapped emits got zero findings and no coverage.
8
+ export const emitCacheWarmed = (data: { key: string }) =>
9
+ emitEventStep({
10
+ data,
11
+ eventName: 'cache.warmed',
12
+ options: withDefaults({ priority: 10 }),
13
+ })
@@ -0,0 +1,12 @@
1
+ import { emitEventStep } from '@medusajs/medusa/core-flows'
2
+
3
+ import { retryableEvent } from './retry'
4
+
5
+ // The shape the consumer actually writes: all 54 of its emit sites go through this helper, which
6
+ // throws on `attempts <= 1`. Named in `budgetHelpers`, so the call IS a budget.
7
+ export const emitQuoteAccepted = (data: { quote_id: string }) =>
8
+ emitEventStep({
9
+ data,
10
+ eventName: 'quote.accepted',
11
+ options: retryableEvent({ priority: 10 }),
12
+ })
@@ -1,3 +1,13 @@
1
1
  // The shared retry budgets. One place, so a change to what "background" means reaches every emit.
2
2
  export const RETRY_BACKGROUND = { attempts: 5, backoff: 2000 }
3
3
  export const RETRY_CRITICAL = { attempts: 9, backoff: 500 }
4
+
5
+ // The budget builder, which throws on `attempts <= 1` — naming it in `budgetHelpers` is what turns
6
+ // a call the rule cannot read into a call it can accept.
7
+ export const retryableEvent = (options: Record<string, unknown> = {}) => ({
8
+ attempts: RETRY_BACKGROUND.attempts,
9
+ ...options,
10
+ })
11
+
12
+ // A wrapper that is NOT a budget builder.
13
+ export const withDefaults = (options: Record<string, unknown> = {}) => ({ ...options })
@@ -0,0 +1 @@
1
+ export const AttioProvider = { id: 'cp_attio' }
@@ -0,0 +1,3 @@
1
+ // Named nowhere in the registry beside it. Ships a manifest, is reached by nothing, and reads as
2
+ // an integration to anyone counting directories. Midday carries eight of these.
3
+ export const CalProvider = { id: 'cp_cal' }
@@ -0,0 +1,3 @@
1
+ // A provider that is a FILE, not a directory — dielime's messaging seam. Out of scope because
2
+ // nothing matches `<root>/<dir>/<manifest>`, not because of a special case.
3
+ export const emailGmail = { channel: 'email' }
@@ -0,0 +1 @@
1
+ export const HubspotProvider = { id: 'cp_hubspot' }
@@ -0,0 +1,9 @@
1
+ import { AttioProvider } from './providers/attio/index'
2
+
3
+ // Two of the three directories beside this file are named here. The third is `dead-cal`, which
4
+ // ships a manifest, is imported by nothing, and reads as an integration to anyone counting
5
+ // directories — Midday carries eight of these.
6
+ export const providers = {
7
+ cp_attio: AttioProvider,
8
+ cp_hubspot: 'providers/hubspot',
9
+ }
@@ -15,10 +15,13 @@
15
15
  "biological-architecture/documents-share-one-table",
16
16
  "biological-architecture/effect-hook-naming",
17
17
  "biological-architecture/emit-declares-attempts",
18
+ "biological-architecture/font-roles-only",
18
19
  "biological-architecture/layer-walls",
19
20
  "biological-architecture/max-comment-density",
20
21
  "biological-architecture/molecule-atoms-only",
21
22
  "biological-architecture/molecule-must-compose",
23
+ "biological-architecture/mutating-step-declares-retry",
24
+ "biological-architecture/named-when-block",
22
25
  "biological-architecture/next-route-segment-is-thin-delegate",
23
26
  "biological-architecture/no-brand-names",
24
27
  "biological-architecture/no-card-shaped-div",
@@ -26,10 +29,13 @@
26
29
  "biological-architecture/no-d1-transaction",
27
30
  "biological-architecture/no-duplicate-jsx-patterns",
28
31
  "biological-architecture/no-hook-in-component-disguise",
32
+ "biological-architecture/no-index-count-as-exact",
29
33
  "biological-architecture/no-inert-hidden-jsx",
30
34
  "biological-architecture/no-inline-data-in-jsx",
31
35
  "biological-architecture/no-invalid-feature-folders",
36
+ "biological-architecture/no-loader-side-effect-in-index-file",
32
37
  "biological-architecture/no-logic-in-component-files",
38
+ "biological-architecture/no-mock-db-in-integration",
33
39
  "biological-architecture/no-orm-outside-db",
34
40
  "biological-architecture/no-raw-html-atoms",
35
41
  "biological-architecture/no-raw-sql-outside-allowed",
@@ -39,15 +45,22 @@
39
45
  "biological-architecture/no-trivial-wrapper-component",
40
46
  "biological-architecture/no-ts-in-bio-folders",
41
47
  "biological-architecture/no-type-definitions-in-components",
48
+ "biological-architecture/no-unregistered-plugin-dir",
42
49
  "biological-architecture/no-void-port",
43
50
  "biological-architecture/organelle-dependency",
44
51
  "biological-architecture/organelle-single-source",
52
+ "biological-architecture/plugin-route-namespaced",
45
53
  "biological-architecture/queries-require-org-scope",
46
54
  "biological-architecture/queue-loop-is-the-library",
55
+ "biological-architecture/route-no-inline-mutation",
56
+ "biological-architecture/router-schema-parity",
57
+ "biological-architecture/service-name-not-reserved",
47
58
  "biological-architecture/ssot-no-inline-facts",
48
59
  "biological-architecture/ssot-no-process-env",
60
+ "biological-architecture/step-declares-compensation-or-none",
49
61
  "biological-architecture/step-opens-its-own-cell",
50
62
  "biological-architecture/store-route-scopes-tenant-data",
63
+ "biological-architecture/subscriber-declares-id",
51
64
  "biological-architecture/tables-declare-their-plane",
52
65
  "biological-architecture/tenant-tables-carry-org-id",
53
66
  "biological-architecture/time-through-the-door",
@@ -56,6 +69,8 @@
56
69
  "biological-architecture/tissue-no-hooks",
57
70
  "biological-architecture/tissue-no-organelles",
58
71
  "biological-architecture/tissue-no-stores",
72
+ "biological-architecture/tokens-only-colors",
73
+ "biological-architecture/unique-query-step-name",
59
74
  "biological-architecture/worker-handles-are-scoped",
60
75
  "biological-architecture/zustand-v5-best-practices"
61
76
  ]
@@ -0,0 +1,12 @@
1
+ export async function GET(req, res) {
2
+ const query = req.scope.resolve('query')
3
+ const { data: orders, metadata } = await query.index({ entity: 'order' })
4
+
5
+ res.json({
6
+ count: metadata?.estimate_count ?? orders.length,
7
+ count_is_estimate: true,
8
+ limit: 20,
9
+ offset: 0,
10
+ orders,
11
+ })
12
+ }
@@ -0,0 +1,11 @@
1
+ export async function GET(req, res) {
2
+ const query = req.scope.resolve('query')
3
+ const { data: orders, metadata } = await query.index({ entity: 'order' })
4
+
5
+ res.json({
6
+ count: metadata?.estimate_count ?? orders.length,
7
+ limit: 20,
8
+ offset: 0,
9
+ orders,
10
+ })
11
+ }
@@ -0,0 +1 @@
1
+ export * from './reconcile-nightly'
@@ -0,0 +1,7 @@
1
+ export default async function reconcileNightly(container) {
2
+ const ledger = container.resolve('ledger')
3
+
4
+ await ledger.reconcile()
5
+ }
6
+
7
+ export const config = { name: 'reconcile-nightly', schedule: '0 2 * * *' }
@@ -0,0 +1,7 @@
1
+ import { Module } from '@medusajs/framework/utils'
2
+
3
+ import { CatalogSearchModuleService } from './service'
4
+
5
+ export const SERVICE_NAME = 'catalog_search'
6
+
7
+ export default Module(SERVICE_NAME, { service: CatalogSearchModuleService })
@@ -0,0 +1,7 @@
1
+ import { Module } from '@medusajs/framework/utils'
2
+
3
+ import { SearchModuleService } from './service'
4
+
5
+ export const SERVICE_NAME = 'search'
6
+
7
+ export default Module(SERVICE_NAME, { service: SearchModuleService })
@@ -0,0 +1,12 @@
1
+ export async function POST(req, res) {
2
+ const conversations = req.scope.resolve('ai')
3
+
4
+ // arch:inline-mutation-ok(model-name patch-up on the row this handler just created)
5
+ await (
6
+ conversations as unknown as {
7
+ updateAiConversations: (data: Record<string, unknown>) => Promise<unknown>
8
+ }
9
+ ).updateAiConversations({ id: req.params.id, model: req.validatedBody.model })
10
+
11
+ res.json({ ok: true })
12
+ }
@@ -0,0 +1,9 @@
1
+ import { placeOrderWorkflow } from '../../../../workflows/place-order'
2
+
3
+ export async function POST(req, res) {
4
+ const { result } = await placeOrderWorkflow(req.scope).run({ input: req.validatedBody })
5
+ const quotes = req.scope.resolve('quote')
6
+ const existing = await quotes.listQuotes({}, { take: 5 })
7
+
8
+ res.json({ existing, result })
9
+ }
@@ -0,0 +1,6 @@
1
+ export async function POST(req, res) {
2
+ const quotes = req.scope.resolve('quote')
3
+ const quote = await quotes.createQuotes(req.validatedBody)
4
+
5
+ res.json({ quote })
6
+ }
@@ -0,0 +1,3 @@
1
+ export async function POST(req, res) {
2
+ res.json({ received: true })
3
+ }
@@ -0,0 +1,6 @@
1
+ export async function GET(req, res) {
2
+ const query = req.scope.resolve('query')
3
+ const { data: companies } = await query.graph({ entity: 'company' })
4
+
5
+ res.json({ companies })
6
+ }
@@ -0,0 +1,3 @@
1
+ export async function GET(req, res) {
2
+ res.json({ ok: true })
3
+ }
@@ -0,0 +1,7 @@
1
+ export default async function orderPlaced({ event, container }) {
2
+ const notifications = container.resolve('notification')
3
+
4
+ await notifications.createNotifications({ to: event.data.email })
5
+ }
6
+
7
+ export const config = { event: 'order.placed' }
@@ -0,0 +1,10 @@
1
+ export default async function orderShipped({ event, container }) {
2
+ const notifications = container.resolve('notification')
3
+
4
+ await notifications.createNotifications({ to: event.data.email })
5
+ }
6
+
7
+ export const config = {
8
+ context: { subscriberId: 'order-shipped-notify' },
9
+ event: 'order.shipped',
10
+ }
@@ -0,0 +1,10 @@
1
+ export default async function orderCancelled({ event, container }) {
2
+ const notifications = container.resolve('notification')
3
+
4
+ await notifications.createNotifications({ to: event.data.email })
5
+ }
6
+
7
+ export const config = {
8
+ context: { subscriberId: 'order-cancelled-notify' },
9
+ event: 'order.cancelled',
10
+ }
@@ -0,0 +1,8 @@
1
+ import { createWorkflow, useQueryGraphStep, WorkflowResponse } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const readTwice = createWorkflow('read-twice', () => {
4
+ const customer = useQueryGraphStep({ entity: 'customer' }).config({ name: 'get-customer' })
5
+ const orders = useQueryGraphStep({ entity: 'order' })
6
+
7
+ return new WorkflowResponse({ customer, orders })
8
+ })
@@ -0,0 +1,7 @@
1
+ import { createStep } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const placeOrder = createStep('place-order', async ({ input }, { container }) => {
4
+ const orders = container.resolve('order')
5
+
6
+ return await orders.createOrders(input)
7
+ })
@@ -0,0 +1,8 @@
1
+ import { createWorkflow, useRemoteQueryStep, WorkflowResponse } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const readBoth = createWorkflow('read-both', () => {
4
+ const customer = useRemoteQueryStep({ entity: 'customer' }).config({ name: 'dup' })
5
+ const orders = useRemoteQueryStep({ entity: 'order' }).config({ name: 'dup' })
6
+
7
+ return new WorkflowResponse({ customer, orders })
8
+ })
@@ -0,0 +1,7 @@
1
+ import { createWorkflow, when } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const shipOrder = createWorkflow('ship-order', (input) => {
4
+ when(input, (values) => values.needsLabel).then(() => {
5
+ return buyLabel(input)
6
+ })
7
+ })
@@ -0,0 +1,10 @@
1
+ import { createStep } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const notifyOps = createStep(
4
+ { maxRetries: 5, name: 'notify-ops', noCompensation: true },
5
+ async ({ input }, { container }) => {
6
+ const notifications = container.resolve('notification')
7
+
8
+ await notifications.createNotifications(input)
9
+ },
10
+ )
@@ -0,0 +1,8 @@
1
+ import { createWorkflow, useQueryGraphStep, WorkflowResponse } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const readTwice = createWorkflow('read-twice', () => {
4
+ const customer = useQueryGraphStep({ entity: 'customer' }).config({ name: 'get-customer' })
5
+ const orders = useQueryGraphStep({ entity: 'order' }).config({ name: 'get-orders' })
6
+
7
+ return new WorkflowResponse({ customer, orders })
8
+ })
@@ -0,0 +1,7 @@
1
+ import { createWorkflow, when } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const shipOrderNamed = createWorkflow('ship-order-named', (input) => {
4
+ when('needs-label', input, (values) => values.needsLabel).then(() => {
5
+ return buyLabel(input)
6
+ })
7
+ })
@@ -0,0 +1,15 @@
1
+ import { createStep } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const placeOrder = createStep(
4
+ { maxRetries: 3, name: 'place-order' },
5
+ async ({ input }, { container }) => {
6
+ const orders = container.resolve('order')
7
+
8
+ return await orders.createOrders(input)
9
+ },
10
+ async ({ id }, { container }) => {
11
+ const orders = container.resolve('order')
12
+
13
+ await orders.deleteOrders(id)
14
+ },
15
+ )
@@ -0,0 +1,7 @@
1
+ import { createWorkflow, useQueryGraphStep, WorkflowResponse } from '@medusajs/framework/workflows-sdk'
2
+
3
+ export const readOnce = createWorkflow('read-once', () => {
4
+ const customer = useQueryGraphStep({ entity: 'customer' })
5
+
6
+ return new WorkflowResponse(customer)
7
+ })
@@ -0,0 +1,11 @@
1
+ // An integration suite that mocks the database it exists to exercise. Midday's shape: the suite
2
+ // then proves that the procedure calls what it says it calls, and nothing about what comes back.
3
+ import { vi } from 'vitest'
4
+
5
+ import { listOrders } from '@fixture/db'
6
+
7
+ vi.mock('@fixture/db')
8
+
9
+ export const testListsOrders = async () => {
10
+ await listOrders()
11
+ }
@@ -0,0 +1,9 @@
1
+ // The other shape: no mock call to see. A handle built in a setup file, imported by name, and used
2
+ // as the database. Two places, and the import binding is ONE of them however the AST spells it.
3
+ import { mockDb } from '@fixture/db'
4
+
5
+ export const testCountsOrders = async () => {
6
+ const rows = await mockDb.select()
7
+
8
+ return rows.length
9
+ }
@@ -0,0 +1,10 @@
1
+ // The same mock, in a unit test, where it is correct: a unit test mocks everything by definition.
2
+ import { vi } from 'vitest'
3
+
4
+ import { listOrders } from '@fixture/db'
5
+
6
+ vi.mock('@fixture/db')
7
+
8
+ export const testListsOrders = async () => {
9
+ await listOrders()
10
+ }
@@ -0,0 +1,3 @@
1
+ export const Ribbon = ({ label }: { label: string }) => (
2
+ <div className="bg-[#ffe849] text-[oklch(0.22_0.02_140)] px-2 py-1">{label}</div>
3
+ )
@@ -0,0 +1,5 @@
1
+ import type { CSSProperties } from 'react'
2
+
3
+ export const Asserted = ({ label }: { label: string }) => (
4
+ <span style={{ color: '#ffe849' } as CSSProperties}>{label}</span>
5
+ )
@@ -0,0 +1,5 @@
1
+ export const Quote = ({ text }: { text: string }) => (
2
+ <blockquote className="font-[Georgia] text-lg" style={{ fontFamily: 'Georgia, serif' }}>
3
+ {text}
4
+ </blockquote>
5
+ )
@@ -0,0 +1,3 @@
1
+ export const Signature = ({ name }: { name: string }) => (
2
+ <p style={{ fontFamily: 'var(--font-handwriting)' }}>{name}</p>
3
+ )
@@ -0,0 +1,3 @@
1
+ export const LegacyBadge = ({ label }: { label: string }) => (
2
+ <span style={{ color: 'var(--legacy-blue)' }}>{label}</span>
3
+ )
@@ -0,0 +1,3 @@
1
+ export const PriceTag = ({ amount }: { amount: string }) => (
2
+ <span style={{ backgroundColor: '#ffe849', color: 'rebeccapurple' }}>{amount}</span>
3
+ )
@@ -0,0 +1,5 @@
1
+ export const Callout = ({ text }: { text: string }) => (
2
+ <aside style={{ border: '1px solid #d8dadb', boxShadow: '0 1px 5px rgba(0, 0, 0, 0.12)' }}>
3
+ {text}
4
+ </aside>
5
+ )
@@ -0,0 +1,3 @@
1
+ export const Grid = ({ children }: { children: React.ReactNode }) => (
2
+ <div className="grid grid-cols-[1fr_auto] w-[32px] top-[-1px]">{children}</div>
3
+ )
@@ -0,0 +1,5 @@
1
+ export const Heading = ({ text }: { text: string }) => (
2
+ <h2 className="font-display font-bold text-2xl" style={{ fontFamily: 'var(--font-display)' }}>
3
+ {text}
4
+ </h2>
5
+ )
@@ -0,0 +1,11 @@
1
+ import type { CSSProperties } from 'react'
2
+
3
+ export const CollapsedCta = ({ href, textColor }: { href: string; textColor: string }) => (
4
+ <a
5
+ className="text-[var(--pb-collapsed-text)] font-[500] underline"
6
+ href={href}
7
+ style={{ '--pb-collapsed-text': textColor } as CSSProperties}
8
+ >
9
+ more
10
+ </a>
11
+ )