@decocms/blocks 7.3.1 → 7.5.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/blocks",
3
- "version": "7.3.1",
3
+ "version": "7.5.0",
4
4
  "type": "module",
5
5
  "description": "Deco framework-agnostic core: CMS block resolution, section registry, matchers, portable SDK utilities",
6
6
  "repository": {
@@ -1,3 +1,15 @@
1
+ "use client";
2
+
3
+ // `"use client"` added by @decocms/nextjs's next-smoke fixture build
4
+ // (Picture is reachable from `DecoRootLayout`/`SectionRenderer` via the
5
+ // `hooks/index.ts` barrel, so it is part of the react-server module graph
6
+ // on any Next.js Server Component page even when a given page never
7
+ // renders it): `createContext`/`useContext` are unavailable under React's
8
+ // react-server condition, and Next statically flags any reachable module
9
+ // that imports them without this directive ("You're importing a component
10
+ // that needs createContext...") — same class of fix, same precedent, as
11
+ // `SectionErrorFallback.tsx`'s `"use client"` (class component /
12
+ // componentDidCatch, also client-only).
1
13
  import {
2
14
  type ComponentPropsWithoutRef,
3
15
  type Context,
@@ -14,15 +26,10 @@ import { type FitOptions, getOptimizedMediaUrl, getSrcSet } from "./Image";
14
26
  // so each source can inject its own <link rel="preload"> with the correct
15
27
  // media query for responsive art direction.
16
28
  //
17
- // Created LAZILY (first render), not at module scope: this file has no
18
- // "use client" directive, so in a react-server graph (a Server Component
19
- // page, or ANY Next.js route handler which ignores "use client"
20
- // entirely) the module evaluates against React's react-server build, where
21
- // `createContext` does not exist. A module-scope call crashes the whole
22
- // graph at import time ("createContext is not a function") even if
23
- // Picture/Source never render. Deferring to render time is safe: renders
24
- // only ever happen under a full React build (client or SSR), and both
25
- // components resolve the same memoized context object.
29
+ // Still created LAZILY (first render, not module scope) even under
30
+ // `"use client"`: this keeps a single memoized context object regardless of
31
+ // how many client bundle chunks end up importing this module, rather than
32
+ // relying on module-instance identity across chunks.
26
33
  // -------------------------------------------------------------------------
27
34
 
28
35
  interface PreloadContextValue {
@@ -0,0 +1,33 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+
3
+ // isDevMode() memoises its result in module-level state after the first
4
+ // call, so each case below resets modules and re-imports fresh to get an
5
+ // unmemoised read for the NODE_ENV value it's stubbing.
6
+ describe("isDevMode", () => {
7
+ afterEach(() => {
8
+ vi.unstubAllEnvs();
9
+ });
10
+
11
+ it("is false when NODE_ENV is production", async () => {
12
+ vi.stubEnv("NODE_ENV", "production");
13
+ vi.stubEnv("DECO_PREVIEW", "");
14
+ vi.resetModules();
15
+ const { isDevMode } = await import("./env");
16
+ expect(isDevMode()).toBe(false);
17
+ });
18
+
19
+ it("is true when NODE_ENV is development", async () => {
20
+ vi.stubEnv("NODE_ENV", "development");
21
+ vi.resetModules();
22
+ const { isDevMode } = await import("./env");
23
+ expect(isDevMode()).toBe(true);
24
+ });
25
+
26
+ it("is true when DECO_PREVIEW=true even if NODE_ENV is production", async () => {
27
+ vi.stubEnv("NODE_ENV", "production");
28
+ vi.stubEnv("DECO_PREVIEW", "true");
29
+ vi.resetModules();
30
+ const { isDevMode } = await import("./env");
31
+ expect(isDevMode()).toBe(true);
32
+ });
33
+ });
package/src/sdk/env.ts CHANGED
@@ -7,12 +7,37 @@
7
7
 
8
8
  let _isDev: boolean | null = null;
9
9
 
10
+ /**
11
+ * Reads `process.env.NODE_ENV` defensively.
12
+ *
13
+ * Wrapped in try/catch so the bare `process` reference can't throw in runtimes
14
+ * without a `process` global (workerd without `nodejs_compat`). Bundlers that
15
+ * statically define `process.env.NODE_ENV` (Vite/esbuild in Workers builds —
16
+ * the same role the old `import.meta.env.DEV` signal served) replace this
17
+ * expression with a string constant at build time, so no runtime `process`
18
+ * global is needed in that path at all.
19
+ */
20
+ function readNodeEnv(): string | undefined {
21
+ try {
22
+ return process.env.NODE_ENV;
23
+ } catch {
24
+ return undefined;
25
+ }
26
+ }
27
+
10
28
  /**
11
29
  * Returns `true` when running in a development environment.
12
30
  *
13
31
  * Detection order:
14
- * 1. `import.meta.env.DEV` Vite build-time constant (reliable in Workers/Miniflare)
15
- * 2. `NODE_ENV=development` standard Node/Vite convention
32
+ * 1. `readNodeEnv() === "development"` bundler-define-friendly read of
33
+ * `process.env.NODE_ENV` (see `readNodeEnv` above). This replaces the
34
+ * previous `import.meta.env.DEV` signal: `import.meta` is ESM-only syntax
35
+ * and is a hard syntax error when CJS consumers (ts-jest) compile this
36
+ * raw-TS package, and `env.ts` is reachable via the `@decocms/blocks/sdk`
37
+ * barrel, so any such consumer importing the barrel would fail to compile.
38
+ * 2. `NODE_ENV=development` read off `globalThis.process.env` — standard
39
+ * Node/Vite convention, for runtimes where `process` is a real global.
40
+ * 3. `DECO_PREVIEW=true` — explicit preview-mode override.
16
41
  *
17
42
  * The result is memoised after the first evaluation.
18
43
  */
@@ -21,11 +46,9 @@ export function isDevMode(): boolean {
21
46
 
22
47
  const env = typeof globalThis.process !== "undefined" ? globalThis.process.env : undefined;
23
48
 
24
- // Vite statically replaces import.meta.env.DEV at build time (true in dev, false in prod).
25
- // In Miniflare/Workers, process.env is unavailable, so this is the reliable signal.
26
- const vitaDev = !!(import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV;
49
+ const nodeEnvDev = readNodeEnv() === "development";
27
50
 
28
- _isDev = vitaDev || env?.NODE_ENV === "development" || env?.DECO_PREVIEW === "true";
51
+ _isDev = nodeEnvDev || env?.NODE_ENV === "development" || env?.DECO_PREVIEW === "true";
29
52
 
30
53
  return _isDev;
31
54
  }
package/src/setup.ts CHANGED
@@ -35,7 +35,8 @@ export interface SiteSetupOptions {
35
35
 
36
36
  /**
37
37
  * Generated blocks object — import and pass directly:
38
- * `import { blocks } from "./server/cms/blocks.gen";`
38
+ * `import { blocks } from "../.deco/blocks.gen";` (`.deco/blocks.gen.ts`
39
+ * is `generate-blocks.ts`'s default output location).
39
40
  */
40
41
  blocks: Record<string, unknown>;
41
42