@salesforce/storefront-next-runtime 0.4.2 → 1.0.0-alpha.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.
Files changed (87) hide show
  1. package/README.md +9 -3
  2. package/dist/ComponentContext.js +199 -4
  3. package/dist/ComponentContext.js.map +1 -1
  4. package/dist/DesignComponent.js +2 -2
  5. package/dist/DesignRegion.js +2 -2
  6. package/dist/RegionContext.js +9 -0
  7. package/dist/RegionContext.js.map +1 -0
  8. package/dist/component.types.d.ts +1 -1
  9. package/dist/config.d.ts +34 -221
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +35 -116
  12. package/dist/config.js.map +1 -1
  13. package/dist/data-store.d.ts +185 -15
  14. package/dist/data-store.d.ts.map +1 -1
  15. package/dist/data-store.js +412 -10
  16. package/dist/data-store.js.map +1 -1
  17. package/dist/defaults.d.ts +106 -0
  18. package/dist/defaults.d.ts.map +1 -0
  19. package/dist/defaults.js +67 -0
  20. package/dist/defaults.js.map +1 -0
  21. package/dist/design-data.d.ts +238 -356
  22. package/dist/design-data.d.ts.map +1 -1
  23. package/dist/design-data.js +459 -30
  24. package/dist/design-data.js.map +1 -1
  25. package/dist/design-mode.d.ts +3 -2
  26. package/dist/design-mode.d.ts.map +1 -1
  27. package/dist/design-react-core.d.ts +5 -15
  28. package/dist/design-react-core.d.ts.map +1 -1
  29. package/dist/design-react-core.js +2 -2
  30. package/dist/design-react.d.ts +2 -2
  31. package/dist/design.d.ts +2 -2
  32. package/dist/events.d.ts +32 -6
  33. package/dist/events.d.ts.map +1 -1
  34. package/dist/i18n-client.d.ts.map +1 -1
  35. package/dist/i18n-client.js.map +1 -1
  36. package/dist/i18n.d.ts +1 -2
  37. package/dist/i18n.d.ts.map +1 -1
  38. package/dist/modeDetection.js +0 -18
  39. package/dist/modeDetection.js.map +1 -1
  40. package/dist/scapi.d.ts +2185 -466
  41. package/dist/scapi.d.ts.map +1 -1
  42. package/dist/scapi.js +1 -1
  43. package/dist/scapi.js.map +1 -1
  44. package/dist/schema.d.ts +17 -15
  45. package/dist/schema.d.ts.map +1 -1
  46. package/dist/security-react.d.ts +34 -0
  47. package/dist/security-react.d.ts.map +1 -0
  48. package/dist/security-react.js +21 -0
  49. package/dist/security-react.js.map +1 -0
  50. package/dist/security.d.ts +61 -0
  51. package/dist/security.d.ts.map +1 -0
  52. package/dist/security.js +304 -0
  53. package/dist/security.js.map +1 -0
  54. package/dist/site-context.d.ts +43 -27
  55. package/dist/site-context.d.ts.map +1 -1
  56. package/dist/site-context.js +2 -2
  57. package/dist/site-context2.js +41 -31
  58. package/dist/site-context2.js.map +1 -1
  59. package/dist/types.d.ts +19 -3
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/types2.d.ts +89 -63
  62. package/dist/types2.d.ts.map +1 -1
  63. package/dist/types3.d.ts +1 -35
  64. package/dist/types3.d.ts.map +1 -1
  65. package/package.json +15 -20
  66. package/dist/DesignFrame.js +0 -204
  67. package/dist/DesignFrame.js.map +0 -1
  68. package/dist/custom-global-preferences.d.ts +0 -20
  69. package/dist/custom-global-preferences.d.ts.map +0 -1
  70. package/dist/custom-global-preferences.js +0 -31
  71. package/dist/custom-global-preferences.js.map +0 -1
  72. package/dist/custom-site-preferences.d.ts +0 -20
  73. package/dist/custom-site-preferences.d.ts.map +0 -1
  74. package/dist/custom-site-preferences.js +0 -31
  75. package/dist/custom-site-preferences.js.map +0 -1
  76. package/dist/data-store-custom-global-preferences.d.ts +0 -2
  77. package/dist/data-store-custom-global-preferences.js +0 -6
  78. package/dist/data-store-custom-site-preferences.d.ts +0 -2
  79. package/dist/data-store-custom-site-preferences.js +0 -6
  80. package/dist/data-store-gcp-preferences.d.ts +0 -2
  81. package/dist/data-store-gcp-preferences.js +0 -6
  82. package/dist/gcp-preferences.d.ts +0 -52
  83. package/dist/gcp-preferences.d.ts.map +0 -1
  84. package/dist/gcp-preferences.js +0 -64
  85. package/dist/gcp-preferences.js.map +0 -1
  86. package/dist/utils.js +0 -90
  87. package/dist/utils.js.map +0 -1
package/README.md CHANGED
@@ -55,9 +55,15 @@ Utilities and middleware for reading scoped entries from the MRT data access lay
55
55
  - `AWS_REGION` (required): AWS region for the data store table (e.g., `us-east-1`)
56
56
  - `MOBIFY_PROPERTY_ID` (required): MRT property identifier (e.g., `abcd1234`)
57
57
  - `DEPLOY_TARGET` (required): MRT deploy target (e.g., `production`)
58
- - `SFNEXT_DATA_STORE_UNAVAILABLE_MODE` (optional): controls middleware behavior when MRT data store is unavailable
59
- - `throw` (default): fail fast by throwing
60
- - `fallback`: use middleware-defined safe fallback values and continue request execution
58
+ - `SFNEXT_DATA_STORE_UNAVAILABLE_MODE` (optional): controls built-in middleware behavior when the
59
+ MRT data store is unavailable or returns a service error
60
+ - `fallback` (default): use middleware-defined safe fallback values and continue request execution
61
+ - `throw`: opt back into fail-fast behavior — middleware throws and the request errors out
62
+
63
+ Applies to the four built-in middlewares (`customSitePreferencesMiddleware`,
64
+ `customGlobalPreferencesMiddleware`, `gcpPreferencesMiddleware`, `loginPreferencesMiddleware`).
65
+ Customer-authored middlewares created via `createDataStoreMiddleware` default to `'throw'`; pass
66
+ `onUnavailable: 'fallback'` and a `fallbackValue` to opt into graceful degradation.
61
67
 
62
68
  These are managed by Managed Runtime and are not typically set by SDK consumers directly.
63
69
 
@@ -1,8 +1,203 @@
1
+ import { a as useDesignState, r as useDesignContext } from "./DesignContext.js";
1
2
  import React from "react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
4
 
3
- //#region src/design/react/core/RegionContext.tsx
4
- const RegionContext = React.createContext(null);
5
- const useRegionContext = () => React.useContext(RegionContext);
5
+ //#region src/design/react/hooks/useNodeToTargetStore.ts
6
+ function useNodeToTargetStore({ parentId, componentId, contentLinkUuid, regionId, nodeRef, type, contentLinkUuids, componentTypeInclusions, componentTypeExclusions }) {
7
+ const { nodeToTargetMap } = useDesignState();
8
+ React.useEffect(() => {
9
+ if (nodeRef.current) nodeToTargetMap.set(nodeRef.current, {
10
+ parentId,
11
+ componentId,
12
+ contentLinkUuid,
13
+ regionId,
14
+ type,
15
+ contentLinkUuids,
16
+ componentTypeInclusions,
17
+ componentTypeExclusions
18
+ });
19
+ }, [
20
+ nodeRef,
21
+ parentId,
22
+ componentId,
23
+ contentLinkUuid,
24
+ regionId,
25
+ type,
26
+ contentLinkUuids,
27
+ nodeToTargetMap,
28
+ componentTypeInclusions,
29
+ componentTypeExclusions
30
+ ]);
31
+ }
32
+
33
+ //#endregion
34
+ //#region src/design/react/hooks/useComponentType.ts
35
+ function useComponentType(componentId) {
36
+ const { pageDesignerConfig } = useDesignContext();
37
+ const { type = "" } = pageDesignerConfig?.components[componentId] ?? {};
38
+ return pageDesignerConfig?.componentTypes[type] ?? null;
39
+ }
40
+
41
+ //#endregion
42
+ //#region src/design/react/components/DeleteToolboxButton.tsx
43
+ const DeleteToolboxButton = ({ title, onClick, onMouseDown = () => {} }) => /* @__PURE__ */ jsx("button", {
44
+ className: "pd-design__frame__toolbox-button",
45
+ title,
46
+ type: "button",
47
+ onMouseDown,
48
+ onClick,
49
+ children: /* @__PURE__ */ jsx("svg", {
50
+ className: "pd-design__frame__delete-icon",
51
+ viewBox: "0 0 24 24",
52
+ fill: "none",
53
+ xmlns: "http://www.w3.org/2000/svg",
54
+ children: /* @__PURE__ */ jsx("path", {
55
+ d: "M18 6L6 18M6 6l12 12",
56
+ stroke: "currentColor",
57
+ strokeWidth: "2",
58
+ strokeLinecap: "round",
59
+ strokeLinejoin: "round"
60
+ })
61
+ })
62
+ });
63
+
64
+ //#endregion
65
+ //#region src/design/react/components/MoveToolboxButton.tsx
66
+ const MoveToolboxButton = ({ title }) => /* @__PURE__ */ jsx("button", {
67
+ className: "pd-design__frame__toolbox-button",
68
+ title,
69
+ type: "button",
70
+ children: /* @__PURE__ */ jsx("svg", {
71
+ className: "pd-design__frame__move-icon",
72
+ viewBox: "0 0 24 24",
73
+ xmlns: "http://www.w3.org/2000/svg",
74
+ children: /* @__PURE__ */ jsx("path", {
75
+ d: "M22.9 11.7l-3.8-4.2c-.3-.3-.6 0-.6.4v2.7h-4.7c-.2 0-.4-.2-.4-.4V5.5h2.7c.5 0 .7-.4.4-.6l-4.1-3.8c-.2-.2-.5-.2-.7 0L7.6 4.9c-.3.3-.1.6.4.6h2.6v4.7c0 .2-.2.4-.4.4H5.5V7.9c0-.5-.4-.7-.6-.4l-3.8 4.1c-.2.2-.2.5 0 .7l3.8 4.1c.3.3.6.1.6-.4v-2.6h4.7c.2 0 .4.2.4.4v4.7H7.9c-.5 0-.7.4-.4.6l4.1 3.8c.2.2.5.2.7 0l4.1-3.8c.3-.3.1-.6-.4-.6h-2.6v-4.7c0-.2.2-.4.4-.4h4.7v2.7c0 .5.4.7.6.4l3.8-4.1c.2-.3.2-.5 0-.7z",
76
+ stroke: "currentColor",
77
+ strokeWidth: "2",
78
+ strokeLinecap: "round",
79
+ strokeLinejoin: "round"
80
+ })
81
+ })
82
+ });
83
+
84
+ //#endregion
85
+ //#region src/design/react/hooks/useLabels.ts
86
+ function useLabels() {
87
+ const { pageDesignerConfig } = useDesignContext();
88
+ return pageDesignerConfig?.labels ?? {};
89
+ }
90
+
91
+ //#endregion
92
+ //#region src/design/react/components/DesignOverlay.tsx
93
+ /**
94
+ * Copyright 2026 Salesforce, Inc.
95
+ *
96
+ * Licensed under the Apache License, Version 2.0 (the "License");
97
+ * you may not use this file except in compliance with the License.
98
+ * You may obtain a copy of the License at
99
+ *
100
+ * http://www.apache.org/licenses/LICENSE-2.0
101
+ *
102
+ * Unless required by applicable law or agreed to in writing, software
103
+ * distributed under the License is distributed on an "AS IS" BASIS,
104
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
105
+ * See the License for the specific language governing permissions and
106
+ * limitations under the License.
107
+ */
108
+ const DesignOverlay = () => {
109
+ return /* @__PURE__ */ jsx("div", {
110
+ className: "pd-design__frame__overlay",
111
+ children: /* @__PURE__ */ jsx("svg", {
112
+ xmlns: "http://www.w3.org/2000/svg",
113
+ x: "0px",
114
+ y: "0px",
115
+ width: "52px",
116
+ height: "52px",
117
+ viewBox: "0 0 52 52",
118
+ enableBackground: "new 0 0 52 52",
119
+ xmlSpace: "preserve",
120
+ children: /* @__PURE__ */ jsx("path", {
121
+ fill: "#FFFFFF",
122
+ d: "M26,2C12.7,2,2,12.7,2,26s10.7,24,24,24s24-10.7,24-24S39.3,2,26,2z M26,7C26,7,26,7,26,7C26,7,26,7,26,7\n C26,7,26,7,26,7z M28,7.1c-0.1,0-0.1,0-0.2,0C27.9,7.1,28,7.1,28,7.1z M26,45C15.5,45,7,36.5,7,26c0-1,0.1-2.1,0.3-3\n c1.3,0.2,2.9,0.7,3.7,1.5c1.7,1.8,3.6,3.9,5.4,4.3c0,0-0.2,0.1-0.4,0.4c-0.2,0.3-0.4,0.9-0.4,1.9c0,4.7,4.4,1.9,4.4,6.6\n c0,4.7,5.3,6.6,5.3,2.8s3.5-5.6,3.5-8.5s-2.7-2.8-4.4-3.8c-1.8-0.9-2.7-2.4-6.1-1.9c-1.8-1.7-2.8-3.1-2-4.7c0.9-1.7,4.6-2,4.6-4.6\n s-2.5-3.1-4.3-3.1c-0.8,0-2.5-0.6-3.9-1.3c1.7-1.7,3.8-3.1,6-4.1c1.6,0.7,4.3,1.8,6.6,1.8c2.7,0,4.1-1.9,3.7-3.1\n c4.5,0.7,8.5,3,11.4,6.2c-1.5,0.9-3.5,1.9-7,1.9c-4.6,0-4.6,4.7-1.9,5.6c2.8,0.9,5.6-1.8,6.5,0c0.9,1.8-6.5,1.8-4.6,6.4\n c1.9,4.6,3.7-0.1,5.6,4.5c1.9,4.6,5.6-0.7,2.8-4.3c-1.2-1.6-0.9-6.5,1.9-6.5h0.9c0.4,1.6,0.7,3.3,0.7,5C45,36.5,36.5,45,26,45z"
123
+ })
124
+ })
125
+ });
126
+ };
127
+
128
+ //#endregion
129
+ //#region src/design/react/components/DesignFrame.tsx
130
+ const DesignFrame = ({ componentId, children, name, parentId, regionId, contentLinkUuid, localized = false, showFrame = false, showToolbox = true, isMoveable = true, className }) => {
131
+ const componentType = useComponentType(componentId ?? "");
132
+ const { deleteComponent } = useDesignState();
133
+ const labels = useLabels();
134
+ const nodeRef = React.useRef(null);
135
+ const handleDelete = React.useCallback((event) => {
136
+ event.stopPropagation();
137
+ if (componentId) deleteComponent({
138
+ componentId,
139
+ contentLinkUuid: contentLinkUuid ?? "",
140
+ sourceComponentId: parentId ?? "",
141
+ sourceRegionId: regionId ?? ""
142
+ });
143
+ }, [
144
+ deleteComponent,
145
+ componentId,
146
+ contentLinkUuid,
147
+ parentId,
148
+ regionId
149
+ ]);
150
+ const stopPropagation = (event) => event.stopPropagation();
151
+ return /* @__PURE__ */ jsxs("div", {
152
+ className: [
153
+ "pd-design__frame",
154
+ showFrame && "pd-design__frame--visible",
155
+ className
156
+ ].filter(Boolean).join(" "),
157
+ ref: nodeRef,
158
+ children: [
159
+ showFrame && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", { className: "pd-design__frame--x" }), /* @__PURE__ */ jsx("div", { className: "pd-design__frame--y" })] }),
160
+ /* @__PURE__ */ jsxs("div", {
161
+ className: "pd-design__frame__label",
162
+ onMouseDown: stopPropagation,
163
+ children: [
164
+ componentType?.image && /* @__PURE__ */ jsx("span", {
165
+ className: "pd-design__icon",
166
+ children: /* @__PURE__ */ jsx("img", {
167
+ src: componentType.image,
168
+ alt: ""
169
+ })
170
+ }),
171
+ /* @__PURE__ */ jsx("span", {
172
+ className: "pd-design__frame__name",
173
+ children: name
174
+ }),
175
+ !localized && /* @__PURE__ */ jsx("span", {
176
+ className: "pd-design__frame__fallback-badge",
177
+ children: labels.fallback ?? "Fallback"
178
+ })
179
+ ]
180
+ }),
181
+ showToolbox && /* @__PURE__ */ jsxs("div", {
182
+ className: "pd-design__frame__toolbox",
183
+ children: [isMoveable && /* @__PURE__ */ jsx(MoveToolboxButton, { title: labels.moveComponent ?? "Move component" }), /* @__PURE__ */ jsx(DeleteToolboxButton, {
184
+ title: labels.deleteComponent ?? "Delete component",
185
+ onMouseDown: stopPropagation,
186
+ onClick: handleDelete
187
+ })]
188
+ }),
189
+ /* @__PURE__ */ jsx(DesignOverlay, {}),
190
+ children
191
+ ]
192
+ });
193
+ };
194
+ DesignFrame.defaultProps = {
195
+ parentId: void 0,
196
+ componentId: void 0,
197
+ showToolbox: true,
198
+ regionId: void 0,
199
+ showFrame: false
200
+ };
6
201
 
7
202
  //#endregion
8
203
  //#region src/design/react/core/ComponentContext.tsx
@@ -10,5 +205,5 @@ const ComponentContext = React.createContext(null);
10
205
  const useComponentContext = () => React.useContext(ComponentContext);
11
206
 
12
207
  //#endregion
13
- export { useRegionContext as i, useComponentContext as n, RegionContext as r, ComponentContext as t };
208
+ export { useComponentType as a, useLabels as i, useComponentContext as n, useNodeToTargetStore as o, DesignFrame as r, ComponentContext as t };
14
209
  //# sourceMappingURL=ComponentContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentContext.js","names":[],"sources":["../src/design/react/core/RegionContext.tsx","../src/design/react/core/ComponentContext.tsx"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport interface RegionContextType {\n regionId: string;\n contentLinkUuids: string[];\n}\n\nexport const RegionContext = React.createContext<RegionContextType | null>(null);\n\nexport const useRegionContext = (): RegionContextType | null => React.useContext(RegionContext);\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport interface ComponentContextType {\n componentId: string;\n name?: string;\n contentLinkUuid?: string;\n}\n\nexport const ComponentContext = React.createContext<ComponentContextType | null>(null);\n\nexport const useComponentContext = (): ComponentContextType | null => React.useContext(ComponentContext);\n"],"mappings":";;;AAsBA,MAAa,gBAAgB,MAAM,cAAwC,KAAK;AAEhF,MAAa,yBAAmD,MAAM,WAAW,cAAc;;;;ACD/F,MAAa,mBAAmB,MAAM,cAA2C,KAAK;AAEtF,MAAa,4BAAyD,MAAM,WAAW,iBAAiB"}
1
+ {"version":3,"file":"ComponentContext.js","names":[],"sources":["../src/design/react/hooks/useNodeToTargetStore.ts","../src/design/react/hooks/useComponentType.ts","../src/design/react/components/DeleteToolboxButton.tsx","../src/design/react/components/MoveToolboxButton.tsx","../src/design/react/hooks/useLabels.ts","../src/design/react/components/DesignOverlay.tsx","../src/design/react/components/DesignFrame.tsx","../src/design/react/core/ComponentContext.tsx"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport { useDesignState } from './useDesignState';\nimport type { NodeToTargetMapEntry } from '../context/DesignStateContext';\n\nexport function useNodeToTargetStore({\n parentId,\n componentId,\n contentLinkUuid,\n regionId,\n nodeRef,\n type,\n contentLinkUuids,\n componentTypeInclusions,\n componentTypeExclusions,\n}: Partial<NodeToTargetMapEntry> & {\n nodeRef: React.RefObject<Element | null>;\n}): void {\n const { nodeToTargetMap } = useDesignState();\n\n React.useEffect(() => {\n if (nodeRef.current) {\n nodeToTargetMap.set(nodeRef.current, {\n parentId,\n componentId,\n contentLinkUuid,\n regionId,\n type,\n contentLinkUuids,\n componentTypeInclusions,\n componentTypeExclusions,\n } as NodeToTargetMapEntry);\n }\n }, [\n nodeRef,\n parentId,\n componentId,\n contentLinkUuid,\n regionId,\n type,\n contentLinkUuids,\n nodeToTargetMap,\n componentTypeInclusions,\n componentTypeExclusions,\n ]);\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useDesignContext } from '../context/DesignContext';\nimport type { ComponentType } from '../../messaging-api/domain-types';\n\nexport function useComponentType(componentId: string): ComponentType | null {\n const { pageDesignerConfig } = useDesignContext();\n const { type = '' } = pageDesignerConfig?.components[componentId] ?? {};\n\n return pageDesignerConfig?.componentTypes[type] ?? null;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type React from 'react';\n\nexport const DeleteToolboxButton = ({\n title,\n onClick,\n onMouseDown = () => {\n /* noop */\n },\n}: {\n title: string;\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;\n onMouseDown?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n}): React.JSX.Element => (\n <button\n className=\"pd-design__frame__toolbox-button\"\n title={title}\n type=\"button\"\n onMouseDown={onMouseDown}\n onClick={onClick}>\n <svg\n className=\"pd-design__frame__delete-icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M18 6L6 18M6 6l12 12\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n);\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type React from 'react';\n\nexport const MoveToolboxButton = ({ title }: { title: string }): React.JSX.Element => (\n <button className=\"pd-design__frame__toolbox-button\" title={title} type=\"button\">\n <svg className=\"pd-design__frame__move-icon\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M22.9 11.7l-3.8-4.2c-.3-.3-.6 0-.6.4v2.7h-4.7c-.2 0-.4-.2-.4-.4V5.5h2.7c.5 0 .7-.4.4-.6l-4.1-3.8c-.2-.2-.5-.2-.7 0L7.6 4.9c-.3.3-.1.6.4.6h2.6v4.7c0 .2-.2.4-.4.4H5.5V7.9c0-.5-.4-.7-.6-.4l-3.8 4.1c-.2.2-.2.5 0 .7l3.8 4.1c.3.3.6.1.6-.4v-2.6h4.7c.2 0 .4.2.4.4v4.7H7.9c-.5 0-.7.4-.4.6l4.1 3.8c.2.2.5.2.7 0l4.1-3.8c.3-.3.1-.6-.4-.6h-2.6v-4.7c0-.2.2-.4.4-.4h4.7v2.7c0 .5.4.7.6.4l3.8-4.1c.2-.3.2-.5 0-.7z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n);\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useDesignContext } from '../context/DesignContext';\n\nexport function useLabels(): Record<string, string> {\n const { pageDesignerConfig } = useDesignContext();\n\n return pageDesignerConfig?.labels ?? {};\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const DesignOverlay = () => {\n return (\n <div className=\"pd-design__frame__overlay\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n x=\"0px\"\n y=\"0px\"\n width=\"52px\"\n height=\"52px\"\n viewBox=\"0 0 52 52\"\n enableBackground=\"new 0 0 52 52\"\n xmlSpace=\"preserve\">\n <path\n fill=\"#FFFFFF\"\n d=\"M26,2C12.7,2,2,12.7,2,26s10.7,24,24,24s24-10.7,24-24S39.3,2,26,2z M26,7C26,7,26,7,26,7C26,7,26,7,26,7\n\tC26,7,26,7,26,7z M28,7.1c-0.1,0-0.1,0-0.2,0C27.9,7.1,28,7.1,28,7.1z M26,45C15.5,45,7,36.5,7,26c0-1,0.1-2.1,0.3-3\n\tc1.3,0.2,2.9,0.7,3.7,1.5c1.7,1.8,3.6,3.9,5.4,4.3c0,0-0.2,0.1-0.4,0.4c-0.2,0.3-0.4,0.9-0.4,1.9c0,4.7,4.4,1.9,4.4,6.6\n\tc0,4.7,5.3,6.6,5.3,2.8s3.5-5.6,3.5-8.5s-2.7-2.8-4.4-3.8c-1.8-0.9-2.7-2.4-6.1-1.9c-1.8-1.7-2.8-3.1-2-4.7c0.9-1.7,4.6-2,4.6-4.6\n\ts-2.5-3.1-4.3-3.1c-0.8,0-2.5-0.6-3.9-1.3c1.7-1.7,3.8-3.1,6-4.1c1.6,0.7,4.3,1.8,6.6,1.8c2.7,0,4.1-1.9,3.7-3.1\n\tc4.5,0.7,8.5,3,11.4,6.2c-1.5,0.9-3.5,1.9-7,1.9c-4.6,0-4.6,4.7-1.9,5.6c2.8,0.9,5.6-1.8,6.5,0c0.9,1.8-6.5,1.8-4.6,6.4\n\tc1.9,4.6,3.7-0.1,5.6,4.5c1.9,4.6,5.6-0.7,2.8-4.3c-1.2-1.6-0.9-6.5,1.9-6.5h0.9c0.4,1.6,0.7,3.3,0.7,5C45,36.5,36.5,45,26,45z\"\n />\n </svg>\n </div>\n );\n};\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport { useComponentType } from '../hooks/useComponentType';\nimport { DeleteToolboxButton } from './DeleteToolboxButton';\nimport { MoveToolboxButton } from './MoveToolboxButton';\nimport { useDesignState } from '../hooks/useDesignState';\nimport { useLabels } from '../hooks/useLabels';\nimport { DesignOverlay } from './DesignOverlay';\n\nexport const DesignFrame = ({\n componentId,\n children,\n name,\n parentId,\n regionId,\n contentLinkUuid,\n localized = false,\n showFrame = false,\n showToolbox = true,\n isMoveable = true,\n className,\n}: React.PropsWithChildren<{\n componentId?: string;\n name: string;\n localized?: boolean;\n parentId?: string;\n regionId?: string;\n contentLinkUuid?: string;\n showToolbox?: boolean;\n showFrame?: boolean;\n isMoveable?: boolean;\n className?: string;\n}>): React.JSX.Element => {\n const componentType = useComponentType(componentId ?? '');\n const { deleteComponent } = useDesignState();\n const labels = useLabels();\n const nodeRef = React.useRef<HTMLDivElement>(null);\n\n const handleDelete = React.useCallback(\n (event: React.MouseEvent) => {\n // Stop propagation so we don't select the component as well when\n // this bubbles up.\n event.stopPropagation();\n\n if (componentId) {\n deleteComponent({\n componentId,\n contentLinkUuid: contentLinkUuid ?? '',\n sourceComponentId: parentId ?? '',\n sourceRegionId: regionId ?? '',\n });\n }\n },\n [deleteComponent, componentId, contentLinkUuid, parentId, regionId]\n );\n\n const stopPropagation = (event: React.MouseEvent) => event.stopPropagation();\n\n const classes = ['pd-design__frame', showFrame && 'pd-design__frame--visible', className].filter(Boolean).join(' ');\n\n // TODO: For the frame label, when there is not enough space above the component to display it, we\n // need to display it inside the container instead.\n return (\n <div className={classes} ref={nodeRef}>\n {showFrame && (\n <>\n <div className=\"pd-design__frame--x\" />\n <div className=\"pd-design__frame--y\" />\n </>\n )}\n <div className=\"pd-design__frame__label\" onMouseDown={stopPropagation}>\n {componentType?.image && (\n <span className=\"pd-design__icon\">\n <img src={componentType.image} alt=\"\" />\n </span>\n )}\n <span className=\"pd-design__frame__name\">{name}</span>\n {!localized && (\n <span className=\"pd-design__frame__fallback-badge\">{labels.fallback ?? 'Fallback'}</span>\n )}\n </div>\n {showToolbox && (\n <div className=\"pd-design__frame__toolbox\">\n {isMoveable && <MoveToolboxButton title={labels.moveComponent ?? 'Move component'} />}\n <DeleteToolboxButton\n title={labels.deleteComponent ?? 'Delete component'}\n onMouseDown={stopPropagation}\n onClick={handleDelete}\n />\n </div>\n )}\n <DesignOverlay />\n {children}\n </div>\n );\n};\n\nDesignFrame.defaultProps = {\n parentId: undefined,\n componentId: undefined,\n showToolbox: true,\n regionId: undefined,\n showFrame: false,\n};\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport interface ComponentContextType {\n componentId: string;\n name?: string;\n contentLinkUuid?: string;\n}\n\nexport const ComponentContext = React.createContext<ComponentContextType | null>(null);\n\nexport const useComponentContext = (): ComponentContextType | null => React.useContext(ComponentContext);\n"],"mappings":"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"}
@@ -2,8 +2,8 @@ import "./messaging-api.js";
2
2
  import { a as useDesignState, i as useThrottledCallback, r as useDesignContext, s as useComponentDiscovery } from "./DesignContext.js";
3
3
  import "./modeDetection.js";
4
4
  import "./PageDesignerProvider.js";
5
- import { i as useRegionContext, n as useComponentContext, t as ComponentContext } from "./ComponentContext.js";
6
- import { i as useNodeToTargetStore, r as useComponentType, t as DesignFrame } from "./DesignFrame.js";
5
+ import { n as useRegionContext } from "./RegionContext.js";
6
+ import { a as useComponentType, n as useComponentContext, o as useNodeToTargetStore, r as DesignFrame, t as ComponentContext } from "./ComponentContext.js";
7
7
  import React, { useCallback, useRef } from "react";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
 
@@ -2,8 +2,8 @@ import "./messaging-api.js";
2
2
  import { a as useDesignState, o as isComponentTypeAllowedInRegion } from "./DesignContext.js";
3
3
  import "./modeDetection.js";
4
4
  import "./PageDesignerProvider.js";
5
- import { n as useComponentContext, r as RegionContext } from "./ComponentContext.js";
6
- import { i as useNodeToTargetStore, n as useLabels, t as DesignFrame } from "./DesignFrame.js";
5
+ import { t as RegionContext } from "./RegionContext.js";
6
+ import { i as useLabels, n as useComponentContext, o as useNodeToTargetStore, r as DesignFrame } from "./ComponentContext.js";
7
7
  import React, { useCallback, useMemo } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
9
9
 
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+
3
+ //#region src/design/react/core/RegionContext.tsx
4
+ const RegionContext = React.createContext(null);
5
+ const useRegionContext = () => React.useContext(RegionContext);
6
+
7
+ //#endregion
8
+ export { useRegionContext as n, RegionContext as t };
9
+ //# sourceMappingURL=RegionContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegionContext.js","names":[],"sources":["../src/design/react/core/RegionContext.tsx"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport interface RegionContextType {\n regionId: string;\n contentLinkUuids: string[];\n}\n\nexport const RegionContext = React.createContext<RegionContextType | null>(null);\n\nexport const useRegionContext = (): RegionContextType | null => React.useContext(RegionContext);\n"],"mappings":";;;AAsBA,MAAa,gBAAgB,MAAM,cAAwC,KAAK;AAEhF,MAAa,yBAAmD,MAAM,WAAW,cAAc"}
@@ -89,5 +89,5 @@ type RegionDecoratorProps<TProps> = React.PropsWithChildren<{
89
89
  className?: string;
90
90
  } & TProps>;
91
91
  //#endregion
92
- export { RegionDesignMetadata as a, RegionDecoratorProps as i, ComponentDesignMetadata as n, DefaultComponentConstructor as r, ComponentDecoratorProps as t };
92
+ export { RegionDesignMetadata as i, ComponentDesignMetadata as n, RegionDecoratorProps as r, ComponentDecoratorProps as t };
93
93
  //# sourceMappingURL=component.types.d.ts.map
package/dist/config.d.ts CHANGED
@@ -1,61 +1,31 @@
1
1
  import { n as Site, r as Url, t as Locale } from "./types.js";
2
2
  import { n as DefineConfigOptions, r as defineConfig, t as BaseConfig } from "./schema.js";
3
- import * as react0 from "react";
3
+ import { n as defaultSecurityHeaders } from "./defaults.js";
4
4
  import { ReactNode } from "react";
5
- import * as react_jsx_runtime2 from "react/jsx-runtime";
6
- import * as react_router11 from "react-router";
7
- import { MiddlewareFunction, RouterContextProvider } from "react-router";
5
+ import * as react_jsx_runtime1 from "react/jsx-runtime";
6
+ import * as react_router14 from "react-router";
7
+ import { RouterContextProvider } from "react-router";
8
8
 
9
- //#region src/config/get-config.d.ts
10
-
11
- declare global {
12
- interface Window {
13
- __APP_CONFIG__?: Record<string, unknown>;
14
- }
15
- }
16
- /**
17
- * Get configuration in loaders, actions, and utilities.
18
- *
19
- * Pass context parameter in server loaders/actions.
20
- * Omit context parameter in client loaders (uses window.__APP_CONFIG__).
21
- *
22
- * @param context - Router context for server loaders/actions
23
- * @returns App configuration
24
- */
25
- declare function getConfig<T extends Record<string, unknown> = Record<string, unknown>>(context?: Readonly<RouterContextProvider>): T;
26
- /**
27
- * Get configuration in React components.
28
- *
29
- * Must use this hook (not getConfig) because React Context requires useContext().
30
- *
31
- * @returns App configuration
32
- */
33
- declare function useConfig<T extends Record<string, unknown> = Record<string, unknown>>(): T;
34
- //#endregion
35
9
  //#region src/config/context.d.ts
10
+
36
11
  /**
37
- * Router context for application configuration.
38
- *
39
- * Populated by `createAppConfigMiddleware` with the `app` section of config.
40
- * Accessible in loaders, actions, and middleware via `context.get(appConfigContext)`.
41
- */
42
- declare const appConfigContext: react_router11.RouterContext<Record<string, unknown>>;
43
- /**
44
- * React context for application configuration.
45
- *
46
- * Used by the `useConfig()` hook in React components.
47
- * Populated by `ConfigProvider` in the component tree.
12
+ * Augmentation hook for typing `getConfig()` / `useConfig()` /
13
+ * `appConfigContext`. Templates augment once via `declare module` so call
14
+ * sites don't need a per-call generic. Without augmentation, property
15
+ * accesses type to `unknown`. See README-CONFIG.md for the augmentation
16
+ * snippet and the multi-template caveat.
48
17
  */
49
- declare const ConfigContext: react0.Context<Record<string, unknown> | null>;
18
+ interface AppConfigShape {
19
+ [key: string]: unknown;
20
+ }
50
21
  /**
51
- * Extract the `app` section from a full config object.
52
- *
53
- * @param staticConfig - The full config object (output of `defineConfig()`)
54
- * @returns The `app` section of the config
22
+ * Router context for application configuration. Populated by the template's
23
+ * app-config middleware; read via `context.get(appConfigContext)` in loaders,
24
+ * actions, and other middleware. Returns the augmented `AppConfigShape`.
55
25
  */
56
- declare function createAppConfig<T extends BaseConfig>(staticConfig: T): T['app'];
26
+ declare const appConfigContext: react_router14.RouterContext<AppConfigShape>;
57
27
  interface ConfigProviderProps {
58
- config: Record<string, unknown>;
28
+ config: AppConfigShape;
59
29
  children: ReactNode;
60
30
  }
61
31
  /**
@@ -67,183 +37,26 @@ interface ConfigProviderProps {
67
37
  declare function ConfigProvider({
68
38
  config,
69
39
  children
70
- }: ConfigProviderProps): react_jsx_runtime2.JSX.Element;
71
- //#endregion
72
- //#region src/config/middleware.d.ts
73
- /**
74
- * Create app config middleware for both server and client.
75
- *
76
- * Follows the same factory pattern as `createSiteContextMiddleware`.
77
- *
78
- * The server middleware:
79
- * - Validates required Commerce API fields on first request (one-time)
80
- * - Sets `appConfigContext` in router context with `config.app`
81
- *
82
- * The client middleware:
83
- * - Reads `window.__APP_CONFIG__` (injected during SSR)
84
- * - Sets `appConfigContext` in router context
85
- *
86
- * Environment variables:
87
- * - `SCAPI_PROXY_HOST` (optional): When set, skips `shortCode` validation
88
- * (workspace environments route through a proxy that doesn't require shortCode)
89
- * - `NODE_ENV` (optional): When set to 'test', skips validation entirely
90
- *
91
- * @param config - The full config object (output of `defineConfig()`)
92
- * @returns Object with `server` and `client` middleware functions
93
- *
94
- * @example
95
- * import { createAppConfigMiddleware } from '@salesforce/storefront-next-runtime/config';
96
- * import config from '@/config/server';
97
- *
98
- * const appConfigMiddleware = createAppConfigMiddleware(config);
99
- *
100
- * export const middleware = [appConfigMiddleware.server, ...otherMiddleware];
101
- * export const clientMiddleware = [appConfigMiddleware.client, ...otherClientMiddleware];
102
- */
103
- declare function createAppConfigMiddleware<T extends BaseConfig>(config: T): {
104
- server: MiddlewareFunction<Response>;
105
- client: MiddlewareFunction<Record<string, unknown>>;
106
- };
40
+ }: ConfigProviderProps): react_jsx_runtime1.JSX.Element;
107
41
  //#endregion
108
- //#region src/config/utils.d.ts
109
- /**
110
- * Copyright 2026 Salesforce, Inc.
111
- *
112
- * Licensed under the Apache License, Version 2.0 (the "License");
113
- * you may not use this file except in compliance with the License.
114
- * You may obtain a copy of the License at
115
- *
116
- * http://www.apache.org/licenses/LICENSE-2.0
117
- *
118
- * Unless required by applicable law or agreed to in writing, software
119
- * distributed under the License is distributed on an "AS IS" BASIS,
120
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121
- * See the License for the specific language governing permissions and
122
- * limitations under the License.
123
- */
124
- /**
125
- * Deep merge two objects, with source values overriding target values
126
- * Arrays are replaced, not merged
127
- *
128
- * @param target - The base object
129
- * @param source - The object with values to merge in
130
- * @returns A new merged object
131
- *
132
- * @example
133
- * deepMerge(
134
- * { a: { b: 1, c: 2 } },
135
- * { a: { b: 3, d: 4 } }
136
- * )
137
- * // Returns: { a: { b: 3, c: 2, d: 4 } }
138
- */
139
- declare const deepMerge: <T extends Record<string, unknown>>(target: T, source: Record<string, unknown>) => T;
140
- /**
141
- * Convert a path string with double underscore separators to a nested object
142
- * Normalizes keys to match baseConfig casing (case-insensitive lookup, preserves baseConfig case)
143
- *
144
- * @param path - The path string (e.g., 'app__pages__cart__quantityUpdateDebounce')
145
- * @param value - The value to set at the path
146
- * @param baseConfig - Optional base config for case normalization
147
- * @returns A nested object
148
- *
149
- * @example
150
- * pathToObject('app__pages__cart__maxQuantity', 999)
151
- * // Returns: { app: { pages: { cart: { maxQuantity: 999 } } } }
152
- *
153
- * @example
154
- * // With baseConfig normalization:
155
- * pathToObject('APP__SITE__LOCALE', 'en-GB', { app: { site: { locale: 'en-GB' } } })
156
- * // Returns: { app: { site: { locale: 'en-GB' } } } (normalized to baseConfig casing)
157
- */
158
- declare const pathToObject: (path: string, value: unknown, baseConfig?: Record<string, unknown>) => Record<string, unknown>;
159
- /**
160
- * Parse environment variable value with optimistic JSON parsing
161
- * Tries to parse as JSON first, falls back to string if invalid
162
- * Supports multi-line formatted JSON by normalizing whitespace before parsing
163
- *
164
- * @param varValue - The environment variable value
165
- * @param varName - Optional variable name for better error messages
166
- * @returns The parsed value (JSON type if valid JSON, otherwise string)
167
- *
168
- * @example
169
- * // Primitives
170
- * parseEnvValue('42') // → 42 (number)
171
- * parseEnvValue('true') // → true (boolean)
172
- * parseEnvValue('hello') // → 'hello' (string)
173
- *
174
- * @example
175
- * // Single-line JSON
176
- * parseEnvValue('["Apple","Google"]') // → ['Apple', 'Google'] (array)
177
- * parseEnvValue('{"key":"value"}') // → {key: 'value'} (object)
178
- *
179
- * @example
180
- * // Multi-line formatted JSON (whitespace normalized automatically)
181
- * parseEnvValue('[
182
- * {"id": "en-GB"},
183
- * {"id": "fr-FR"}
184
- * ]') // → [{id: 'en-GB'}, {id: 'fr-FR'}] (array)
185
- */
186
- declare const parseEnvValue: (varValue: string, varName?: string) => unknown;
187
- /**
188
- * Extract all valid paths from a config object (recursively traverses the object structure)
189
- * Returns paths in lowercase with double underscore separators
190
- *
191
- * @param obj - The config object to extract paths from
192
- * @param prefix - Current path prefix (used for recursion)
193
- * @returns Array of valid config paths
194
- *
195
- * @example
196
- * extractValidPaths({ app: { site: { locale: 'en-GB' } } })
197
- * // Returns: ['app__site__locale']
198
- */
199
- declare const extractValidPaths: (obj: unknown, prefix?: string) => string[];
42
+ //#region src/config/get-config.d.ts
43
+ declare global {
44
+ interface Window {
45
+ __APP_CONFIG__?: Record<string, unknown>;
46
+ }
47
+ }
200
48
  /**
201
- * Options for mergeEnvConfig
49
+ * Get configuration in loaders, actions, and utilities. Pass `context` on the
50
+ * server; omit it on the client (reads `window.__APP_CONFIG__`). Returns the
51
+ * augmented `AppConfigShape` — pass an explicit generic only for narrower or
52
+ * unrelated shapes (rare).
202
53
  */
203
- interface MergeEnvConfigOptions {
204
- /**
205
- * Config paths that cannot be overridden by environment variables.
206
- * Paths are matched case-insensitively with double underscore separators.
207
- * Any env var targeting a protected path or a sub-path of it will throw an error.
208
- *
209
- * @example ['app__engagement'] — prevents PUBLIC__app__engagement__* from being set via env
210
- */
211
- protectedPaths?: string[];
212
- }
54
+ declare function getConfig<T extends Record<string, unknown> = AppConfigShape>(context?: Readonly<RouterContextProvider>): T;
213
55
  /**
214
- * Merge environment variables with PUBLIC__ prefix into config.
215
- *
216
- * Uses double underscore (__) to target nested config paths.
217
- * All PUBLIC__ prefixed variables are exposed to the client (bundled into window.__APP_CONFIG__).
218
- *
219
- * Server-only secrets should NEVER use this — read them directly from process.env in server code.
220
- *
221
- * Environment variables:
222
- * - `PUBLIC__<path>` (optional): Override any config path. e.g. `PUBLIC__app__commerce__api__clientId=abc123`
223
- * - `NODE_ENV` (optional): When set to 'development', enables conflict warnings for overlapping paths
224
- *
225
- * @param env - Environment variables object (defaults to process.env)
226
- * @param baseConfig - Optional base config for strict path validation and case normalization
227
- * @param options - Optional configuration including protected paths
228
- * @returns Object with overrides to merge into base config
229
- *
230
- * @example
231
- * // Environment variables:
232
- * // PUBLIC__app__commerce__api__clientId=abc123
233
- * // PUBLIC__app__pages__cart__quantityUpdateDebounce=1000
234
- * // PUBLIC__app__features__socialLogin__providers=["Apple","Google"]
235
- *
236
- * mergeEnvConfig()
237
- * // Returns:
238
- * // {
239
- * // app: {
240
- * // commerce: { api: { clientId: 'abc123' } },
241
- * // pages: { cart: { quantityUpdateDebounce: 1000 } },
242
- * // features: { socialLogin: { providers: ['Apple', 'Google'] } }
243
- * // }
244
- * // }
56
+ * Get configuration in React components (use this instead of `getConfig` —
57
+ * React Context requires `useContext`). Returns the augmented `AppConfigShape`.
245
58
  */
246
- declare const mergeEnvConfig: (env?: Record<string, string | undefined>, baseConfig?: Record<string, unknown>, options?: MergeEnvConfigOptions) => Record<string, unknown>;
59
+ declare function useConfig<T extends Record<string, unknown> = AppConfigShape>(): T;
247
60
  //#endregion
248
- export { type BaseConfig, ConfigContext, ConfigProvider, type DefineConfigOptions, type Locale, type MergeEnvConfigOptions, type Site, type Url, appConfigContext, createAppConfig, createAppConfigMiddleware, deepMerge, defineConfig, extractValidPaths, getConfig, mergeEnvConfig, parseEnvValue, pathToObject, useConfig };
61
+ export { type AppConfigShape, type BaseConfig, ConfigProvider, type DefineConfigOptions, type Locale, type Site, type Url, appConfigContext, defaultSecurityHeaders, defineConfig, getConfig, useConfig };
249
62
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","names":[],"sources":["../src/config/get-config.ts","../src/config/context.tsx","../src/config/middleware.ts","../src/config/utils.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;QA2C8D,MAAA,CAAA;EACvC,UAAA,MAAA,CAAA;IAAT,cAAA,CAAA,EAdW,MAcX,CAAA,MAAA,EAAA,OAAA,CAAA;EACX;;AA+BH;;;;;;;;AC1CA;AASa,iBDAG,SCAU,CAAA,UDAU,MCAV,CAAA,MAAA,EAAA,OAAA,CAAA,GDAoC,MCApC,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,CAAA,OAAA,CAAA,EDCZ,QCDY,CDCH,qBCDG,CAAA,CAAA,EDEvB,CCFuB;AAS1B;;;;;AAEC;AAaD;AAAiC,iBDSjB,SCTiB,CAAA,UDSG,MCTH,CAAA,MAAA,EAAA,OAAA,CAAA,GDS6B,MCT7B,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,CAAA,CAAA,EDSyD,CCTzD;;;;;;;;;AAjCpB,cAAA,gBAAgB,EAAA,cAAA,CAAA,aAAA,CAAA,MAAA,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA;AAS7B;AASA;;;;;AAIU,cAbG,aAagB,EAbH,MAAA,CAAA,OAeH,CAfG,MAeH,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,IAAA,CAAA;AASvB;;;;;;iBAfgB,0BAA0B,0BAA0B,IAAI;UAI9D,mBAAA;UACE;ECPI,QAAA,EDQF,SCRE;;;;;;;;iBDiBA,cAAA;;;GAAqC,sBAAmB,kBAAA,CAAA,GAAA,CAAA;;;;;;;ADSxE;;;;;;;;AC1CA;AASA;AASA;;;;;AAEC;AAaD;;;;;;;;;ACjBA;AAAoD,iBAApC,yBAAoC,CAAA,UAAA,UAAA,CAAA,CAAA,MAAA,EACxC,CADwC,CAAA,EAAA;EACxC,MAAA,EAEA,kBAFA,CAEmB,QAFnB,CAAA;EAEmB,MAAA,EACnB,kBADmB,CACA,MADA,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA;CAAnB;;;;;;;;;;;;AF5B8C;;;;;AAkB1D;;;;;;;AAiCA;;;;;;;;AC1CA;AASa,cELA,SFKmE,EAAA,CAAtD,UELU,MFKV,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,CAAA,MAAA,EEL2C,CFK3C,EAAA,MAAA,EELsD,MFKtD,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GELgF,CFKhF;AAS1B;;;;;AAEC;AAaD;;;;;;;;;ACjBA;;;AAG+B,cCoBlB,YDpBkB,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,UAAA,CAAA,ECuBd,MDvBc,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GCwB5B,MDxB4B,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;;;;ACf/B;;;;;;AAmCA;AAqEA;AAqCA;AAiCA;AA4CA;;;;;;;;;;cAlHa;;;;;;;;;;;;;cAqCA;;;;UAiCI,qBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4CJ,uBACJ,iDACQ,mCACH,0BACX"}
1
+ {"version":3,"file":"config.d.ts","names":[],"sources":["../src/config/context.tsx","../src/config/get-config.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;AC4EA;AAAoC,UDtCnB,cAAA,CCsCmB;EAA0B,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;;;;;;cD5BjD,kBAAgB,cAAA,CAAA,cAAA;UAWnB,mBAAA;UACE;YACE;;;;;;;;iBASE,cAAA;;;GAAqC,sBAAmB,kBAAA,CAAA,GAAA,CAAA;;;;;qBClC/C;EAJM;;;;;AAc/B;;;AACuB,iBADP,SACO,CAAA,UADa,MACb,CAAA,MAAA,EAAA,OAAA,CAAA,GADuC,cACvC,CAAA,CAAA,OAAA,CAAA,EAAT,QAAS,CAAA,qBAAA,CAAA,CAAA,EACpB,CADoB;;;;AA6BvB;AAAoC,iBAApB,SAAoB,CAAA,UAAA,MAAA,CAAA,MAAA,EAAA,OAAA,CAAA,GAA0B,cAA1B,CAAA,CAAA,CAAA,EAA6C,CAA7C"}