@no-mess/client 0.2.0 → 0.4.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/README.md +108 -125
- package/dist/client.d.ts +12 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +250 -41
- package/dist/client.js.map +1 -1
- package/dist/error-utils.d.ts +20 -0
- package/dist/error-utils.d.ts.map +1 -0
- package/dist/error-utils.js +67 -0
- package/dist/error-utils.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +152 -22
- package/dist/index.js.map +1 -1
- package/dist/live-edit.d.ts.map +1 -1
- package/dist/live-edit.js +263 -102
- package/dist/live-edit.js.map +1 -1
- package/dist/logging.d.ts +6 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +58 -0
- package/dist/logging.js.map +1 -0
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/no-mess-field.d.ts +10 -0
- package/dist/react/no-mess-field.d.ts.map +1 -0
- package/dist/react/no-mess-field.js +7 -0
- package/dist/react/no-mess-field.js.map +1 -0
- package/dist/react/no-mess-preview.d.ts +2 -6
- package/dist/react/no-mess-preview.d.ts.map +1 -1
- package/dist/react/no-mess-preview.js.map +1 -1
- package/dist/react/no-mess-provider.d.ts +21 -0
- package/dist/react/no-mess-provider.d.ts.map +1 -0
- package/dist/react/no-mess-provider.js +286 -0
- package/dist/react/no-mess-provider.js.map +1 -0
- package/dist/react/use-no-mess-live-edit.d.ts.map +1 -1
- package/dist/react/use-no-mess-live-edit.js +32 -2
- package/dist/react/use-no-mess-live-edit.js.map +1 -1
- package/dist/react/use-no-mess-preview.d.ts.map +1 -1
- package/dist/react/use-no-mess-preview.js +29 -6
- package/dist/react/use-no-mess-preview.js.map +1 -1
- package/dist/types.d.ts +78 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +23 -4
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { NoMessContextValue, NoMessEntry, NoMessLiveRouteProviderProps, NoMessProviderProps, UseNoMessEditableEntryOptions } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Provider for route-aware preview and live edit on real site routes.
|
|
4
|
+
* Keeps the legacy preview-only APIs available while adding route reporting
|
|
5
|
+
* and entry binding for live edit on delivered pages.
|
|
6
|
+
*/
|
|
7
|
+
export declare function NoMessLiveRouteProvider({ children, liveEditConfig, ...previewConfig }: NoMessLiveRouteProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
/**
|
|
9
|
+
* Backward-compatible alias for the route-aware provider.
|
|
10
|
+
*/
|
|
11
|
+
export declare function NoMessProvider(props: NoMessProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
/** Access the current no-mess provider context. */
|
|
13
|
+
export declare function useNoMess(): NoMessContextValue | null;
|
|
14
|
+
/** Read a single live field override from provider context. */
|
|
15
|
+
export declare function useNoMessField<T = unknown>(fieldName: string): T | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the entry visible on the current route, switching to preview/draft
|
|
18
|
+
* content when the active iframe session targets this entry.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useNoMessEditableEntry<T extends NoMessEntry>(entry: T, options?: UseNoMessEditableEntryOptions): T;
|
|
21
|
+
//# sourceMappingURL=no-mess-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-mess-provider.d.ts","sourceRoot":"","sources":["../../src/react/no-mess-provider.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,4BAA4B,EAC5B,mBAAmB,EAEnB,6BAA6B,EAG9B,MAAM,aAAa,CAAC;AAwErB;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,cAAc,EACd,GAAG,aAAa,EACjB,EAAE,4BAA4B,2CAuK9B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAExD;AAED,mDAAmD;AACnD,wBAAgB,SAAS,8BAExB;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,iBAI5D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,WAAW,EAC1D,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,6BAA6B,KA4DxC"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { NoMessClient } from "../client.js";
|
|
5
|
+
import { normalizeNoMessError } from "../error-utils.js";
|
|
6
|
+
import { createPreviewHandler } from "../index.js";
|
|
7
|
+
import { createLiveEditHandler } from "../live-edit.js";
|
|
8
|
+
import { DEFAULT_ADMIN_ORIGIN } from "../types.js";
|
|
9
|
+
const REPORTED_ROUTE_CACHE_PREFIX = "no-mess:reported-route";
|
|
10
|
+
const REPORTED_ROUTE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
11
|
+
const TRANSIENT_PARAMS = ["preview", "secret", "sid", "slug", "type"];
|
|
12
|
+
const NoMessContext = createContext(null);
|
|
13
|
+
function sortSearchParams(url) {
|
|
14
|
+
const entries = [...url.searchParams.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
15
|
+
url.search = "";
|
|
16
|
+
for (const [key, value] of entries) {
|
|
17
|
+
url.searchParams.append(key, value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function normalizeRouteUrl(url) {
|
|
21
|
+
const normalized = new URL(url, window.location.href);
|
|
22
|
+
for (const param of TRANSIENT_PARAMS) {
|
|
23
|
+
normalized.searchParams.delete(param);
|
|
24
|
+
}
|
|
25
|
+
sortSearchParams(normalized);
|
|
26
|
+
return normalized.toString();
|
|
27
|
+
}
|
|
28
|
+
function createReportedRouteCacheKey(entryId, url) {
|
|
29
|
+
return `${REPORTED_ROUTE_CACHE_PREFIX}:${entryId}:${url}`;
|
|
30
|
+
}
|
|
31
|
+
function shouldReportRoute(entryId, url) {
|
|
32
|
+
if (typeof localStorage === "undefined") {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
const key = createReportedRouteCacheKey(entryId, url);
|
|
36
|
+
const lastReportedAt = Number(localStorage.getItem(key) ?? "0");
|
|
37
|
+
return (!lastReportedAt || Date.now() - lastReportedAt >= REPORTED_ROUTE_TTL_MS);
|
|
38
|
+
}
|
|
39
|
+
function markRouteReported(entryId, url) {
|
|
40
|
+
if (typeof localStorage === "undefined") {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const key = createReportedRouteCacheKey(entryId, url);
|
|
44
|
+
localStorage.setItem(key, String(Date.now()));
|
|
45
|
+
}
|
|
46
|
+
function defaultPreviewState() {
|
|
47
|
+
return {
|
|
48
|
+
entry: null,
|
|
49
|
+
error: null,
|
|
50
|
+
errorDetails: null,
|
|
51
|
+
isLoading: true,
|
|
52
|
+
status: "waiting-for-admin",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function defaultLiveEditState() {
|
|
56
|
+
return {
|
|
57
|
+
isLiveEditActive: false,
|
|
58
|
+
fieldOverrides: {},
|
|
59
|
+
error: null,
|
|
60
|
+
errorDetails: null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Provider for route-aware preview and live edit on real site routes.
|
|
65
|
+
* Keeps the legacy preview-only APIs available while adding route reporting
|
|
66
|
+
* and entry binding for live edit on delivered pages.
|
|
67
|
+
*/
|
|
68
|
+
export function NoMessLiveRouteProvider({ children, liveEditConfig, ...previewConfig }) {
|
|
69
|
+
const [isIframe, setIsIframe] = useState(false);
|
|
70
|
+
const [preview, setPreview] = useState(defaultPreviewState);
|
|
71
|
+
const [liveEdit, setLiveEdit] = useState(defaultLiveEditState);
|
|
72
|
+
const adminOrigin = liveEditConfig?.adminOrigin ??
|
|
73
|
+
previewConfig.adminOrigin ??
|
|
74
|
+
DEFAULT_ADMIN_ORIGIN;
|
|
75
|
+
const client = useMemo(() => new NoMessClient({
|
|
76
|
+
apiKey: previewConfig.apiKey,
|
|
77
|
+
apiUrl: previewConfig.apiUrl,
|
|
78
|
+
logger: previewConfig.logger,
|
|
79
|
+
}), [previewConfig.apiKey, previewConfig.apiUrl, previewConfig.logger]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
const iframe = window.self !== window.top;
|
|
82
|
+
setIsIframe(iframe);
|
|
83
|
+
if (!iframe) {
|
|
84
|
+
setPreview({
|
|
85
|
+
entry: null,
|
|
86
|
+
error: null,
|
|
87
|
+
errorDetails: null,
|
|
88
|
+
isLoading: false,
|
|
89
|
+
status: "ready",
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const previewHandler = createPreviewHandler({
|
|
94
|
+
client: {
|
|
95
|
+
exchangePreviewSession: async (...args) => {
|
|
96
|
+
setPreview((current) => ({
|
|
97
|
+
...current,
|
|
98
|
+
isLoading: true,
|
|
99
|
+
status: "exchanging-session",
|
|
100
|
+
}));
|
|
101
|
+
return client.exchangePreviewSession(...args);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
adminOrigin,
|
|
105
|
+
logger: previewConfig.logger,
|
|
106
|
+
onEntry: (entry) => {
|
|
107
|
+
setPreview({
|
|
108
|
+
entry,
|
|
109
|
+
error: null,
|
|
110
|
+
errorDetails: null,
|
|
111
|
+
isLoading: false,
|
|
112
|
+
status: "ready",
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
onError: (error) => {
|
|
116
|
+
const normalized = normalizeNoMessError(error, {
|
|
117
|
+
kind: "runtime",
|
|
118
|
+
code: "preview_exchange_failed",
|
|
119
|
+
operation: "NoMessLiveRouteProvider.onPreviewError",
|
|
120
|
+
});
|
|
121
|
+
setPreview({
|
|
122
|
+
entry: null,
|
|
123
|
+
error: normalized,
|
|
124
|
+
errorDetails: normalized,
|
|
125
|
+
isLoading: false,
|
|
126
|
+
status: "error",
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
const liveEditHandler = createLiveEditHandler({
|
|
131
|
+
adminOrigin,
|
|
132
|
+
logger: liveEditConfig?.logger ?? previewConfig.logger,
|
|
133
|
+
onEnter: () => {
|
|
134
|
+
setLiveEdit({
|
|
135
|
+
isLiveEditActive: true,
|
|
136
|
+
fieldOverrides: {},
|
|
137
|
+
error: null,
|
|
138
|
+
errorDetails: null,
|
|
139
|
+
});
|
|
140
|
+
},
|
|
141
|
+
onExit: () => {
|
|
142
|
+
setLiveEdit({
|
|
143
|
+
isLiveEditActive: false,
|
|
144
|
+
fieldOverrides: {},
|
|
145
|
+
error: null,
|
|
146
|
+
errorDetails: null,
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
onError: (error) => {
|
|
150
|
+
const normalized = normalizeNoMessError(error, {
|
|
151
|
+
kind: "runtime",
|
|
152
|
+
code: "live_edit_runtime_failed",
|
|
153
|
+
operation: "NoMessLiveRouteProvider.onLiveEditError",
|
|
154
|
+
});
|
|
155
|
+
setLiveEdit((current) => ({
|
|
156
|
+
...current,
|
|
157
|
+
error: normalized,
|
|
158
|
+
errorDetails: normalized,
|
|
159
|
+
}));
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
const handleMessage = (event) => {
|
|
163
|
+
if (event.origin !== adminOrigin)
|
|
164
|
+
return;
|
|
165
|
+
const data = event.data;
|
|
166
|
+
if (!data || typeof data.type !== "string")
|
|
167
|
+
return;
|
|
168
|
+
if (data.type === "no-mess:field-updated" &&
|
|
169
|
+
typeof data.fieldName === "string") {
|
|
170
|
+
setLiveEdit((current) => ({
|
|
171
|
+
...current,
|
|
172
|
+
fieldOverrides: {
|
|
173
|
+
...current.fieldOverrides,
|
|
174
|
+
[data.fieldName]: data.value,
|
|
175
|
+
},
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
previewHandler.start();
|
|
180
|
+
window.addEventListener("message", handleMessage);
|
|
181
|
+
return () => {
|
|
182
|
+
previewHandler.cleanup();
|
|
183
|
+
liveEditHandler.cleanup();
|
|
184
|
+
window.removeEventListener("message", handleMessage);
|
|
185
|
+
};
|
|
186
|
+
}, [adminOrigin, client, liveEditConfig?.logger, previewConfig.logger]);
|
|
187
|
+
const value = useMemo(() => ({
|
|
188
|
+
adminOrigin,
|
|
189
|
+
apiKey: previewConfig.apiKey,
|
|
190
|
+
apiUrl: previewConfig.apiUrl,
|
|
191
|
+
bindEntry: (entryId) => {
|
|
192
|
+
if (!isIframe)
|
|
193
|
+
return;
|
|
194
|
+
window.parent.postMessage({ type: "no-mess:entry-bound", entryId }, adminOrigin);
|
|
195
|
+
},
|
|
196
|
+
client,
|
|
197
|
+
isIframe,
|
|
198
|
+
preview,
|
|
199
|
+
liveEdit,
|
|
200
|
+
}), [
|
|
201
|
+
adminOrigin,
|
|
202
|
+
client,
|
|
203
|
+
isIframe,
|
|
204
|
+
liveEdit,
|
|
205
|
+
preview,
|
|
206
|
+
previewConfig.apiKey,
|
|
207
|
+
previewConfig.apiUrl,
|
|
208
|
+
]);
|
|
209
|
+
return _jsx(NoMessContext, { value: value, children: children });
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Backward-compatible alias for the route-aware provider.
|
|
213
|
+
*/
|
|
214
|
+
export function NoMessProvider(props) {
|
|
215
|
+
return _jsx(NoMessLiveRouteProvider, { ...props });
|
|
216
|
+
}
|
|
217
|
+
/** Access the current no-mess provider context. */
|
|
218
|
+
export function useNoMess() {
|
|
219
|
+
return useContext(NoMessContext);
|
|
220
|
+
}
|
|
221
|
+
/** Read a single live field override from provider context. */
|
|
222
|
+
export function useNoMessField(fieldName) {
|
|
223
|
+
const ctx = useContext(NoMessContext);
|
|
224
|
+
if (!ctx)
|
|
225
|
+
return undefined;
|
|
226
|
+
return ctx.liveEdit.fieldOverrides[fieldName];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Returns the entry visible on the current route, switching to preview/draft
|
|
230
|
+
* content when the active iframe session targets this entry.
|
|
231
|
+
*/
|
|
232
|
+
export function useNoMessEditableEntry(entry, options) {
|
|
233
|
+
const ctx = useContext(NoMessContext);
|
|
234
|
+
const lastBoundEntryId = useRef(null);
|
|
235
|
+
const registerCurrentUrl = options?.registerCurrentUrl ?? true;
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
if (!ctx || !registerCurrentUrl)
|
|
238
|
+
return;
|
|
239
|
+
if (typeof window === "undefined")
|
|
240
|
+
return;
|
|
241
|
+
let normalizedUrl;
|
|
242
|
+
try {
|
|
243
|
+
normalizedUrl = normalizeRouteUrl(options?.url ?? window.location.href);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (!shouldReportRoute(entry._id, normalizedUrl)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
let cancelled = false;
|
|
252
|
+
const reportOptions = {
|
|
253
|
+
entryId: entry._id,
|
|
254
|
+
url: normalizedUrl,
|
|
255
|
+
};
|
|
256
|
+
void ctx.client
|
|
257
|
+
.reportLiveEditRoute(reportOptions)
|
|
258
|
+
.then(() => {
|
|
259
|
+
if (!cancelled) {
|
|
260
|
+
markRouteReported(entry._id, normalizedUrl);
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
.catch(() => { });
|
|
264
|
+
return () => {
|
|
265
|
+
cancelled = true;
|
|
266
|
+
};
|
|
267
|
+
}, [ctx, entry._id, options?.url, registerCurrentUrl]);
|
|
268
|
+
const matchesPreviewEntry = ctx?.preview.entry?._id === entry._id;
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
if (!ctx || !ctx.isIframe || !matchesPreviewEntry)
|
|
271
|
+
return;
|
|
272
|
+
if (lastBoundEntryId.current === entry._id)
|
|
273
|
+
return;
|
|
274
|
+
ctx.bindEntry(entry._id);
|
|
275
|
+
lastBoundEntryId.current = entry._id;
|
|
276
|
+
}, [ctx, entry._id, matchesPreviewEntry]);
|
|
277
|
+
if (!ctx || !matchesPreviewEntry) {
|
|
278
|
+
return entry;
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
...entry,
|
|
282
|
+
...ctx.preview.entry,
|
|
283
|
+
...ctx.liveEdit.fieldOverrides,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=no-mess-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-mess-provider.js","sourceRoot":"","sources":["../../src/react/no-mess-provider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-no-mess-live-edit.d.ts","sourceRoot":"","sources":["../../src/react/use-no-mess-live-edit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-no-mess-live-edit.d.ts","sourceRoot":"","sources":["../../src/react/use-no-mess-live-edit.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAGrB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,uBAAuB,GAC9B,uBAAuB,CA8EzB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { normalizeNoMessError } from "../error-utils.js";
|
|
4
|
+
import { createSdkLogger } from "../logging.js";
|
|
3
5
|
import { createLiveEditHandler } from "../live-edit.js";
|
|
4
6
|
import { DEFAULT_ADMIN_ORIGIN } from "../types.js";
|
|
5
7
|
/**
|
|
@@ -19,8 +21,12 @@ import { DEFAULT_ADMIN_ORIGIN } from "../types.js";
|
|
|
19
21
|
export function useNoMessLiveEdit(config) {
|
|
20
22
|
const [isLiveEditActive, setIsLiveEditActive] = useState(false);
|
|
21
23
|
const [fieldOverrides, setFieldOverrides] = useState({});
|
|
24
|
+
const [error, setError] = useState(null);
|
|
25
|
+
const [errorDetails, setErrorDetails] = useState(null);
|
|
22
26
|
const configRef = useRef(config);
|
|
23
27
|
configRef.current = config;
|
|
28
|
+
const loggerRef = useRef(createSdkLogger(config.logger));
|
|
29
|
+
loggerRef.current = createSdkLogger(config.logger);
|
|
24
30
|
const handleFieldUpdate = useCallback((event) => {
|
|
25
31
|
const origin = configRef.current.adminOrigin ?? DEFAULT_ADMIN_ORIGIN;
|
|
26
32
|
if (event.origin !== origin)
|
|
@@ -28,25 +34,49 @@ export function useNoMessLiveEdit(config) {
|
|
|
28
34
|
const data = event.data;
|
|
29
35
|
if (!data || typeof data.type !== "string")
|
|
30
36
|
return;
|
|
31
|
-
if (data.type === "no-mess:field-updated" && data.fieldName) {
|
|
37
|
+
if (data.type === "no-mess:field-updated" && typeof data.fieldName === "string") {
|
|
32
38
|
setFieldOverrides((prev) => ({
|
|
33
39
|
...prev,
|
|
34
40
|
[data.fieldName]: data.value,
|
|
35
41
|
}));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (data.type === "no-mess:field-updated") {
|
|
45
|
+
loggerRef.current({
|
|
46
|
+
level: "debug",
|
|
47
|
+
code: "live_edit_runtime_failed",
|
|
48
|
+
message: "Ignored malformed live edit field update message in React state bridge",
|
|
49
|
+
scope: "live-edit-react",
|
|
50
|
+
operation: "useNoMessLiveEdit.handleFieldUpdate",
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
context: {},
|
|
53
|
+
});
|
|
36
54
|
}
|
|
37
55
|
}, []);
|
|
38
56
|
useEffect(() => {
|
|
39
57
|
const adminOrigin = configRef.current.adminOrigin ?? DEFAULT_ADMIN_ORIGIN;
|
|
40
58
|
const handle = createLiveEditHandler({
|
|
41
59
|
adminOrigin,
|
|
60
|
+
logger: configRef.current.logger,
|
|
42
61
|
onEnter: () => {
|
|
43
62
|
setIsLiveEditActive(true);
|
|
44
63
|
setFieldOverrides({});
|
|
64
|
+
setError(null);
|
|
65
|
+
setErrorDetails(null);
|
|
45
66
|
},
|
|
46
67
|
onExit: () => {
|
|
47
68
|
setIsLiveEditActive(false);
|
|
48
69
|
setFieldOverrides({});
|
|
49
70
|
},
|
|
71
|
+
onError: (err) => {
|
|
72
|
+
const normalized = normalizeNoMessError(err, {
|
|
73
|
+
kind: "runtime",
|
|
74
|
+
code: "live_edit_runtime_failed",
|
|
75
|
+
operation: "useNoMessLiveEdit.onError",
|
|
76
|
+
});
|
|
77
|
+
setError(normalized);
|
|
78
|
+
setErrorDetails(normalized);
|
|
79
|
+
},
|
|
50
80
|
});
|
|
51
81
|
// Also listen for field-updated to track overrides in React state
|
|
52
82
|
window.addEventListener("message", handleFieldUpdate);
|
|
@@ -55,6 +85,6 @@ export function useNoMessLiveEdit(config) {
|
|
|
55
85
|
window.removeEventListener("message", handleFieldUpdate);
|
|
56
86
|
};
|
|
57
87
|
}, [handleFieldUpdate]);
|
|
58
|
-
return { isLiveEditActive, fieldOverrides };
|
|
88
|
+
return { isLiveEditActive, fieldOverrides, error, errorDetails };
|
|
59
89
|
}
|
|
60
90
|
//# sourceMappingURL=use-no-mess-live-edit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-no-mess-live-edit.js","sourceRoot":"","sources":["../../src/react/use-no-mess-live-edit.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-no-mess-live-edit.js","sourceRoot":"","sources":["../../src/react/use-no-mess-live-edit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-no-mess-preview.d.ts","sourceRoot":"","sources":["../../src/react/use-no-mess-preview.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-no-mess-preview.d.ts","sourceRoot":"","sources":["../../src/react/use-no-mess-preview.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,WAAW,EAEX,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAGrB,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAClE,MAAM,EAAE,sBAAsB,GAC7B,sBAAsB,CAAC,CAAC,CAAC,CA0D3B"}
|
|
@@ -1,35 +1,58 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { NoMessClient } from "../client.js";
|
|
4
|
+
import { normalizeNoMessError } from "../error-utils.js";
|
|
4
5
|
import { createPreviewHandler } from "../index.js";
|
|
5
6
|
import { DEFAULT_ADMIN_ORIGIN } from "../types.js";
|
|
6
7
|
export function useNoMessPreview(config) {
|
|
7
8
|
const [entry, setEntry] = useState(null);
|
|
8
9
|
const [error, setError] = useState(null);
|
|
9
|
-
const [
|
|
10
|
+
const [errorDetails, setErrorDetails] = useState(null);
|
|
11
|
+
const [status, setStatus] = useState("waiting-for-admin");
|
|
10
12
|
const configRef = useRef(config);
|
|
11
13
|
configRef.current = config;
|
|
12
14
|
useEffect(() => {
|
|
13
|
-
const
|
|
15
|
+
const baseClient = new NoMessClient({
|
|
14
16
|
apiKey: configRef.current.apiKey,
|
|
15
17
|
apiUrl: configRef.current.apiUrl,
|
|
18
|
+
logger: configRef.current.logger,
|
|
16
19
|
});
|
|
20
|
+
const client = {
|
|
21
|
+
exchangePreviewSession: async (...args) => {
|
|
22
|
+
setStatus("exchanging-session");
|
|
23
|
+
return baseClient.exchangePreviewSession(...args);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
17
26
|
const handler = createPreviewHandler({
|
|
18
27
|
client,
|
|
19
28
|
adminOrigin: configRef.current.adminOrigin ?? DEFAULT_ADMIN_ORIGIN,
|
|
29
|
+
logger: configRef.current.logger,
|
|
20
30
|
onEntry: (e) => {
|
|
21
31
|
setEntry(e);
|
|
22
32
|
setError(null);
|
|
23
|
-
|
|
33
|
+
setErrorDetails(null);
|
|
34
|
+
setStatus("ready");
|
|
24
35
|
},
|
|
25
36
|
onError: (err) => {
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
const normalized = normalizeNoMessError(err, {
|
|
38
|
+
kind: "runtime",
|
|
39
|
+
code: "preview_exchange_failed",
|
|
40
|
+
operation: "useNoMessPreview.onError",
|
|
41
|
+
});
|
|
42
|
+
setError(normalized);
|
|
43
|
+
setErrorDetails(normalized);
|
|
44
|
+
setStatus("error");
|
|
28
45
|
},
|
|
29
46
|
});
|
|
30
47
|
handler.start();
|
|
31
48
|
return () => handler.cleanup();
|
|
32
49
|
}, []);
|
|
33
|
-
return {
|
|
50
|
+
return {
|
|
51
|
+
entry,
|
|
52
|
+
error,
|
|
53
|
+
errorDetails,
|
|
54
|
+
isLoading: status !== "ready" && status !== "error",
|
|
55
|
+
status,
|
|
56
|
+
};
|
|
34
57
|
}
|
|
35
58
|
//# sourceMappingURL=use-no-mess-preview.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-no-mess-preview.js","sourceRoot":"","sources":["../../src/react/use-no-mess-preview.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"use-no-mess-preview.js","sourceRoot":"","sources":["../../src/react/use-no-mess-preview.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,UAAU,gBAAgB,CAC9B,MAA8B;IAE9B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAW,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IAC3E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAClC,mBAAmB,CACpB,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,UAAU,GAAG,IAAI,YAAY,CAAC;YAClC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM;YAChC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM;YAChC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM;SACjC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG;YACb,sBAAsB,EAAE,KAAK,EAAE,GAAG,IAAwD,EAAE,EAAE;gBAC5F,SAAS,CAAC,oBAAoB,CAAC,CAAC;gBAChC,OAAO,UAAU,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC,CAAC;YACpD,CAAC;SACF,CAAC;QAEF,MAAM,OAAO,GAAG,oBAAoB,CAAC;YACnC,MAAM;YACN,WAAW,EAAE,SAAS,CAAC,OAAO,CAAC,WAAW,IAAI,oBAAoB;YAClE,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM;YAChC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACb,QAAQ,CAAC,CAAM,CAAC,CAAC;gBACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACf,eAAe,CAAC,IAAI,CAAC,CAAC;gBACtB,SAAS,CAAC,OAAO,CAAC,CAAC;YACrB,CAAC;YACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACf,MAAM,UAAU,GAAG,oBAAoB,CAAC,GAAG,EAAE;oBAC3C,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,yBAAyB;oBAC/B,SAAS,EAAE,0BAA0B;iBACtC,CAAC,CAAC;gBACH,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACrB,eAAe,CAAC,UAAU,CAAC,CAAC;gBAC5B,SAAS,CAAC,OAAO,CAAC,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,KAAK;QACL,KAAK;QACL,YAAY;QACZ,SAAS,EAAE,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO;QACnD,MAAM;KACP,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
export declare const DEFAULT_API_URL = "https://api.
|
|
1
|
+
export declare const DEFAULT_API_URL = "https://api.nomess.xyz";
|
|
2
2
|
export declare const DEFAULT_ADMIN_ORIGIN = "https://admin.no-mess.xyz";
|
|
3
|
+
export type NoMessErrorKind = "config" | "network" | "http" | "response" | "crypto" | "protocol" | "runtime";
|
|
4
|
+
export type NoMessErrorCode = "secret_key_in_browser" | "request_failed" | "http_error" | "invalid_success_response" | "invalid_error_response" | "crypto_unavailable" | "invalid_session_secret" | "preview_message_invalid" | "preview_exchange_failed" | "preview_postmessage_failed" | "live_edit_runtime_failed";
|
|
5
|
+
export type NoMessLogLevel = "debug" | "info" | "warn" | "error";
|
|
6
|
+
export interface NoMessLogEvent {
|
|
7
|
+
level: NoMessLogLevel;
|
|
8
|
+
code: NoMessErrorCode;
|
|
9
|
+
message: string;
|
|
10
|
+
scope: string;
|
|
11
|
+
operation?: string;
|
|
12
|
+
error?: NoMessError;
|
|
13
|
+
timestamp: string;
|
|
14
|
+
context: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export type NoMessLogger = (event: NoMessLogEvent) => void;
|
|
17
|
+
export interface NoMessErrorOptions {
|
|
18
|
+
kind?: NoMessErrorKind;
|
|
19
|
+
code?: NoMessErrorCode;
|
|
20
|
+
status?: number;
|
|
21
|
+
retryable?: boolean;
|
|
22
|
+
operation?: string;
|
|
23
|
+
method?: string;
|
|
24
|
+
url?: string;
|
|
25
|
+
requestId?: string;
|
|
26
|
+
details?: Record<string, unknown>;
|
|
27
|
+
cause?: unknown;
|
|
28
|
+
}
|
|
3
29
|
export interface NoMessClientConfig {
|
|
4
30
|
apiUrl?: string;
|
|
5
31
|
/**
|
|
@@ -10,6 +36,7 @@ export interface NoMessClientConfig {
|
|
|
10
36
|
* - **Publishable key**: Safe for client-side use. Read-only access to published content.
|
|
11
37
|
*/
|
|
12
38
|
apiKey: string;
|
|
39
|
+
logger?: NoMessLogger;
|
|
13
40
|
}
|
|
14
41
|
/** Returns true if the key is a publishable key (nm_pub_ prefix). */
|
|
15
42
|
export declare function isPublishableKey(key: string): boolean;
|
|
@@ -66,6 +93,11 @@ export interface PreviewSessionAuth {
|
|
|
66
93
|
sessionId: string;
|
|
67
94
|
sessionSecret: string;
|
|
68
95
|
}
|
|
96
|
+
/** Report a delivery URL for route-aware Live Edit. */
|
|
97
|
+
export interface ReportLiveEditRouteOptions {
|
|
98
|
+
entryId: string;
|
|
99
|
+
url?: string;
|
|
100
|
+
}
|
|
69
101
|
export interface PreviewExchangeResult {
|
|
70
102
|
entry: NoMessEntry;
|
|
71
103
|
sessionId: string;
|
|
@@ -78,16 +110,21 @@ export interface PreviewHandlerConfig {
|
|
|
78
110
|
adminOrigin: string;
|
|
79
111
|
onEntry: (entry: NoMessEntry) => void;
|
|
80
112
|
onError?: (error: Error) => void;
|
|
113
|
+
logger?: NoMessLogger;
|
|
81
114
|
}
|
|
82
115
|
export interface UseNoMessPreviewConfig {
|
|
83
116
|
apiKey: string;
|
|
84
117
|
apiUrl?: string;
|
|
85
118
|
adminOrigin?: string;
|
|
119
|
+
logger?: NoMessLogger;
|
|
86
120
|
}
|
|
121
|
+
export type UseNoMessPreviewStatus = "waiting-for-admin" | "exchanging-session" | "ready" | "error";
|
|
87
122
|
export interface UseNoMessPreviewResult<T extends NoMessEntry = NoMessEntry> {
|
|
88
123
|
entry: T | null;
|
|
89
124
|
error: Error | null;
|
|
125
|
+
errorDetails: NoMessError | null;
|
|
90
126
|
isLoading: boolean;
|
|
127
|
+
status: UseNoMessPreviewStatus;
|
|
91
128
|
}
|
|
92
129
|
export interface ContentTypeSchema {
|
|
93
130
|
name: string;
|
|
@@ -138,6 +175,30 @@ export interface SchemaGetResponse {
|
|
|
138
175
|
contentType: ContentTypeSchema;
|
|
139
176
|
sdkExample: string;
|
|
140
177
|
}
|
|
178
|
+
/** Props for the route-aware provider used on real site routes. */
|
|
179
|
+
export interface NoMessLiveRouteProviderProps extends UseNoMessPreviewConfig {
|
|
180
|
+
children: import("react").ReactNode;
|
|
181
|
+
liveEditConfig?: UseNoMessLiveEditConfig;
|
|
182
|
+
}
|
|
183
|
+
/** Backward-compatible alias for the route-aware provider props. */
|
|
184
|
+
export interface NoMessProviderProps extends NoMessLiveRouteProviderProps {
|
|
185
|
+
}
|
|
186
|
+
/** Options for binding a rendered entry to the current route. */
|
|
187
|
+
export interface UseNoMessEditableEntryOptions {
|
|
188
|
+
registerCurrentUrl?: boolean;
|
|
189
|
+
url?: string;
|
|
190
|
+
}
|
|
191
|
+
/** Shared provider context for preview/live-edit state. */
|
|
192
|
+
export interface NoMessContextValue {
|
|
193
|
+
adminOrigin: string;
|
|
194
|
+
apiKey: string;
|
|
195
|
+
apiUrl?: string;
|
|
196
|
+
bindEntry: (entryId: string) => void;
|
|
197
|
+
client: Pick<import("./client.js").NoMessClient, "reportLiveEditRoute">;
|
|
198
|
+
isIframe: boolean;
|
|
199
|
+
preview: UseNoMessPreviewResult;
|
|
200
|
+
liveEdit: UseNoMessLiveEditResult;
|
|
201
|
+
}
|
|
141
202
|
export interface LiveEditFieldInfo {
|
|
142
203
|
name: string;
|
|
143
204
|
type: string;
|
|
@@ -148,19 +209,34 @@ export interface LiveEditConfig {
|
|
|
148
209
|
onFieldClicked?: (fieldName: string) => void;
|
|
149
210
|
onEnter?: () => void;
|
|
150
211
|
onExit?: () => void;
|
|
212
|
+
onError?: (error: Error) => void;
|
|
213
|
+
logger?: NoMessLogger;
|
|
151
214
|
}
|
|
152
215
|
export interface LiveEditHandle {
|
|
153
216
|
cleanup: () => void;
|
|
154
217
|
}
|
|
155
218
|
export interface UseNoMessLiveEditConfig {
|
|
156
219
|
adminOrigin?: string;
|
|
220
|
+
logger?: NoMessLogger;
|
|
157
221
|
}
|
|
158
222
|
export interface UseNoMessLiveEditResult {
|
|
159
223
|
isLiveEditActive: boolean;
|
|
160
224
|
fieldOverrides: Record<string, unknown>;
|
|
225
|
+
error: Error | null;
|
|
226
|
+
errorDetails: NoMessError | null;
|
|
161
227
|
}
|
|
162
228
|
export declare class NoMessError extends Error {
|
|
163
|
-
|
|
229
|
+
readonly kind: NoMessErrorKind;
|
|
230
|
+
readonly code: NoMessErrorCode;
|
|
231
|
+
readonly status?: number;
|
|
232
|
+
readonly retryable: boolean;
|
|
233
|
+
readonly operation?: string;
|
|
234
|
+
readonly method?: string;
|
|
235
|
+
readonly url?: string;
|
|
236
|
+
readonly requestId?: string;
|
|
237
|
+
readonly details?: Record<string, unknown>;
|
|
238
|
+
readonly cause?: unknown;
|
|
164
239
|
constructor(message: string, status: number);
|
|
240
|
+
constructor(message: string, options?: NoMessErrorOptions);
|
|
165
241
|
}
|
|
166
242
|
//# sourceMappingURL=types.d.ts.map
|