@shopify/cli-hydrogen 6.0.2 → 7.0.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.
Files changed (108) hide show
  1. package/dist/commands/hydrogen/build.js +40 -78
  2. package/dist/commands/hydrogen/codegen.js +8 -3
  3. package/dist/commands/hydrogen/deploy.js +173 -37
  4. package/dist/commands/hydrogen/deploy.test.js +192 -20
  5. package/dist/commands/hydrogen/dev.js +56 -31
  6. package/dist/commands/hydrogen/init.js +1 -1
  7. package/dist/commands/hydrogen/init.test.js +155 -53
  8. package/dist/commands/hydrogen/link.js +5 -21
  9. package/dist/commands/hydrogen/link.test.js +10 -10
  10. package/dist/commands/hydrogen/preview.js +22 -11
  11. package/dist/commands/hydrogen/setup.js +0 -4
  12. package/dist/commands/hydrogen/setup.test.js +0 -1
  13. package/dist/commands/hydrogen/shortcut.js +1 -0
  14. package/dist/commands/hydrogen/upgrade.js +720 -0
  15. package/dist/commands/hydrogen/upgrade.test.js +786 -0
  16. package/dist/generator-templates/starter/.graphqlrc.yml +12 -1
  17. package/dist/generator-templates/starter/CHANGELOG.md +126 -0
  18. package/dist/generator-templates/starter/README.md +23 -0
  19. package/dist/generator-templates/starter/app/components/Cart.tsx +1 -1
  20. package/dist/generator-templates/starter/app/components/Footer.tsx +3 -1
  21. package/dist/generator-templates/starter/app/components/Header.tsx +5 -1
  22. package/dist/generator-templates/starter/app/components/Layout.tsx +14 -11
  23. package/dist/generator-templates/starter/app/components/Search.tsx +1 -1
  24. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerAddressMutations.ts +61 -0
  25. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +39 -0
  26. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrderQuery.ts +87 -0
  27. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +58 -0
  28. package/dist/generator-templates/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +24 -0
  29. package/dist/generator-templates/starter/app/lib/fragments.ts +102 -0
  30. package/dist/generator-templates/starter/app/lib/session.ts +67 -0
  31. package/dist/generator-templates/starter/app/root.tsx +11 -45
  32. package/dist/generator-templates/starter/app/routes/[robots.txt].tsx +0 -27
  33. package/dist/generator-templates/starter/app/routes/account.$.tsx +8 -4
  34. package/dist/generator-templates/starter/app/routes/account._index.tsx +5 -0
  35. package/dist/generator-templates/starter/app/routes/account.addresses.tsx +215 -206
  36. package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +56 -163
  37. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +32 -109
  38. package/dist/generator-templates/starter/app/routes/account.profile.tsx +40 -180
  39. package/dist/generator-templates/starter/app/routes/account.tsx +20 -135
  40. package/dist/generator-templates/starter/app/routes/account_.authorize.tsx +5 -0
  41. package/dist/generator-templates/starter/app/routes/account_.login.tsx +3 -140
  42. package/dist/generator-templates/starter/app/routes/account_.logout.tsx +5 -24
  43. package/dist/generator-templates/starter/app/routes/cart.tsx +7 -5
  44. package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +1 -1
  45. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +2 -2
  46. package/dist/generator-templates/starter/app/routes/search.tsx +1 -1
  47. package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +506 -0
  48. package/dist/generator-templates/starter/package.json +11 -10
  49. package/dist/generator-templates/starter/remix.config.js +4 -0
  50. package/dist/generator-templates/starter/remix.env.d.ts +6 -11
  51. package/dist/generator-templates/starter/server.ts +24 -167
  52. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +104 -881
  53. package/dist/hooks/init.js +4 -4
  54. package/dist/lib/auth.js +5 -10
  55. package/dist/lib/build.js +6 -1
  56. package/dist/lib/bundle/analyzer.js +36 -26
  57. package/dist/lib/check-lockfile.js +1 -0
  58. package/dist/lib/codegen.js +59 -18
  59. package/dist/lib/defer.js +12 -0
  60. package/dist/lib/file.js +52 -3
  61. package/dist/lib/flags.js +27 -9
  62. package/dist/lib/get-oxygen-deployment-data.test.js +4 -2
  63. package/dist/lib/graphql/admin/client.test.js +2 -2
  64. package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
  65. package/dist/lib/log.js +32 -14
  66. package/dist/lib/mini-oxygen/assets.js +118 -0
  67. package/dist/lib/mini-oxygen/common.js +2 -1
  68. package/dist/lib/mini-oxygen/index.js +7 -5
  69. package/dist/lib/mini-oxygen/mini-oxygen.test.js +214 -0
  70. package/dist/lib/mini-oxygen/node.js +19 -5
  71. package/dist/lib/mini-oxygen/workerd-inspector-logs.js +227 -0
  72. package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +200 -0
  73. package/dist/lib/mini-oxygen/workerd-inspector.js +62 -235
  74. package/dist/lib/mini-oxygen/workerd.js +74 -50
  75. package/dist/lib/missing-routes.js +6 -3
  76. package/dist/lib/onboarding/common.js +40 -9
  77. package/dist/lib/onboarding/local.js +19 -11
  78. package/dist/lib/onboarding/remote.js +48 -28
  79. package/dist/lib/render-errors.js +2 -0
  80. package/dist/lib/request-events.js +65 -31
  81. package/dist/lib/setups/css/assets.js +1 -46
  82. package/dist/lib/setups/css/css-modules.js +3 -2
  83. package/dist/lib/setups/css/postcss.js +4 -2
  84. package/dist/lib/setups/css/tailwind.js +4 -2
  85. package/dist/lib/setups/css/vanilla-extract.js +3 -2
  86. package/dist/lib/setups/i18n/replacers.test.js +56 -38
  87. package/dist/lib/shell.js +1 -1
  88. package/dist/lib/template-diff.js +89 -0
  89. package/dist/lib/template-downloader.js +3 -2
  90. package/dist/lib/transpile/project.js +1 -1
  91. package/dist/virtual-routes/assets/debug-network.css +592 -0
  92. package/dist/virtual-routes/assets/favicon-dark.svg +20 -0
  93. package/dist/virtual-routes/components/FlameChartWrapper.jsx +8 -10
  94. package/dist/virtual-routes/components/IconClose.jsx +38 -0
  95. package/dist/virtual-routes/components/IconDiscard.jsx +44 -0
  96. package/dist/virtual-routes/components/RequestDetails.jsx +179 -0
  97. package/dist/virtual-routes/components/RequestTable.jsx +92 -0
  98. package/dist/virtual-routes/components/RequestWaterfall.jsx +151 -0
  99. package/dist/virtual-routes/lib/useDebugNetworkServer.jsx +176 -0
  100. package/dist/virtual-routes/routes/subrequest-profiler.jsx +243 -0
  101. package/oclif.manifest.json +134 -59
  102. package/package.json +18 -26
  103. package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +0 -161
  104. package/dist/generator-templates/starter/app/routes/account_.recover.tsx +0 -129
  105. package/dist/generator-templates/starter/app/routes/account_.register.tsx +0 -207
  106. package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +0 -136
  107. package/dist/virtual-routes/routes/debug-network.jsx +0 -289
  108. /package/dist/generator-templates/starter/app/{utils.ts → lib/variants.ts} +0 -0
@@ -0,0 +1,179 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef } from "react";
3
+ import { Link } from "@remix-run/react";
4
+ import { IconClose } from "./IconClose.jsx";
5
+ import _useResizeObserver from "use-resize-observer";
6
+ const useResizeObserver = _useResizeObserver;
7
+ const TABS = {
8
+ 1: "General",
9
+ 2: "Headers",
10
+ 3: "Cache",
11
+ 4: "Data"
12
+ };
13
+ function RequestDetails({
14
+ serverEvents,
15
+ activeEventId,
16
+ setActiveEventId
17
+ }) {
18
+ const [activeTab, setActiveTab] = useState(1);
19
+ if (!activeEventId) {
20
+ return null;
21
+ }
22
+ const requestInfo = serverEvents.allRequests[activeEventId];
23
+ if (!requestInfo) {
24
+ return null;
25
+ }
26
+ function activeTabClass(tab) {
27
+ return activeTab === tab ? " active" : "";
28
+ }
29
+ function TabButton(key) {
30
+ return /* @__PURE__ */ jsx(
31
+ "div",
32
+ {
33
+ tabIndex: 0,
34
+ className: `tab${activeTabClass(key)}`,
35
+ onClick: () => setActiveTab(key),
36
+ onKeyUp: (event) => {
37
+ if (event.code === "Space")
38
+ setActiveTab(key);
39
+ },
40
+ children: TABS[key]
41
+ }
42
+ );
43
+ }
44
+ return /* @__PURE__ */ jsxs("div", { id: "request-detail", children: [
45
+ /* @__PURE__ */ jsxs("div", { id: "request-detail-header", children: [
46
+ /* @__PURE__ */ jsxs(TabButtonsBar, { children: [
47
+ TabButton(1),
48
+ !!requestInfo.responseInit?.headers && TabButton(2),
49
+ !!requestInfo.cache && TabButton(3),
50
+ !!requestInfo.responsePayload && TabButton(4)
51
+ ] }),
52
+ /* @__PURE__ */ jsx("div", { id: "close-request-detail", children: /* @__PURE__ */ jsx(
53
+ "button",
54
+ {
55
+ className: "plain icon",
56
+ onClick: () => {
57
+ setActiveEventId(void 0);
58
+ },
59
+ children: /* @__PURE__ */ jsx(IconClose, {})
60
+ }
61
+ ) })
62
+ ] }),
63
+ /* @__PURE__ */ jsxs("div", { className: "tabPanels pad", children: [
64
+ /* @__PURE__ */ jsx("div", { id: "tab1-panel", className: `tabPanel${activeTabClass(1)}`, children: /* @__PURE__ */ jsxs("div", { className: "grid-layout", children: [
65
+ /* @__PURE__ */ jsx(DetailsRow, { rowName: "Name", value: requestInfo.displayName }),
66
+ /* @__PURE__ */ jsx(DetailsRow, { rowName: "Request URL", value: requestInfo.url }),
67
+ /* @__PURE__ */ jsx(
68
+ DetailsRow,
69
+ {
70
+ rowName: "Status",
71
+ value: `${requestInfo.responseInit?.status} ${requestInfo.responseInit?.statusText}`
72
+ }
73
+ ),
74
+ /* @__PURE__ */ jsx(
75
+ DetailsRow,
76
+ {
77
+ rowName: "GraphiQL",
78
+ value: requestInfo.graphiqlLink,
79
+ type: "url"
80
+ }
81
+ ),
82
+ /* @__PURE__ */ jsx(
83
+ DetailsRow,
84
+ {
85
+ rowName: "Location",
86
+ text: requestInfo.stackLine,
87
+ value: requestInfo.stackLink,
88
+ type: "url"
89
+ }
90
+ )
91
+ ] }) }),
92
+ !!requestInfo.responseInit?.headers && /* @__PURE__ */ jsx("div", { id: "tab2-panel", className: `tabPanel${activeTabClass(2)}`, children: /* @__PURE__ */ jsx("div", { className: "grid-layout", children: Object.entries(requestInfo.responseInit?.headers).map(
93
+ ([key, value]) => /* @__PURE__ */ jsx(DetailsRow, { rowName: value[0], value: value[1] }, key)
94
+ ) }) }),
95
+ !!requestInfo.cache && /* @__PURE__ */ jsx("div", { id: "tab3-panel", className: `tabPanel${activeTabClass(3)}`, children: /* @__PURE__ */ jsxs("div", { className: "grid-layout", children: [
96
+ /* @__PURE__ */ jsx(DetailsRow, { rowName: "Status", value: requestInfo.cache?.status }),
97
+ /* @__PURE__ */ jsx(
98
+ DetailsRow,
99
+ {
100
+ rowName: "Cache-Control",
101
+ value: requestInfo.cache?.strategy
102
+ }
103
+ ),
104
+ /* @__PURE__ */ jsx(
105
+ DetailsRow,
106
+ {
107
+ rowName: "Cache Key",
108
+ value: requestInfo.cache?.key?.toString()
109
+ }
110
+ )
111
+ ] }) }),
112
+ !!requestInfo.responsePayload && /* @__PURE__ */ jsx("div", { id: "tab4-panel", className: `tabPanel${activeTabClass(4)}`, children: /* @__PURE__ */ jsx("pre", { className: "code-json", children: JSON.stringify(requestInfo.responsePayload, void 0, 2) }) })
113
+ ] })
114
+ ] });
115
+ }
116
+ function TabButtonsBar({ children }) {
117
+ const [fadeClass, setFadeClass] = useState("");
118
+ const scrollBarRef = useRef(null);
119
+ useResizeObserver({
120
+ ref: scrollBarRef,
121
+ onResize: () => {
122
+ if (scrollBarRef.current) {
123
+ setFade(scrollBarRef.current);
124
+ }
125
+ }
126
+ });
127
+ function setFade(target) {
128
+ if (target.scrollWidth === target.clientWidth) {
129
+ setFadeClass("");
130
+ return;
131
+ }
132
+ const scrollRange = target.scrollWidth - target.clientWidth;
133
+ if (target.scrollLeft > 10 && target.scrollLeft < scrollRange - 10) {
134
+ setFadeClass("fadeLeftRight");
135
+ } else if (target.scrollLeft <= 10) {
136
+ setFadeClass("fadeRight");
137
+ } else if (target.scrollLeft > scrollRange - 10) {
138
+ setFadeClass("fadeLeft");
139
+ }
140
+ }
141
+ return /* @__PURE__ */ jsxs(
142
+ "div",
143
+ {
144
+ id: "tab-buttons-wrapper",
145
+ onResize: (event) => setFade(event.currentTarget),
146
+ children: [
147
+ /* @__PURE__ */ jsx(
148
+ "div",
149
+ {
150
+ id: "tabButtons",
151
+ ref: scrollBarRef,
152
+ className: "flex-row gap-tiny",
153
+ onScroll: (event) => setFade(event.currentTarget),
154
+ children
155
+ }
156
+ ),
157
+ /* @__PURE__ */ jsx("div", { className: `fadCover ${fadeClass}` })
158
+ ]
159
+ }
160
+ );
161
+ }
162
+ function DetailsRow({
163
+ rowName,
164
+ value,
165
+ text,
166
+ type = "string"
167
+ }) {
168
+ if (!rowName || !value) {
169
+ return null;
170
+ }
171
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
172
+ /* @__PURE__ */ jsx("div", { className: "gridTitle", children: rowName }),
173
+ type === "url" && /* @__PURE__ */ jsx(Link, { target: "_blank", to: value, children: text ?? value }),
174
+ type === "string" && /* @__PURE__ */ jsx("div", { className: "word-break-all", children: text ?? value })
175
+ ] });
176
+ }
177
+ export {
178
+ RequestDetails
179
+ };
@@ -0,0 +1,92 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect } from "react";
3
+ import {
4
+ buildRequestData
5
+ } from "../lib/useDebugNetworkServer.jsx";
6
+ function RequestTable({
7
+ serverEvents,
8
+ activeEventId,
9
+ setActiveEventId
10
+ }) {
11
+ let totalMainRequests = 0;
12
+ let totalSubRequest = 0;
13
+ const items = buildRequestData({
14
+ serverEvents,
15
+ buildMainRequest: (mainRequest, timing) => {
16
+ totalMainRequests++;
17
+ return {
18
+ id: mainRequest.id,
19
+ requestId: mainRequest.requestId,
20
+ url: mainRequest.url,
21
+ status: mainRequest.responseInit?.status ?? 0,
22
+ cacheStatus: mainRequest.cacheStatus,
23
+ duration: timing.responseEnd - timing.requestStart
24
+ };
25
+ },
26
+ buildSubRequest: (subRequest, timing) => {
27
+ if (serverEvents.hidePutRequests) {
28
+ subRequest.cacheStatus !== "PUT" && totalSubRequest++;
29
+ } else {
30
+ totalSubRequest++;
31
+ }
32
+ return {
33
+ id: subRequest.id,
34
+ requestId: subRequest.requestId,
35
+ url: subRequest.displayName ?? subRequest.url,
36
+ status: subRequest.responseInit?.status ?? 0,
37
+ cacheStatus: subRequest.cacheStatus,
38
+ duration: timing.requestEnd - timing.requestStart
39
+ };
40
+ }
41
+ });
42
+ useEffect(() => {
43
+ if (!serverEvents.preserveLog && activeEventId) {
44
+ const selectedItem = items.find((item) => item.id === activeEventId);
45
+ if (!selectedItem) {
46
+ setActiveEventId(void 0);
47
+ }
48
+ }
49
+ }, [serverEvents.preserveLog]);
50
+ return /* @__PURE__ */ jsx("div", { id: "request-table", children: /* @__PURE__ */ jsxs("div", { children: [
51
+ /* @__PURE__ */ jsxs("div", { id: "request-table__header", className: "grid-row", children: [
52
+ /* @__PURE__ */ jsx("div", { className: "grid-cell", children: "Name" }),
53
+ /* @__PURE__ */ jsx("div", { className: "grid-cell", children: "Cache" }),
54
+ /* @__PURE__ */ jsx("div", { className: "grid-cell", children: "Time" })
55
+ ] }),
56
+ /* @__PURE__ */ jsx("div", { id: "request-table__content", children: items.map((row) => /* @__PURE__ */ jsxs(
57
+ "div",
58
+ {
59
+ id: `request-table__row-${row.id}`,
60
+ tabIndex: 0,
61
+ className: `grid-row${activeEventId === row.id ? " active" : ""}${row.status >= 400 ? " error" : ""}`,
62
+ onClick: () => setActiveEventId(row.id),
63
+ onKeyUp: (event) => {
64
+ if (event.code === "Space")
65
+ setActiveEventId(row.id);
66
+ },
67
+ children: [
68
+ /* @__PURE__ */ jsx("div", { className: "grid-cell", children: row.url }),
69
+ /* @__PURE__ */ jsx("div", { className: "grid-cell", children: row.cacheStatus }),
70
+ /* @__PURE__ */ jsxs("div", { className: "grid-cell", children: [
71
+ row.duration,
72
+ "ms"
73
+ ] })
74
+ ]
75
+ },
76
+ row.id
77
+ )) }),
78
+ /* @__PURE__ */ jsxs("div", { id: "request-table__footer", children: [
79
+ totalMainRequests,
80
+ " request",
81
+ totalMainRequests > 1 ? "s" : "",
82
+ " |",
83
+ " ",
84
+ totalSubRequest,
85
+ " sub request",
86
+ totalSubRequest > 1 ? "s" : ""
87
+ ] })
88
+ ] }) });
89
+ }
90
+ export {
91
+ RequestTable
92
+ };
@@ -0,0 +1,151 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { FlameChartWrapper } from "./FlameChartWrapper.jsx";
4
+ import {
5
+ buildRequestData
6
+ } from "../lib/useDebugNetworkServer.jsx";
7
+ const STYLE_FONT = "10px Inter, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, sans-serif";
8
+ let resizeTimeout;
9
+ function RequestWaterfall({
10
+ serverEvents,
11
+ config
12
+ }) {
13
+ const items = buildRequestData({
14
+ serverEvents,
15
+ buildMainRequest: (mainRequest, timing) => {
16
+ return {
17
+ name: mainRequest.url,
18
+ intervals: "mainRequest",
19
+ timing,
20
+ meta: [
21
+ {
22
+ name: "id",
23
+ value: mainRequest.id,
24
+ color: "black"
25
+ }
26
+ ]
27
+ };
28
+ },
29
+ buildSubRequest: (subRequest, timing) => {
30
+ return {
31
+ name: `${subRequest.cacheStatus} ${subRequest.displayName ?? subRequest.url}`.trim(),
32
+ intervals: "request",
33
+ timing,
34
+ meta: [
35
+ {
36
+ name: "id",
37
+ value: subRequest.id,
38
+ color: "black"
39
+ }
40
+ ]
41
+ };
42
+ }
43
+ });
44
+ const data = {
45
+ items: [
46
+ {
47
+ // Workaround a bug in flame-chart-js where the first item onSelect is not triggered
48
+ name: "padding-request",
49
+ intervals: "request",
50
+ timing: {
51
+ requestStart: 0,
52
+ responseStart: 0,
53
+ responseEnd: 0,
54
+ requestEnd: -1
55
+ }
56
+ },
57
+ ...items
58
+ ],
59
+ intervals: {
60
+ mainRequest: [
61
+ {
62
+ name: "server",
63
+ color: config.colors.server,
64
+ type: "block",
65
+ start: "requestStart",
66
+ end: "responseStart"
67
+ },
68
+ {
69
+ name: "streaming",
70
+ color: config.colors.streaming,
71
+ type: "block",
72
+ start: "responseStart",
73
+ end: "responseEnd"
74
+ }
75
+ ],
76
+ request: [
77
+ {
78
+ name: "request",
79
+ color: config.colors.subRequest,
80
+ type: "block",
81
+ start: "requestStart",
82
+ end: "requestEnd"
83
+ }
84
+ ]
85
+ }
86
+ };
87
+ const onSelect = (data2) => {
88
+ const eventIdMeta = data2?.node?.meta?.filter(
89
+ (meta) => meta.name === "id"
90
+ )?.[0];
91
+ if (eventIdMeta) {
92
+ setTimeout(() => {
93
+ window.setActiveEventId && window.setActiveEventId(eventIdMeta.value);
94
+ document.querySelector(`#request-table__row-${eventIdMeta.value}`)?.scrollIntoView();
95
+ }, 0);
96
+ }
97
+ };
98
+ const settings = useMemo(
99
+ () => ({
100
+ options: {
101
+ tooltip: () => {
102
+ }
103
+ },
104
+ styles: {
105
+ main: {
106
+ blockHeight: 22,
107
+ font: STYLE_FONT,
108
+ tooltipShadowBlur: 1
109
+ },
110
+ timeframeSelectorPlugin: {
111
+ font: STYLE_FONT,
112
+ waterfallStrokeOpacity: 1,
113
+ waterfallFillOpacity: 0.1
114
+ },
115
+ timeGridPlugin: {
116
+ font: STYLE_FONT
117
+ },
118
+ waterfallPlugin: {
119
+ defaultHeight: 500
120
+ }
121
+ }
122
+ }),
123
+ []
124
+ );
125
+ return /* @__PURE__ */ jsx(
126
+ FlameChartWrapper,
127
+ {
128
+ waterfall: data,
129
+ onSelect,
130
+ settings,
131
+ onResize: (flameChart, width, height) => {
132
+ flameChart?.setSettings({
133
+ ...settings,
134
+ styles: {
135
+ ...settings.styles,
136
+ waterfallPlugin: {
137
+ defaultHeight: height
138
+ }
139
+ }
140
+ });
141
+ clearTimeout(resizeTimeout);
142
+ resizeTimeout = setTimeout(() => {
143
+ flameChart?.resize(width, height);
144
+ }, 50);
145
+ }
146
+ }
147
+ );
148
+ }
149
+ export {
150
+ RequestWaterfall
151
+ };
@@ -0,0 +1,176 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ let nextEventId = 0;
3
+ const LOCAL_STORAGE_SETTINGS_KEY = "h2-debug-network-settings";
4
+ function getSettings() {
5
+ try {
6
+ return JSON.parse(localStorage.getItem(LOCAL_STORAGE_SETTINGS_KEY) ?? "{}");
7
+ } catch {
8
+ return {};
9
+ }
10
+ }
11
+ function setSettings(settings) {
12
+ localStorage.setItem(
13
+ LOCAL_STORAGE_SETTINGS_KEY,
14
+ JSON.stringify({ ...getSettings(), ...settings })
15
+ );
16
+ }
17
+ function useDebugNetworkServer() {
18
+ const serverEvents = useRef({
19
+ mainRequests: [],
20
+ subRequests: {},
21
+ allRequests: {},
22
+ hidePutRequests: true,
23
+ preserveLog: false,
24
+ activeEventId: void 0,
25
+ hideNotification: void 0
26
+ });
27
+ const [timestamp, setTimestamp] = useState();
28
+ function triggerRender() {
29
+ setTimestamp((/* @__PURE__ */ new Date()).getTime());
30
+ }
31
+ useEffect(() => {
32
+ try {
33
+ const debugNetworkSettings = getSettings();
34
+ serverEvents.current.hidePutRequests = debugNetworkSettings.hidePutRequests ?? true;
35
+ serverEvents.current.preserveLog = debugNetworkSettings.preserveLog ?? false;
36
+ serverEvents.current.hideNotification = debugNetworkSettings.hideNotification ?? void 0;
37
+ triggerRender();
38
+ } catch {
39
+ }
40
+ }, []);
41
+ function clearServerEvents() {
42
+ fetch("/debug-network-server", { method: "DELETE" }).catch(
43
+ (error) => console.error("Could not clear history:", error)
44
+ );
45
+ serverEvents.current = {
46
+ ...serverEvents.current,
47
+ mainRequests: [],
48
+ subRequests: {},
49
+ allRequests: {},
50
+ activeEventId: void 0
51
+ };
52
+ }
53
+ function serverEventHandler(onEvent) {
54
+ return (event) => {
55
+ const data = JSON.parse(event.data);
56
+ const id = `event-${nextEventId++}`;
57
+ onEvent({
58
+ ...data,
59
+ id
60
+ });
61
+ setTimeout(triggerRender, 0);
62
+ };
63
+ }
64
+ useEffect(() => {
65
+ const evtSource = new EventSource("/debug-network-server", {
66
+ withCredentials: true
67
+ });
68
+ const mainRequestHandler = serverEventHandler((data) => {
69
+ const cleanData = {
70
+ ...data,
71
+ url: data.url.replace(location.origin, "")
72
+ };
73
+ if (serverEvents.current.preserveLog) {
74
+ serverEvents.current.mainRequests = [
75
+ ...serverEvents.current.mainRequests,
76
+ cleanData
77
+ ];
78
+ } else {
79
+ serverEvents.current.mainRequests = [cleanData];
80
+ }
81
+ serverEvents.current.allRequests[cleanData.id] = cleanData;
82
+ });
83
+ evtSource.addEventListener("Request", mainRequestHandler);
84
+ const subRequestHandler = serverEventHandler((data) => {
85
+ let groupEvents = serverEvents.current.subRequests[data.requestId] || [];
86
+ groupEvents = [...groupEvents, data];
87
+ serverEvents.current.subRequests = {
88
+ ...serverEvents.current.subRequests,
89
+ [data.requestId]: groupEvents
90
+ };
91
+ serverEvents.current.allRequests[data.id] = data;
92
+ });
93
+ evtSource.addEventListener("Sub request", subRequestHandler);
94
+ return () => {
95
+ evtSource.removeEventListener("Request", mainRequestHandler);
96
+ evtSource.removeEventListener("Sub request", subRequestHandler);
97
+ evtSource.close();
98
+ };
99
+ }, []);
100
+ function clear() {
101
+ clearServerEvents();
102
+ triggerRender();
103
+ }
104
+ function setHidePutRequests(hidePutRequests) {
105
+ serverEvents.current.hidePutRequests = hidePutRequests;
106
+ setSettings({ hidePutRequests });
107
+ triggerRender();
108
+ }
109
+ function setPreserveLog(preserveLog) {
110
+ serverEvents.current.preserveLog = preserveLog;
111
+ setSettings({ preserveLog });
112
+ triggerRender();
113
+ }
114
+ function setActiveEventId(eventId) {
115
+ serverEvents.current.activeEventId = eventId;
116
+ }
117
+ function setHideNotification(hideNotification) {
118
+ serverEvents.current.hideNotification = hideNotification;
119
+ setSettings({ hideNotification });
120
+ triggerRender();
121
+ }
122
+ return {
123
+ serverEvents: serverEvents.current,
124
+ clear,
125
+ setHidePutRequests,
126
+ setPreserveLog,
127
+ setActiveEventId,
128
+ setHideNotification,
129
+ timestamp
130
+ };
131
+ }
132
+ function buildRequestData({
133
+ serverEvents,
134
+ buildMainRequest,
135
+ buildSubRequest
136
+ }) {
137
+ const calcDuration = (time) => time - (serverEvents.mainRequests[0]?.startTime ?? 0);
138
+ let items = [];
139
+ serverEvents.mainRequests.forEach((mainRequest) => {
140
+ const mainResponseStart = calcDuration(mainRequest.endTime);
141
+ let mainResponseEnd = mainResponseStart;
142
+ const subRequestItems = [];
143
+ const subRequests = serverEvents.subRequests[mainRequest.requestId] || [];
144
+ subRequests.forEach((subRequest) => {
145
+ const subRequestEnd = calcDuration(subRequest.endTime);
146
+ if (subRequest.cacheStatus !== "PUT") {
147
+ mainResponseEnd = Math.max(mainResponseEnd, subRequestEnd);
148
+ }
149
+ const subRequestItem = buildSubRequest(subRequest, {
150
+ requestStart: calcDuration(subRequest.startTime),
151
+ requestEnd: subRequestEnd,
152
+ responseStart: -1,
153
+ responseEnd: -1
154
+ });
155
+ if (serverEvents.hidePutRequests) {
156
+ subRequest.cacheStatus !== "PUT" && subRequestItems.push(subRequestItem);
157
+ } else {
158
+ subRequestItems.push(subRequestItem);
159
+ }
160
+ });
161
+ items.push(
162
+ buildMainRequest(mainRequest, {
163
+ requestStart: calcDuration(mainRequest.startTime),
164
+ responseStart: mainResponseStart,
165
+ responseEnd: mainResponseEnd,
166
+ requestEnd: -1
167
+ })
168
+ );
169
+ items = items.concat(subRequestItems);
170
+ });
171
+ return items;
172
+ }
173
+ export {
174
+ buildRequestData,
175
+ useDebugNetworkServer
176
+ };