@alpaca-headless/alpaca-headless-nextjs 1.0.4230 → 1.0.4231
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.
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { EditorIntegrationClient } from "./EditorIntegrationClient";
|
|
3
3
|
export function EditorIntegration(props) {
|
|
4
|
+
// Server-side log (will appear in server logs)
|
|
5
|
+
console.log(`[HEADLESS-SERVER] EditorIntegration render, mode: ${props.mode}`);
|
|
4
6
|
if (props.mode !== "normal") {
|
|
7
|
+
console.log(`[HEADLESS-SERVER] Rendering EditorIntegrationClient`);
|
|
5
8
|
return _jsx(EditorIntegrationClient, Object.assign({}, props));
|
|
6
9
|
}
|
|
10
|
+
console.log(`[HEADLESS-SERVER] Mode is normal, returning null (no client integration)`);
|
|
7
11
|
return null;
|
|
8
12
|
}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect } from "react";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
4
|
import useExposeRefreshFunction from "./useExposeRefreshFunction";
|
|
5
|
+
// Helper for consistent logging with timestamps
|
|
6
|
+
const log = (message, data) => {
|
|
7
|
+
const timestamp = new Date().toISOString();
|
|
8
|
+
if (data !== undefined) {
|
|
9
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`, data);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
5
15
|
export function EditorIntegrationClient({ timings, mode, }) {
|
|
16
|
+
const instanceIdRef = useRef(Math.random().toString(36).substring(7));
|
|
17
|
+
log(`EditorIntegrationClient RENDER, mode: ${mode}, instance: ${instanceIdRef.current}`);
|
|
18
|
+
log(`window.parent === window:`, window.parent === window);
|
|
6
19
|
useExposeRefreshFunction();
|
|
7
20
|
useEffect(() => {
|
|
21
|
+
log(`EditorIntegrationClient useEffect RUNNING, instance: ${instanceIdRef.current}`);
|
|
8
22
|
const handleKeyDown = (event) => {
|
|
9
23
|
if (event.ctrlKey && event.key === "F11") {
|
|
10
24
|
event.preventDefault();
|
|
@@ -16,8 +30,10 @@ export function EditorIntegrationClient({ timings, mode, }) {
|
|
|
16
30
|
}
|
|
17
31
|
};
|
|
18
32
|
window.addEventListener("keydown", handleKeyDown);
|
|
33
|
+
log(`Sending editor-timings postMessage to parent`);
|
|
19
34
|
window.parent.postMessage({ type: "editor-timings", timings }, "*");
|
|
20
35
|
return () => {
|
|
36
|
+
log(`EditorIntegrationClient useEffect CLEANUP, instance: ${instanceIdRef.current}`);
|
|
21
37
|
window.removeEventListener("keydown", handleKeyDown);
|
|
22
38
|
};
|
|
23
39
|
}, []);
|
|
@@ -1,31 +1,72 @@
|
|
|
1
1
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
2
|
+
import { useEffect, useState, useRef } from "react";
|
|
3
3
|
import uuid from "react-uuid";
|
|
4
|
+
// Helper for consistent logging with timestamps
|
|
5
|
+
const log = (message, data) => {
|
|
6
|
+
const timestamp = new Date().toISOString();
|
|
7
|
+
if (data !== undefined) {
|
|
8
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`, data);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
4
14
|
const useExposeRefreshFunction = () => {
|
|
5
15
|
const router = useRouter();
|
|
6
16
|
const searchParams = useSearchParams();
|
|
7
17
|
const [refreshStart, setRefreshStart] = useState();
|
|
18
|
+
const mountCountRef = useRef(0);
|
|
19
|
+
const instanceIdRef = useRef(Math.random().toString(36).substring(7));
|
|
20
|
+
log(`useExposeRefreshFunction hook called, instance: ${instanceIdRef.current}`);
|
|
8
21
|
useEffect(() => {
|
|
22
|
+
mountCountRef.current++;
|
|
23
|
+
const mountId = mountCountRef.current;
|
|
24
|
+
log(`useEffect[router] RUNNING - mount #${mountId}, instance: ${instanceIdRef.current}`);
|
|
25
|
+
log(`Current window.requestRefresh before set:`, typeof window.requestRefresh);
|
|
26
|
+
log(`window.parent === window:`, window.parent === window);
|
|
9
27
|
// Expose the refresh function to the parent window
|
|
10
28
|
window.requestRefresh = (newUri) => {
|
|
11
|
-
|
|
29
|
+
log(`requestRefresh CALLED with:`, newUri);
|
|
30
|
+
log(`Called from mount #${mountId}, instance: ${instanceIdRef.current}`);
|
|
12
31
|
if (!newUri) {
|
|
13
32
|
const uri = new URL(window.location.href);
|
|
14
33
|
uri.searchParams.set("edit_rev", uuid().toString());
|
|
15
34
|
newUri = uri.toString();
|
|
16
35
|
}
|
|
36
|
+
log(`router.replace() about to be called with:`, newUri);
|
|
17
37
|
router.replace(newUri, { scroll: false });
|
|
18
38
|
setRefreshStart(performance.now());
|
|
39
|
+
log(`router.replace() completed`);
|
|
19
40
|
return true; // Indicate the function executed successfully
|
|
20
41
|
};
|
|
42
|
+
log(`window.requestRefresh SET, typeof:`, typeof window.requestRefresh);
|
|
43
|
+
// Notify parent that integration is ready
|
|
44
|
+
if (window.parent !== window) {
|
|
45
|
+
log(`Sending integration-ready postMessage to parent`);
|
|
46
|
+
try {
|
|
47
|
+
window.parent.postMessage({ type: "integration-ready" }, "*");
|
|
48
|
+
log(`integration-ready postMessage SENT successfully`);
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
log(`integration-ready postMessage FAILED:`, e);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
log(`NOT in iframe (window.parent === window), skipping integration-ready`);
|
|
56
|
+
}
|
|
21
57
|
// Optionally clean up when the component unmounts
|
|
22
58
|
return () => {
|
|
59
|
+
log(`useEffect[router] CLEANUP - mount #${mountId}, instance: ${instanceIdRef.current}`);
|
|
60
|
+
log(`Deleting window.requestRefresh`);
|
|
23
61
|
delete window.requestRefresh;
|
|
62
|
+
log(`window.requestRefresh after delete:`, typeof window.requestRefresh);
|
|
24
63
|
};
|
|
25
64
|
}, [router]);
|
|
26
65
|
useEffect(() => {
|
|
27
|
-
if (refreshStart)
|
|
28
|
-
|
|
66
|
+
if (refreshStart) {
|
|
67
|
+
const duration = performance.now() - refreshStart;
|
|
68
|
+
log(`Refresh complete in ${duration}ms`);
|
|
69
|
+
}
|
|
29
70
|
}, [searchParams]);
|
|
30
71
|
return null; // This hook doesn't render anything
|
|
31
72
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alpaca-headless/alpaca-headless-nextjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4231",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Alpaca Headless",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"typescript": "^5"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@alpaca-headless/alpaca-headless": "^1.0.
|
|
55
|
+
"@alpaca-headless/alpaca-headless": "^1.0.4231",
|
|
56
56
|
"axios": "^1.8.1",
|
|
57
57
|
"https-proxy-agent": "^7.0.4",
|
|
58
58
|
"next": "^14.2.4",
|
|
@@ -8,8 +8,17 @@ export type EditorIntegrationProps = {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export function EditorIntegration(props: EditorIntegrationProps) {
|
|
11
|
+
// Server-side log (will appear in server logs)
|
|
12
|
+
console.log(
|
|
13
|
+
`[HEADLESS-SERVER] EditorIntegration render, mode: ${props.mode}`
|
|
14
|
+
);
|
|
15
|
+
|
|
11
16
|
if (props.mode !== "normal") {
|
|
17
|
+
console.log(`[HEADLESS-SERVER] Rendering EditorIntegrationClient`);
|
|
12
18
|
return <EditorIntegrationClient {...props} />;
|
|
13
19
|
}
|
|
20
|
+
console.log(
|
|
21
|
+
`[HEADLESS-SERVER] Mode is normal, returning null (no client integration)`
|
|
22
|
+
);
|
|
14
23
|
return null;
|
|
15
24
|
}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useEffect } from "react";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
4
|
import useExposeRefreshFunction from "./useExposeRefreshFunction";
|
|
5
5
|
|
|
6
|
+
// Helper for consistent logging with timestamps
|
|
7
|
+
const log = (message: string, data?: any) => {
|
|
8
|
+
const timestamp = new Date().toISOString();
|
|
9
|
+
if (data !== undefined) {
|
|
10
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`, data);
|
|
11
|
+
} else {
|
|
12
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
6
16
|
export function EditorIntegrationClient({
|
|
7
17
|
timings,
|
|
8
18
|
mode,
|
|
@@ -12,9 +22,20 @@ export function EditorIntegrationClient({
|
|
|
12
22
|
};
|
|
13
23
|
mode: "edit" | "preview" | "normal";
|
|
14
24
|
}) {
|
|
25
|
+
const instanceIdRef = useRef(Math.random().toString(36).substring(7));
|
|
26
|
+
|
|
27
|
+
log(
|
|
28
|
+
`EditorIntegrationClient RENDER, mode: ${mode}, instance: ${instanceIdRef.current}`
|
|
29
|
+
);
|
|
30
|
+
log(`window.parent === window:`, window.parent === window);
|
|
31
|
+
|
|
15
32
|
useExposeRefreshFunction();
|
|
16
33
|
|
|
17
34
|
useEffect(() => {
|
|
35
|
+
log(
|
|
36
|
+
`EditorIntegrationClient useEffect RUNNING, instance: ${instanceIdRef.current}`
|
|
37
|
+
);
|
|
38
|
+
|
|
18
39
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
19
40
|
if (event.ctrlKey && event.key === "F11") {
|
|
20
41
|
event.preventDefault();
|
|
@@ -27,9 +48,13 @@ export function EditorIntegrationClient({
|
|
|
27
48
|
};
|
|
28
49
|
|
|
29
50
|
window.addEventListener("keydown", handleKeyDown);
|
|
51
|
+
log(`Sending editor-timings postMessage to parent`);
|
|
30
52
|
window.parent.postMessage({ type: "editor-timings", timings }, "*");
|
|
31
53
|
|
|
32
54
|
return () => {
|
|
55
|
+
log(
|
|
56
|
+
`EditorIntegrationClient useEffect CLEANUP, instance: ${instanceIdRef.current}`
|
|
57
|
+
);
|
|
33
58
|
window.removeEventListener("keydown", handleKeyDown);
|
|
34
59
|
};
|
|
35
60
|
}, []);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
2
|
+
import { useEffect, useState, useRef } from "react";
|
|
3
3
|
import uuid from "react-uuid";
|
|
4
4
|
|
|
5
5
|
declare global {
|
|
@@ -8,35 +8,89 @@ declare global {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
// Helper for consistent logging with timestamps
|
|
12
|
+
const log = (message: string, data?: any) => {
|
|
13
|
+
const timestamp = new Date().toISOString();
|
|
14
|
+
if (data !== undefined) {
|
|
15
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`, data);
|
|
16
|
+
} else {
|
|
17
|
+
console.log(`[HEADLESS ${timestamp}] ${message}`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
11
21
|
const useExposeRefreshFunction = () => {
|
|
12
22
|
const router = useRouter();
|
|
13
23
|
const searchParams = useSearchParams();
|
|
14
24
|
const [refreshStart, setRefreshStart] = useState<number>();
|
|
25
|
+
const mountCountRef = useRef(0);
|
|
26
|
+
const instanceIdRef = useRef(Math.random().toString(36).substring(7));
|
|
27
|
+
|
|
28
|
+
log(
|
|
29
|
+
`useExposeRefreshFunction hook called, instance: ${instanceIdRef.current}`
|
|
30
|
+
);
|
|
15
31
|
|
|
16
32
|
useEffect(() => {
|
|
33
|
+
mountCountRef.current++;
|
|
34
|
+
const mountId = mountCountRef.current;
|
|
35
|
+
log(
|
|
36
|
+
`useEffect[router] RUNNING - mount #${mountId}, instance: ${instanceIdRef.current}`
|
|
37
|
+
);
|
|
38
|
+
log(
|
|
39
|
+
`Current window.requestRefresh before set:`,
|
|
40
|
+
typeof window.requestRefresh
|
|
41
|
+
);
|
|
42
|
+
log(`window.parent === window:`, window.parent === window);
|
|
43
|
+
|
|
17
44
|
// Expose the refresh function to the parent window
|
|
18
45
|
window.requestRefresh = (newUri?: string) => {
|
|
19
|
-
|
|
46
|
+
log(`requestRefresh CALLED with:`, newUri);
|
|
47
|
+
log(`Called from mount #${mountId}, instance: ${instanceIdRef.current}`);
|
|
20
48
|
if (!newUri) {
|
|
21
49
|
const uri = new URL(window.location.href);
|
|
22
50
|
uri.searchParams.set("edit_rev", uuid().toString());
|
|
23
51
|
newUri = uri.toString();
|
|
24
52
|
}
|
|
25
53
|
|
|
54
|
+
log(`router.replace() about to be called with:`, newUri);
|
|
26
55
|
router.replace(newUri, { scroll: false });
|
|
27
56
|
setRefreshStart(performance.now());
|
|
57
|
+
log(`router.replace() completed`);
|
|
28
58
|
return true; // Indicate the function executed successfully
|
|
29
59
|
};
|
|
30
60
|
|
|
61
|
+
log(`window.requestRefresh SET, typeof:`, typeof window.requestRefresh);
|
|
62
|
+
|
|
63
|
+
// Notify parent that integration is ready
|
|
64
|
+
if (window.parent !== window) {
|
|
65
|
+
log(`Sending integration-ready postMessage to parent`);
|
|
66
|
+
try {
|
|
67
|
+
window.parent.postMessage({ type: "integration-ready" }, "*");
|
|
68
|
+
log(`integration-ready postMessage SENT successfully`);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
log(`integration-ready postMessage FAILED:`, e);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
log(
|
|
74
|
+
`NOT in iframe (window.parent === window), skipping integration-ready`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
31
78
|
// Optionally clean up when the component unmounts
|
|
32
79
|
return () => {
|
|
80
|
+
log(
|
|
81
|
+
`useEffect[router] CLEANUP - mount #${mountId}, instance: ${instanceIdRef.current}`
|
|
82
|
+
);
|
|
83
|
+
log(`Deleting window.requestRefresh`);
|
|
33
84
|
delete window.requestRefresh;
|
|
85
|
+
log(`window.requestRefresh after delete:`, typeof window.requestRefresh);
|
|
34
86
|
};
|
|
35
87
|
}, [router]);
|
|
36
88
|
|
|
37
89
|
useEffect(() => {
|
|
38
|
-
if (refreshStart)
|
|
39
|
-
|
|
90
|
+
if (refreshStart) {
|
|
91
|
+
const duration = performance.now() - refreshStart;
|
|
92
|
+
log(`Refresh complete in ${duration}ms`);
|
|
93
|
+
}
|
|
40
94
|
}, [searchParams]);
|
|
41
95
|
|
|
42
96
|
return null; // This hook doesn't render anything
|