skybridge 0.35.20 → 0.36.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 (134) hide show
  1. package/README.md +8 -8
  2. package/dist/cli/header.js +1 -1
  3. package/dist/cli/header.js.map +1 -1
  4. package/dist/cli/use-nodemon.js +2 -2
  5. package/dist/cli/use-nodemon.js.map +1 -1
  6. package/dist/cli/use-tunnel.d.ts +12 -5
  7. package/dist/cli/use-tunnel.js +34 -29
  8. package/dist/cli/use-tunnel.js.map +1 -1
  9. package/dist/cli/use-typescript-check.d.ts +1 -0
  10. package/dist/cli/use-typescript-check.js +41 -6
  11. package/dist/cli/use-typescript-check.js.map +1 -1
  12. package/dist/commands/build.js +28 -7
  13. package/dist/commands/build.js.map +1 -1
  14. package/dist/commands/dev.d.ts +1 -0
  15. package/dist/commands/dev.js +7 -2
  16. package/dist/commands/dev.js.map +1 -1
  17. package/dist/commands/start.js +7 -10
  18. package/dist/commands/start.js.map +1 -1
  19. package/dist/server/asset-base-url-transform-plugin.js +1 -1
  20. package/dist/server/asset-base-url-transform-plugin.js.map +1 -1
  21. package/dist/server/asset-base-url-transform-plugin.test.js +29 -0
  22. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -1
  23. package/dist/server/content-helpers.d.ts +27 -0
  24. package/dist/server/content-helpers.js +46 -0
  25. package/dist/server/content-helpers.js.map +1 -0
  26. package/dist/server/content-helpers.test.js +70 -0
  27. package/dist/server/content-helpers.test.js.map +1 -0
  28. package/dist/server/express.js +3 -3
  29. package/dist/server/express.js.map +1 -1
  30. package/dist/server/express.test.js +39 -2
  31. package/dist/server/express.test.js.map +1 -1
  32. package/dist/server/index.d.ts +4 -3
  33. package/dist/server/index.js +3 -2
  34. package/dist/server/index.js.map +1 -1
  35. package/dist/server/inferUtilityTypes.d.ts +6 -6
  36. package/dist/server/middleware.test.js +12 -9
  37. package/dist/server/middleware.test.js.map +1 -1
  38. package/dist/server/server.d.ts +95 -72
  39. package/dist/server/server.js +208 -74
  40. package/dist/server/server.js.map +1 -1
  41. package/dist/server/templateHelper.d.ts +5 -5
  42. package/dist/server/templates/development.hbs +2 -2
  43. package/dist/server/templates/production.hbs +1 -1
  44. package/dist/server/viewsDevServer.d.ts +14 -0
  45. package/dist/server/viewsDevServer.js +45 -0
  46. package/dist/server/viewsDevServer.js.map +1 -0
  47. package/dist/test/utils.d.ts +8 -20
  48. package/dist/test/utils.js +39 -35
  49. package/dist/test/utils.js.map +1 -1
  50. package/dist/test/view.test.js +523 -0
  51. package/dist/test/view.test.js.map +1 -0
  52. package/dist/web/bridges/apps-sdk/adaptor.d.ts +2 -2
  53. package/dist/web/bridges/apps-sdk/adaptor.js +8 -2
  54. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -1
  55. package/dist/web/bridges/mcp-app/adaptor.d.ts +6 -6
  56. package/dist/web/bridges/mcp-app/adaptor.js +24 -24
  57. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -1
  58. package/dist/web/bridges/types.d.ts +7 -7
  59. package/dist/web/components/modal-provider.js +1 -1
  60. package/dist/web/components/modal-provider.js.map +1 -1
  61. package/dist/web/create-store.js +9 -9
  62. package/dist/web/create-store.js.map +1 -1
  63. package/dist/web/create-store.test.js +14 -16
  64. package/dist/web/create-store.test.js.map +1 -1
  65. package/dist/web/data-llm.d.ts +1 -1
  66. package/dist/web/data-llm.js +3 -3
  67. package/dist/web/data-llm.js.map +1 -1
  68. package/dist/web/data-llm.test.js +22 -22
  69. package/dist/web/data-llm.test.js.map +1 -1
  70. package/dist/web/generate-helpers.d.ts +20 -18
  71. package/dist/web/generate-helpers.js +20 -18
  72. package/dist/web/generate-helpers.js.map +1 -1
  73. package/dist/web/generate-helpers.test-d.js +26 -26
  74. package/dist/web/generate-helpers.test-d.js.map +1 -1
  75. package/dist/web/helpers/state.d.ts +2 -2
  76. package/dist/web/helpers/state.js +11 -11
  77. package/dist/web/helpers/state.js.map +1 -1
  78. package/dist/web/helpers/state.test.js +9 -9
  79. package/dist/web/helpers/state.test.js.map +1 -1
  80. package/dist/web/hooks/index.d.ts +1 -1
  81. package/dist/web/hooks/index.js +1 -1
  82. package/dist/web/hooks/index.js.map +1 -1
  83. package/dist/web/hooks/use-request-modal.d.ts +1 -1
  84. package/dist/web/hooks/use-request-modal.js +4 -4
  85. package/dist/web/hooks/use-request-modal.js.map +1 -1
  86. package/dist/web/hooks/use-request-modal.test.js +1 -1
  87. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  88. package/dist/web/hooks/use-view-state.d.ts +4 -0
  89. package/dist/web/hooks/use-view-state.js +32 -0
  90. package/dist/web/hooks/use-view-state.js.map +1 -0
  91. package/dist/web/hooks/{use-widget-state.test.js → use-view-state.test.js} +17 -17
  92. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  93. package/dist/web/index.d.ts +1 -2
  94. package/dist/web/index.js +1 -2
  95. package/dist/web/index.js.map +1 -1
  96. package/dist/web/mount-view.d.ts +1 -0
  97. package/dist/web/{mount-widget.js → mount-view.js} +2 -2
  98. package/dist/web/mount-view.js.map +1 -0
  99. package/dist/web/plugin/plugin.d.ts +4 -1
  100. package/dist/web/plugin/plugin.js +134 -25
  101. package/dist/web/plugin/plugin.js.map +1 -1
  102. package/dist/web/plugin/scan-views.d.ts +16 -0
  103. package/dist/web/plugin/scan-views.js +88 -0
  104. package/dist/web/plugin/scan-views.js.map +1 -0
  105. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  106. package/dist/web/plugin/scan-views.test.js +99 -0
  107. package/dist/web/plugin/scan-views.test.js.map +1 -0
  108. package/dist/web/plugin/validate-view.d.ts +1 -0
  109. package/dist/web/plugin/validate-view.js +9 -0
  110. package/dist/web/plugin/validate-view.js.map +1 -0
  111. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  112. package/dist/web/plugin/validate-view.test.js +24 -0
  113. package/dist/web/plugin/validate-view.test.js.map +1 -0
  114. package/package.json +8 -1
  115. package/tsconfig.base.json +2 -0
  116. package/dist/server/widgetsDevServer.d.ts +0 -13
  117. package/dist/server/widgetsDevServer.js +0 -52
  118. package/dist/server/widgetsDevServer.js.map +0 -1
  119. package/dist/test/widget.test.js +0 -334
  120. package/dist/test/widget.test.js.map +0 -1
  121. package/dist/web/hooks/use-widget-state.d.ts +0 -4
  122. package/dist/web/hooks/use-widget-state.js +0 -32
  123. package/dist/web/hooks/use-widget-state.js.map +0 -1
  124. package/dist/web/hooks/use-widget-state.test.js.map +0 -1
  125. package/dist/web/mount-widget.d.ts +0 -1
  126. package/dist/web/mount-widget.js.map +0 -1
  127. package/dist/web/plugin/validate-widget.d.ts +0 -5
  128. package/dist/web/plugin/validate-widget.js +0 -27
  129. package/dist/web/plugin/validate-widget.js.map +0 -1
  130. package/dist/web/plugin/validate-widget.test.js +0 -42
  131. package/dist/web/plugin/validate-widget.test.js.map +0 -1
  132. /package/dist/{test/widget.test.d.ts → server/content-helpers.test.d.ts} +0 -0
  133. /package/dist/{web/hooks/use-widget-state.test.d.ts → test/view.test.d.ts} +0 -0
  134. /package/dist/web/{plugin/validate-widget.test.d.ts → hooks/use-view-state.test.d.ts} +0 -0
@@ -0,0 +1,32 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { getAdaptor, useHostContext } from "../bridges/index.js";
3
+ import { filterViewContext, injectViewContext } from "../helpers/state.js";
4
+ export function useViewState(defaultState) {
5
+ const adaptor = getAdaptor();
6
+ const viewStateFromBridge = useHostContext("viewState");
7
+ const [viewState, _setViewState] = useState(() => {
8
+ if (viewStateFromBridge !== null) {
9
+ return filterViewContext(viewStateFromBridge);
10
+ }
11
+ return typeof defaultState === "function"
12
+ ? defaultState()
13
+ : (defaultState ?? null);
14
+ });
15
+ useEffect(() => {
16
+ if (viewStateFromBridge !== null) {
17
+ _setViewState(filterViewContext(viewStateFromBridge));
18
+ }
19
+ }, [viewStateFromBridge]);
20
+ const setViewState = useCallback((state) => {
21
+ _setViewState((prevState) => {
22
+ const newState = typeof state === "function" ? state(prevState) : state;
23
+ const stateToSet = injectViewContext(newState);
24
+ if (stateToSet !== null) {
25
+ adaptor.setViewState(stateToSet);
26
+ }
27
+ return filterViewContext(stateToSet);
28
+ });
29
+ }, [adaptor]);
30
+ return [viewState, setViewState];
31
+ }
32
+ //# sourceMappingURL=use-view-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-view-state.js","sourceRoot":"","sources":["../../../src/web/hooks/use-view-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAS3E,MAAM,UAAU,YAAY,CAC1B,YAA0C;IAE1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,mBAAmB,GAAG,cAAc,CAAC,WAAW,CAAa,CAAC;IAEpE,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAW,GAAG,EAAE;QACzD,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;YACjC,OAAO,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,OAAO,YAAY,KAAK,UAAU;YACvC,CAAC,CAAC,YAAY,EAAE;YAChB,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;YACjC,aAAa,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE1B,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,KAA+B,EAAE,EAAE;QAClC,aAAa,CAAC,CAAC,SAAS,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACxE,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAE/C,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACnC,CAAC;YAED,OAAO,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,CAAC,SAAS,EAAE,YAAY,CAAU,CAAC;AAC5C,CAAC"}
@@ -2,8 +2,8 @@ import { act, renderHook, waitFor } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi, } from "vitest";
3
3
  import { McpAppAdaptor, McpAppBridge } from "../bridges/mcp-app/index.js";
4
4
  import { fireToolResultNotification, getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
5
- import { useWidgetState } from "./use-widget-state.js";
6
- describe("useWidgetState", () => {
5
+ import { useViewState } from "./use-view-state.js";
6
+ describe("useViewState", () => {
7
7
  let OpenaiMock;
8
8
  beforeEach(() => {
9
9
  OpenaiMock = {
@@ -21,16 +21,16 @@ describe("useWidgetState", () => {
21
21
  const windowState = { count: 5, name: "window" };
22
22
  it("should initialize with default state when window.openai.widgetState is null", () => {
23
23
  OpenaiMock.widgetState = null;
24
- const { result } = renderHook(() => useWidgetState(defaultState));
24
+ const { result } = renderHook(() => useViewState(defaultState));
25
25
  expect(result.current[0]).toEqual(defaultState);
26
26
  });
27
27
  it("should initialize with window.openai.widgetState when available", () => {
28
28
  OpenaiMock.widgetState = { modelContent: windowState };
29
- const { result } = renderHook(() => useWidgetState(defaultState));
29
+ const { result } = renderHook(() => useViewState(defaultState));
30
30
  expect(result.current[0]).toEqual(windowState);
31
31
  });
32
- it("should call window.openai.setWidgetState when setWidgetState is called with a new state", async () => {
33
- const { result } = renderHook(() => useWidgetState(defaultState));
32
+ it("should call window.openai.setWidgetState when setViewState is called with a new state", async () => {
33
+ const { result } = renderHook(() => useViewState(defaultState));
34
34
  const newState = { count: 10, name: "updated" };
35
35
  act(() => {
36
36
  result.current[1](newState);
@@ -41,8 +41,8 @@ describe("useWidgetState", () => {
41
41
  });
42
42
  expect(result.current[0]).toEqual(newState);
43
43
  });
44
- it("should call window.openai.setWidgetState when setWidgetState is called with a function updater", async () => {
45
- const { result } = renderHook(() => useWidgetState(defaultState));
44
+ it("should call window.openai.setWidgetState when setViewState is called with a function updater", async () => {
45
+ const { result } = renderHook(() => useViewState(defaultState));
46
46
  act(() => {
47
47
  result.current[1]((prev) => ({ ...prev, count: prev.count + 1 }));
48
48
  });
@@ -54,7 +54,7 @@ describe("useWidgetState", () => {
54
54
  });
55
55
  it("should update state when window.openai.widgetState changes", () => {
56
56
  OpenaiMock.widgetState = { modelContent: defaultState };
57
- const { result, rerender } = renderHook(() => useWidgetState(defaultState));
57
+ const { result, rerender } = renderHook(() => useViewState(defaultState));
58
58
  expect(result.current[0]).toEqual(defaultState);
59
59
  // Simulate window.openai.widgetState changing
60
60
  OpenaiMock.widgetState = { modelContent: windowState };
@@ -63,7 +63,7 @@ describe("useWidgetState", () => {
63
63
  expect(result.current[0]).toEqual(windowState);
64
64
  });
65
65
  });
66
- describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
66
+ describe("useViewState (mcp-app host — localStorage persistence)", () => {
67
67
  beforeEach(() => {
68
68
  vi.stubGlobal("parent", { postMessage: getMcpAppHostPostMessageMock() });
69
69
  vi.stubGlobal("skybridge", { hostType: "mcp-app" });
@@ -79,7 +79,7 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
79
79
  });
80
80
  it("should persist state to localStorage when viewUUID is available", async () => {
81
81
  const viewUUID = "test-uuid-123";
82
- const { result } = renderHook(() => useWidgetState({ page: 1, zoom: 100 }));
82
+ const { result } = renderHook(() => useViewState({ page: 1, zoom: 100 }));
83
83
  await act(async () => {
84
84
  fireToolResultNotification({
85
85
  content: [{ type: "text", text: "result" }],
@@ -97,7 +97,7 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
97
97
  const viewUUID = "test-uuid-456";
98
98
  // Pre-seed with the sb:{timestamp}:{viewUUID} format
99
99
  localStorage.setItem(`sb:1700000000000:${viewUUID}`, JSON.stringify({ page: 5, zoom: 200 }));
100
- const { result } = renderHook(() => useWidgetState({ page: 1, zoom: 100 }));
100
+ const { result } = renderHook(() => useViewState({ page: 1, zoom: 100 }));
101
101
  act(() => {
102
102
  fireToolResultNotification({
103
103
  content: [{ type: "text", text: "result" }],
@@ -110,7 +110,7 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
110
110
  });
111
111
  });
112
112
  it("should not persist when no viewUUID is available", () => {
113
- const { result } = renderHook(() => useWidgetState({ page: 1 }));
113
+ const { result } = renderHook(() => useViewState({ page: 1 }));
114
114
  act(() => {
115
115
  result.current[1]({ page: 2 });
116
116
  });
@@ -120,7 +120,7 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
120
120
  it("should handle corrupted localStorage data gracefully", async () => {
121
121
  const viewUUID = "test-uuid-corrupt";
122
122
  localStorage.setItem(`sb:1700000000000:${viewUUID}`, "not valid json{{{");
123
- const { result } = renderHook(() => useWidgetState({ page: 1 }));
123
+ const { result } = renderHook(() => useViewState({ page: 1 }));
124
124
  act(() => {
125
125
  fireToolResultNotification({
126
126
  content: [{ type: "text", text: "result" }],
@@ -136,7 +136,7 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
136
136
  const viewUUID = "lru-test-uuid";
137
137
  const oldKey = `sb:1000000000000:${viewUUID}`;
138
138
  localStorage.setItem(oldKey, JSON.stringify({ page: 1 }));
139
- const { result } = renderHook(() => useWidgetState({ page: 1 }));
139
+ const { result } = renderHook(() => useViewState({ page: 1 }));
140
140
  await act(async () => {
141
141
  fireToolResultNotification({
142
142
  content: [{ type: "text", text: "result" }],
@@ -158,7 +158,7 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
158
158
  }
159
159
  expect(localStorage.length).toBe(200);
160
160
  const viewUUID = "eviction-test-uuid";
161
- const { result } = renderHook(() => useWidgetState({ page: 1 }));
161
+ const { result } = renderHook(() => useViewState({ page: 1 }));
162
162
  await act(async () => {
163
163
  fireToolResultNotification({
164
164
  content: [{ type: "text", text: "result" }],
@@ -174,4 +174,4 @@ describe("useWidgetState (mcp-app host — localStorage persistence)", () => {
174
174
  expect(localStorage.getItem("sb:1000000000000:old-uuid-0000")).toBeNull();
175
175
  });
176
176
  });
177
- //# sourceMappingURL=use-widget-state.test.js.map
177
+ //# sourceMappingURL=use-view-state.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-view-state.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-view-state.test.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,5 @@ export { createStore } from "./create-store.js";
3
3
  export * from "./data-llm.js";
4
4
  export { generateHelpers } from "./generate-helpers.js";
5
5
  export * from "./hooks/index.js";
6
- export { mountWidget } from "./mount-widget.js";
7
- export { skybridge } from "./plugin/plugin.js";
6
+ export { mountView } from "./mount-view.js";
8
7
  export * from "./types.js";
package/dist/web/index.js CHANGED
@@ -3,7 +3,6 @@ export { createStore } from "./create-store.js";
3
3
  export * from "./data-llm.js";
4
4
  export { generateHelpers } from "./generate-helpers.js";
5
5
  export * from "./hooks/index.js";
6
- export { mountWidget } from "./mount-widget.js";
7
- export { skybridge } from "./plugin/plugin.js";
6
+ export { mountView } from "./mount-view.js";
8
7
  export * from "./types.js";
9
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,cAAc,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const mountView: (component: React.ReactNode) => void;
@@ -3,7 +3,7 @@ import { createElement, StrictMode } from "react";
3
3
  import { createRoot } from "react-dom/client";
4
4
  import { installOpenAILoggingProxy } from "./proxy.js";
5
5
  let rootInstance = null;
6
- export const mountWidget = (component) => {
6
+ export const mountView = (component) => {
7
7
  const rootElement = document.getElementById("root");
8
8
  if (!rootElement) {
9
9
  throw new Error("Root element not found");
@@ -24,4 +24,4 @@ export const mountWidget = (component) => {
24
24
  rootInstance.render(createElement(StrictMode, null, app));
25
25
  })();
26
26
  };
27
- //# sourceMappingURL=mount-widget.js.map
27
+ //# sourceMappingURL=mount-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount-view.js","sourceRoot":"","sources":["../../src/web/mount-view.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD,IAAI,YAAY,GAAgB,IAAI,CAAC;AAErC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,SAA0B,EAAE,EAAE;IACtD,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACxB,yBAAyB,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;IAE5C,CAAC,KAAK,IAAI,EAAE;QACV,IAAI,GAAG,GAAG,SAAS,CAAC;QACpB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACzE,GAAG,GAAG,aAAa,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACtD,CAAC;QACD,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,EAAE,CAAC;AACP,CAAC,CAAC"}
@@ -1,2 +1,5 @@
1
1
  import type { Plugin } from "vite";
2
- export declare function skybridge(): Plugin;
2
+ export interface SkybridgePluginOptions {
3
+ viewsDir?: string;
4
+ }
5
+ export declare function skybridge(options?: SkybridgePluginOptions): Plugin;
@@ -1,29 +1,51 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { assertUniqueViewNames, discoverViewsSync, scanViewsSync, writeViewsDts, } from "./scan-views.js";
1
3
  import { transform as dataLlmTransform } from "./transform-data-llm.js";
2
- import { validateWidget } from "./validate-widget.js";
3
- // Matches widget entry files (e.g. src/widgets/foo.tsx, src/widgets/foo/index.tsx) with optional Vite query strings
4
- const WIDGET_ENTRY_RE = /\/src\/widgets\/(?:[^/]+\.(?:jsx|tsx)|[^/]+\/index\.tsx)(?:\?.*)?$/;
5
- export function skybridge() {
4
+ import { hasDefaultExport } from "./validate-view.js";
5
+ const VIRTUAL_PREFIX = "/_skybridge/view/";
6
+ const VIRTUAL_MODULE_PREFIX = "\0skybridge:view:";
7
+ function buildVirtualEntry(viewFilePath) {
8
+ const normalized = viewFilePath.replace(/\\/g, "/");
9
+ return [
10
+ `import { mountView } from "skybridge/web";`,
11
+ `import Component from "${normalized}";`,
12
+ `import { createElement } from "react";`,
13
+ `mountView(createElement(Component));`,
14
+ ].join("\n");
15
+ }
16
+ function getViewEntryPattern(viewsDir) {
17
+ const escaped = viewsDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18
+ return new RegExp(`${escaped}\\/(?:[^/]+\\.(?:jsx|tsx)|[^/]+\\/index\\.(?:tsx|jsx))(?:\\?.*)?$`);
19
+ }
20
+ export function skybridge(options) {
21
+ const rawViewsDir = options?.viewsDir ?? "src/views";
22
+ let resolvedViewsDir;
23
+ let projectRoot;
24
+ let viewMap = new Map();
25
+ let viewEntryPattern;
6
26
  return {
7
27
  name: "skybridge",
8
- async config(config) {
9
- // Dynamic imports to ensure Node modules are only loaded in Node.js context
10
- const { globSync } = await import("node:fs");
11
- const { basename, dirname, parse, resolve } = await import("node:path");
12
- const projectRoot = config.root || process.cwd();
13
- const flatWidgetPattern = resolve(projectRoot, "src/widgets/*.{js,ts,jsx,tsx,html}");
14
- const dirWidgetPattern = resolve(projectRoot, "src/widgets/*/index.tsx");
15
- const flatWidgets = globSync(flatWidgetPattern).map((file) => {
16
- const name = parse(file).name;
17
- return [name, file];
18
- });
19
- const dirWidgets = globSync(dirWidgetPattern).map((file) => {
20
- const name = basename(dirname(file));
21
- return [name, file];
22
- });
23
- const input = Object.fromEntries([...flatWidgets, ...dirWidgets]);
28
+ enforce: "pre",
29
+ // Read by `skybridge build` to resolve viewsDir before `tsc -b` runs.
30
+ api: { viewsDir: rawViewsDir },
31
+ config(config) {
32
+ projectRoot = config.root || process.cwd();
33
+ resolvedViewsDir = isAbsolute(rawViewsDir)
34
+ ? rawViewsDir
35
+ : resolve(projectRoot, rawViewsDir);
36
+ viewEntryPattern = getViewEntryPattern(resolvedViewsDir);
37
+ const views = discoverViewsSync(resolvedViewsDir);
38
+ viewMap = new Map(views.map((v) => [v.name, v]));
39
+ writeViewsDts(projectRoot, views);
40
+ const input = {};
41
+ for (const view of views) {
42
+ input[view.name] = `${VIRTUAL_PREFIX}${view.name}`;
43
+ }
24
44
  return {
25
45
  base: "/assets",
26
46
  build: {
47
+ outDir: "dist/assets",
48
+ emptyOutDir: true,
27
49
  manifest: true,
28
50
  minify: true,
29
51
  cssCodeSplit: false,
@@ -31,6 +53,27 @@ export function skybridge() {
31
53
  input,
32
54
  },
33
55
  },
56
+ // Pre-bundle view deps at startup so the first tool invocation
57
+ // doesn't hit Vite's on-demand re-optimization path (which sends
58
+ // `full-reload` over HMR — in our iframe flow the parent host
59
+ // can't honour a reload, and the view silently never mounts).
60
+ optimizeDeps: {
61
+ // Scan view files so transitive user deps (zod, tailwind, etc.)
62
+ // get pre-bundled at startup.
63
+ entries: [
64
+ `${resolvedViewsDir}/*.{tsx,jsx}`,
65
+ `${resolvedViewsDir}/*/index.{tsx,jsx}`,
66
+ ],
67
+ // Framework deps imported by the synthesized virtual entry.
68
+ // The scanner can't see the virtual module source, so we must
69
+ // list these explicitly.
70
+ include: [
71
+ "react",
72
+ "react-dom/client",
73
+ "react/jsx-runtime",
74
+ "skybridge/web",
75
+ ],
76
+ },
34
77
  experimental: {
35
78
  renderBuiltUrl: (filename) => {
36
79
  return {
@@ -40,12 +83,78 @@ export function skybridge() {
40
83
  },
41
84
  };
42
85
  },
43
- enforce: "pre",
44
- async transform(code, id) {
45
- if (WIDGET_ENTRY_RE.test(id)) {
46
- for (const warning of validateWidget(code, id)) {
47
- this.warn(warning.message);
86
+ resolveId(id) {
87
+ if (id.startsWith(VIRTUAL_PREFIX)) {
88
+ const name = id.slice(VIRTUAL_PREFIX.length);
89
+ if (viewMap.has(name)) {
90
+ return `${VIRTUAL_MODULE_PREFIX}${name}`;
91
+ }
92
+ }
93
+ return null;
94
+ },
95
+ load(id) {
96
+ if (id.startsWith(VIRTUAL_MODULE_PREFIX)) {
97
+ const name = id.slice(VIRTUAL_MODULE_PREFIX.length);
98
+ const view = viewMap.get(name);
99
+ if (view) {
100
+ return buildVirtualEntry(view.filePath);
101
+ }
102
+ }
103
+ return null;
104
+ },
105
+ configureServer(server) {
106
+ if (!resolvedViewsDir) {
107
+ const root = server.config.root || process.cwd();
108
+ resolvedViewsDir = isAbsolute(rawViewsDir)
109
+ ? rawViewsDir
110
+ : resolve(root, rawViewsDir);
111
+ projectRoot = root;
112
+ viewEntryPattern = getViewEntryPattern(resolvedViewsDir);
113
+ }
114
+ server.watcher.add(resolvedViewsDir);
115
+ // Track which view files we've already warned about so a rescan
116
+ // triggered by an unrelated edit doesn't re-emit the same warning.
117
+ let knownInvalid = new Set();
118
+ const rescan = () => {
119
+ try {
120
+ // Surface broken view files. Without this, files lacking a
121
+ // default export are silently dropped from the input and the
122
+ // user has no idea why their widget never mounts.
123
+ const { valid, invalid } = scanViewsSync(resolvedViewsDir);
124
+ const nextInvalid = new Set(invalid.map((v) => v.filePath));
125
+ for (const filePath of nextInvalid) {
126
+ if (!knownInvalid.has(filePath)) {
127
+ server.config.logger.warn(`[skybridge] view file "${relative(projectRoot, filePath)}" is missing a default export — it won't be served until fixed.`);
128
+ }
129
+ }
130
+ for (const filePath of knownInvalid) {
131
+ if (!nextInvalid.has(filePath)) {
132
+ server.config.logger.info(`[skybridge] view file "${relative(projectRoot, filePath)}" resolved.`);
133
+ }
134
+ }
135
+ knownInvalid = nextInvalid;
136
+ assertUniqueViewNames(valid);
137
+ viewMap = new Map(valid.map((v) => [v.name, v]));
138
+ writeViewsDts(projectRoot, valid);
48
139
  }
140
+ catch (err) {
141
+ // assertUniqueViewNames throws on duplicate view names. Catch so
142
+ // chokidar's listener chain doesn't surface it as unhandled and
143
+ // crash the dev server — previous viewMap stays active until
144
+ // the user fixes the conflict.
145
+ const message = err instanceof Error ? err.message : String(err);
146
+ server.config.logger.error(`[skybridge] view rescan failed: ${message}`);
147
+ }
148
+ };
149
+ // Initial scan emits warnings for broken files that exist at startup.
150
+ rescan();
151
+ server.watcher.on("add", rescan);
152
+ server.watcher.on("change", rescan);
153
+ server.watcher.on("unlink", rescan);
154
+ },
155
+ async transform(code, id) {
156
+ if (viewEntryPattern?.test(id) && !hasDefaultExport(code, id)) {
157
+ this.warn(`View file "${id.split("/").pop()}" is missing a default export.`);
49
158
  }
50
159
  return await dataLlmTransform(code, id);
51
160
  },
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/web/plugin/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,oHAAoH;AACpH,MAAM,eAAe,GACnB,oEAAoE,CAAC;AAEvE,MAAM,UAAU,SAAS;IACvB,OAAO;QACL,IAAI,EAAE,WAAW;QAEjB,KAAK,CAAC,MAAM,CAAC,MAAM;YACjB,4EAA4E;YAC5E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;YAC7C,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAExE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YACjD,MAAM,iBAAiB,GAAG,OAAO,CAC/B,WAAW,EACX,oCAAoC,CACrC,CAAC;YACF,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW,EAAE,yBAAyB,CAAC,CAAC;YAEzE,MAAM,WAAW,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;gBAC9B,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YACH,MAAM,UAAU,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;gBACrC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,WAAW,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;YAElE,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE;oBACL,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,IAAI;oBACZ,YAAY,EAAE,KAAK;oBACnB,aAAa,EAAE;wBACb,KAAK;qBACN;iBACF;gBACD,YAAY,EAAE;oBACZ,cAAc,EAAE,CAAC,QAAQ,EAAE,EAAE;wBAC3B,OAAO;4BACL,OAAO,EAAE,yCAAyC,QAAQ,GAAG;yBAC9D,CAAC;oBACJ,CAAC;iBACF;aACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,KAAK;QACd,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE;YACtB,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC7B,KAAK,MAAM,OAAO,IAAI,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;oBAC/C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,OAAO,MAAM,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/web/plugin/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface DiscoveredView {
2
+ name: string;
3
+ filePath: string;
4
+ }
5
+ export interface InvalidView {
6
+ filePath: string;
7
+ }
8
+ export declare function scanViewsSync(viewsDir: string): {
9
+ valid: DiscoveredView[];
10
+ invalid: InvalidView[];
11
+ };
12
+ export declare function assertUniqueViewNames(views: DiscoveredView[]): void;
13
+ export declare function discoverViewsSync(viewsDir: string): DiscoveredView[];
14
+ export declare function generateViewsDts(views: DiscoveredView[]): string;
15
+ export declare function writeViewsDts(projectRoot: string, views: DiscoveredView[]): void;
16
+ export declare function scanAndWriteViewsDts(projectRoot?: string, viewsDir?: string): void;
@@ -0,0 +1,88 @@
1
+ import { globSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { basename, dirname, isAbsolute, join, parse, resolve } from "node:path";
3
+ import { hasDefaultExport } from "./validate-view.js";
4
+ export function scanViewsSync(viewsDir) {
5
+ const flatPattern = resolve(viewsDir, "*.{tsx,jsx}");
6
+ const dirPattern = resolve(viewsDir, "*/index.{tsx,jsx}");
7
+ const flatFiles = globSync(flatPattern).map((file) => ({
8
+ name: parse(file).name,
9
+ filePath: file,
10
+ }));
11
+ const dirFiles = globSync(dirPattern).map((file) => ({
12
+ name: basename(dirname(file)),
13
+ filePath: file,
14
+ }));
15
+ // A barrel file like `views/foo/index.tsx` (no default export) must not
16
+ // falsely collide with a sibling `views/foo.tsx`. Drop top-level `index`
17
+ // before splitting valid vs invalid.
18
+ const candidates = [...flatFiles, ...dirFiles].filter((v) => v.name !== "index");
19
+ const valid = [];
20
+ const invalid = [];
21
+ for (const candidate of candidates) {
22
+ const code = readFileSync(candidate.filePath, "utf-8");
23
+ if (hasDefaultExport(code, candidate.filePath)) {
24
+ valid.push(candidate);
25
+ }
26
+ else {
27
+ invalid.push({
28
+ filePath: candidate.filePath,
29
+ });
30
+ }
31
+ }
32
+ return { valid, invalid };
33
+ }
34
+ export function assertUniqueViewNames(views) {
35
+ const nameMap = new Map();
36
+ for (const view of views) {
37
+ const paths = nameMap.get(view.name) ?? [];
38
+ paths.push(view.filePath);
39
+ nameMap.set(view.name, paths);
40
+ }
41
+ for (const [name, paths] of nameMap) {
42
+ if (paths.length > 1) {
43
+ throw new Error(`skybridge: duplicate view name "${name}" resolved from:\n - ${paths.join("\n - ")}\nRename one of the files to avoid the conflict.`);
44
+ }
45
+ }
46
+ }
47
+ export function discoverViewsSync(viewsDir) {
48
+ const { valid } = scanViewsSync(viewsDir);
49
+ assertUniqueViewNames(valid);
50
+ return valid;
51
+ }
52
+ export function generateViewsDts(views) {
53
+ const entries = views.map((v) => ` "${v.name}": true;`).join("\n");
54
+ return [
55
+ "export {};",
56
+ "",
57
+ 'declare module "skybridge/server" {',
58
+ " interface ViewNameRegistry {",
59
+ entries,
60
+ " }",
61
+ "}",
62
+ "",
63
+ ].join("\n");
64
+ }
65
+ export function writeViewsDts(projectRoot, views) {
66
+ const dir = join(projectRoot, ".skybridge");
67
+ mkdirSync(dir, { recursive: true });
68
+ const filePath = join(dir, "views.d.ts");
69
+ const content = generateViewsDts(views);
70
+ try {
71
+ const existing = readFileSync(filePath, "utf-8");
72
+ if (existing === content) {
73
+ return;
74
+ }
75
+ }
76
+ catch {
77
+ // File doesn't exist yet
78
+ }
79
+ writeFileSync(filePath, content, "utf-8");
80
+ }
81
+ export function scanAndWriteViewsDts(projectRoot, viewsDir) {
82
+ const root = projectRoot ?? process.cwd();
83
+ const rawDir = viewsDir ?? "src/views";
84
+ const resolvedDir = isAbsolute(rawDir) ? rawDir : resolve(root, rawDir);
85
+ const views = discoverViewsSync(resolvedDir);
86
+ writeViewsDts(root, views);
87
+ }
88
+ //# sourceMappingURL=scan-views.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-views.js","sourceRoot":"","sources":["../../../src/web/plugin/scan-views.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};