@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 +1 -1
- package/src/hooks/Picture.tsx +16 -9
- package/src/sdk/env.test.ts +33 -0
- package/src/sdk/env.ts +29 -6
- package/src/setup.ts +2 -1
package/package.json
CHANGED
package/src/hooks/Picture.tsx
CHANGED
|
@@ -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
|
-
//
|
|
18
|
-
// "use client"
|
|
19
|
-
//
|
|
20
|
-
//
|
|
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. `
|
|
15
|
-
*
|
|
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
|
-
|
|
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 =
|
|
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 "
|
|
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
|
|