@decocms/apps-commerce 7.31.6 → 7.32.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/apps-commerce",
3
- "version": "7.31.6",
3
+ "version": "7.32.0",
4
4
  "type": "module",
5
5
  "description": "Deco commerce apps: shared types, app-registry, and portable commerce utilities",
6
6
  "repository": {
@@ -26,7 +26,7 @@
26
26
  "lint:unused": "knip"
27
27
  },
28
28
  "dependencies": {
29
- "@decocms/blocks": "7.31.6"
29
+ "@decocms/blocks": "7.32.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "^19.0.0",
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Cross-app guardrail: every commerce provider that makes upstream API calls
3
+ * MUST ship an instrumented fetch that routes egress through the framework's
4
+ * `createInstrumentedFetch` and emits the canonical
5
+ * `http.client.request.duration` histogram via `recordCommerceMetric`.
6
+ *
7
+ * Scope, stated honestly: this asserts the *factory exists* in the package
8
+ * (it greps `src/utils/instrumentedFetch.ts` for the two required symbols). It
9
+ * does NOT prove the fetch is actually reached at runtime — for VTEX/Shopify/
10
+ * Magento that still depends on the *site* calling `setXFetch(createXFetch())`
11
+ * at boot (they fall back to an uninstrumented `globalThis.fetch` otherwise).
12
+ * Only Salesforce is auto-wired via `createHttpClient`'s default fetcher. So
13
+ * this catches "a provider shipped with no instrumented fetch at all"; it does
14
+ * not catch "a site forgot to wire it".
15
+ *
16
+ * This test reads sibling package source from disk (it does NOT import app
17
+ * modules) so it stays within the one-way dependency graph. If you add a new
18
+ * commerce provider, add it to REQUIRED below and give it a
19
+ * `src/utils/instrumentedFetch.ts` that wires the two symbols.
20
+ *
21
+ * Known exception: `apps-algolia` uses the `algoliasearch` SDK, which owns its
22
+ * own transport + cache, so it has no framework-instrumented fetch and is not
23
+ * listed here.
24
+ */
25
+ import { existsSync, readFileSync } from "node:fs";
26
+ import { dirname, join } from "node:path";
27
+ import { describe, expect, it } from "vitest";
28
+
29
+ // Repo root = nearest ancestor of cwd that contains `packages/apps-commerce`.
30
+ // Robust whether the runner's cwd is the repo root (vitest --root .) or the
31
+ // package dir (`bun run --filter ... test`).
32
+ function findRepoRoot(): string {
33
+ let dir = process.cwd();
34
+ for (let i = 0; i < 8; i++) {
35
+ if (existsSync(join(dir, "packages", "apps-commerce"))) return dir;
36
+ const parent = dirname(dir);
37
+ if (parent === dir) break;
38
+ dir = parent;
39
+ }
40
+ throw new Error("could not locate repo root (packages/apps-commerce not found above cwd)");
41
+ }
42
+ const repoRoot = findRepoRoot();
43
+
44
+ /** Commerce apps whose upstream egress must be instrumented. */
45
+ const REQUIRED = ["apps-vtex", "apps-shopify", "apps-magento", "apps-salesforce"] as const;
46
+
47
+ describe("commerce apps instrumentation guardrail", () => {
48
+ for (const app of REQUIRED) {
49
+ it(`${app} wires createInstrumentedFetch + recordCommerceMetric`, () => {
50
+ const file = join(repoRoot, "packages", app, "src", "utils", "instrumentedFetch.ts");
51
+ let src: string;
52
+ try {
53
+ src = readFileSync(file, "utf8");
54
+ } catch {
55
+ throw new Error(
56
+ `${app} is missing src/utils/instrumentedFetch.ts — every commerce app must ` +
57
+ `route egress through @decocms/blocks/sdk/instrumentedFetch. See apps-vtex for the pattern.`,
58
+ );
59
+ }
60
+ expect(src, `${app} must call createInstrumentedFetch`).toContain("createInstrumentedFetch");
61
+ expect(src, `${app} must record the commerce histogram`).toContain("recordCommerceMetric");
62
+ });
63
+ }
64
+ });