@osdk/widget.vite-plugin 3.1.0-beta.4 → 3.2.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/esm/build-plugin/FoundryWidgetBuildPlugin.js +39 -31
  3. package/build/esm/build-plugin/FoundryWidgetBuildPlugin.js.map +1 -1
  4. package/build/esm/build-plugin/__tests__/getWidgetBuildOutputs.test.js +25 -20
  5. package/build/esm/build-plugin/__tests__/getWidgetBuildOutputs.test.js.map +1 -1
  6. package/build/esm/build-plugin/getWidgetBuildOutputs.js +6 -10
  7. package/build/esm/build-plugin/getWidgetBuildOutputs.js.map +1 -1
  8. package/build/esm/client/app.js +11 -8
  9. package/build/esm/client/app.js.map +1 -1
  10. package/build/esm/client/entrypointIframe.js +41 -0
  11. package/build/esm/client/entrypointIframe.js.map +1 -0
  12. package/build/esm/common/__tests__/extractWidgetConfig.test.js +73 -0
  13. package/build/esm/common/__tests__/extractWidgetConfig.test.js.map +1 -0
  14. package/build/esm/common/constants.js +5 -0
  15. package/build/esm/common/constants.js.map +1 -1
  16. package/build/esm/common/extractWidgetConfig.js +11 -49
  17. package/build/esm/common/extractWidgetConfig.js.map +1 -1
  18. package/build/esm/dev-plugin/FoundryWidgetDevPlugin.js +15 -28
  19. package/build/esm/dev-plugin/FoundryWidgetDevPlugin.js.map +1 -1
  20. package/build/esm/dev-plugin/__tests__/getWidgetIdOverrideMap.test.js +13 -8
  21. package/build/esm/dev-plugin/__tests__/getWidgetIdOverrideMap.test.js.map +1 -1
  22. package/build/esm/dev-plugin/getWidgetIdOverrideMap.js +6 -6
  23. package/build/esm/dev-plugin/getWidgetIdOverrideMap.js.map +1 -1
  24. package/build/esm/dev-plugin/publishDevModeSettings.js +4 -4
  25. package/build/esm/dev-plugin/publishDevModeSettings.js.map +1 -1
  26. package/build/site/assets/{allPaths--FceqVry.js → allPaths-DcyFnTvZ.js} +1 -1
  27. package/build/site/assets/{allPathsLoader-DZfabLiK.js → allPathsLoader-DHYhi3rh.js} +2 -2
  28. package/build/site/assets/{index-npVd4hRG.js → index-Dm4x3YrF.js} +9 -9
  29. package/build/site/assets/{splitPathsBySizeLoader-CCtHMC1A.js → splitPathsBySizeLoader-CtOeozdm.js} +1 -1
  30. package/build/site/index.html +1 -1
  31. package/build/types/build-plugin/FoundryWidgetBuildPlugin.d.ts.map +1 -1
  32. package/build/types/build-plugin/getWidgetBuildOutputs.d.ts +2 -2
  33. package/build/types/build-plugin/getWidgetBuildOutputs.d.ts.map +1 -1
  34. package/build/types/client/app.d.ts.map +1 -1
  35. package/build/types/client/entrypointIframe.d.ts +4 -0
  36. package/build/types/client/entrypointIframe.d.ts.map +1 -0
  37. package/build/types/common/__tests__/extractWidgetConfig.test.d.ts +1 -0
  38. package/build/types/common/__tests__/extractWidgetConfig.test.d.ts.map +1 -0
  39. package/build/types/common/constants.d.ts +3 -0
  40. package/build/types/common/constants.d.ts.map +1 -1
  41. package/build/types/common/extractWidgetConfig.d.ts +2 -2
  42. package/build/types/common/extractWidgetConfig.d.ts.map +1 -1
  43. package/build/types/dev-plugin/FoundryWidgetDevPlugin.d.ts.map +1 -1
  44. package/build/types/dev-plugin/getWidgetIdOverrideMap.d.ts +1 -2
  45. package/build/types/dev-plugin/getWidgetIdOverrideMap.d.ts.map +1 -1
  46. package/build/types/dev-plugin/publishDevModeSettings.d.ts.map +1 -1
  47. package/package.json +5 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @osdk/widget.vite-plugin
2
2
 
3
+ ## 3.1.0-beta.5
4
+
5
+ ### Minor Changes
6
+
7
+ - 3e9cc76: Improve error visibility during widgets vite dev mode
8
+ - 232a11a: Replace AST parsing with Vite module evaluation for widget config extraction
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies [f173ee1]
13
+ - @osdk/widget.api@3.1.0-beta.5
14
+
3
15
  ## 3.1.0-beta.4
4
16
 
5
17
  ### Minor Changes
@@ -18,22 +18,22 @@ import { autoVersion, loadFoundryConfig } from "@osdk/foundry-config-json";
18
18
  import { MANIFEST_FILE_LOCATION } from "@osdk/widget.api";
19
19
  import fs from "fs";
20
20
  import path from "path";
21
- import { extractWidgetConfig } from "../common/extractWidgetConfig.js";
21
+ import { createServer } from "vite";
22
+ import { BUILD_PLUGIN_ID, MODULE_EVALUATION_MODE } from "../common/constants.js";
22
23
  import { getInputHtmlEntrypoints } from "../common/getInputHtmlEntrypoints.js";
23
- import { standardizeFileExtension } from "../common/standardizeFileExtension.js";
24
24
  import { buildWidgetSetManifest } from "./buildWidgetSetManifest.js";
25
25
  import { getWidgetBuildOutputs } from "./getWidgetBuildOutputs.js";
26
26
  import { getWidgetSetInputSpec } from "./getWidgetSetInputSpec.js";
27
- import { isConfigFile } from "./isConfigFile.js";
28
27
  export function FoundryWidgetBuildPlugin() {
29
28
  // The root HTML entrypoints of the build process
30
29
  let htmlEntrypoints;
31
- // Store the configuration per module ID, e.g. /repo/src/widget-one.config.ts -> { ... }
32
- const configFiles = {};
30
+ // Store the resolved Vite config for use in later build steps
33
31
  let config;
34
32
  return {
35
- name: "@osdk:widget-build-plugin",
33
+ name: BUILD_PLUGIN_ID,
36
34
  enforce: "pre",
35
+ // Only apply this plugin during build
36
+ apply: "build",
37
37
  /**
38
38
  * Capture the entrypoints from the Vite config for use in later build steps.
39
39
  */
@@ -46,20 +46,6 @@ export function FoundryWidgetBuildPlugin() {
46
46
  configResolved(_config) {
47
47
  config = _config;
48
48
  },
49
- /**
50
- * Attempt to parse any module that looks like a widget configuration file, storing the result
51
- * to be matched to entrypoints later.
52
- */
53
- moduleParsed(moduleInfo) {
54
- if (!isConfigFile(moduleInfo.id)) {
55
- return;
56
- }
57
- const widgetConfig = extractWidgetConfig(moduleInfo.id, moduleInfo.ast);
58
- if (widgetConfig != null) {
59
- const standardizedSource = standardizeFileExtension(moduleInfo.id);
60
- configFiles[standardizedSource] = widgetConfig;
61
- }
62
- },
63
49
  /**
64
50
  * Once the build is complete, generate the widget set manifest based on the entrypoints and
65
51
  * configuration files that were found.
@@ -72,24 +58,46 @@ export function FoundryWidgetBuildPlugin() {
72
58
  throw new Error("foundry.config.json file not found.");
73
59
  }
74
60
 
75
- // Build widget set manifest
76
- const widgetSetVersion = await computeWidgetSetVersion(foundryConfig);
77
- const widgetBuilds = htmlEntrypoints.map(input => getWidgetBuildOutputs(bundle, input, config.build.outDir, configFiles));
78
- const widgetSetInputSpec = await getWidgetSetInputSpec(path.resolve(process.cwd(), "package.json"));
79
- const widgetSetManifest = buildWidgetSetManifest(foundryConfig.foundryConfig.widgetSet.rid, widgetSetVersion, widgetBuilds, widgetSetInputSpec);
61
+ // Create a Vite server to evaluate widget config modules
62
+ const server = await createModuleEvaluationServer(config);
63
+ try {
64
+ // Build widget set manifest
65
+ const widgetSetVersion = await computeWidgetSetVersion(foundryConfig);
66
+ const widgetBuilds = await Promise.all(htmlEntrypoints.map(input => getWidgetBuildOutputs(bundle, input, config.build.outDir, server)));
67
+ const widgetSetInputSpec = await getWidgetSetInputSpec(path.resolve(process.cwd(), "package.json"));
68
+ const widgetSetManifest = buildWidgetSetManifest(foundryConfig.foundryConfig.widgetSet.rid, widgetSetVersion, widgetBuilds, widgetSetInputSpec);
80
69
 
81
- // Write the manifest to the dist directory
82
- const manifestPath = path.join(config.build.outDir, MANIFEST_FILE_LOCATION);
83
- fs.mkdirSync(path.dirname(manifestPath), {
84
- recursive: true
85
- });
86
- fs.writeFileSync(manifestPath, JSON.stringify(widgetSetManifest, null, 2));
70
+ // Write the manifest to the dist directory
71
+ writeManifest(widgetSetManifest, config.build.outDir);
72
+ } finally {
73
+ await server.close();
74
+ }
87
75
  }
88
76
  };
89
77
  }
78
+
79
+ /**
80
+ * Create a Vite server for widget config module evaluation during the build process.
81
+ * Must prevent loading the dev plugin to avoid triggering dev mode build steps.
82
+ */
83
+ async function createModuleEvaluationServer(config) {
84
+ return await createServer({
85
+ // Reference the existing config file in order to respect any custom config
86
+ configFile: config.configFile,
87
+ // Custom mode to prevent dev plugin execution
88
+ mode: MODULE_EVALUATION_MODE
89
+ });
90
+ }
90
91
  async function computeWidgetSetVersion(foundryConfig) {
91
92
  return autoVersion(foundryConfig.foundryConfig.widgetSet.autoVersion ?? {
92
93
  "type": "package-json"
93
94
  });
94
95
  }
96
+ function writeManifest(widgetSetManifest, outDir) {
97
+ const manifestPath = path.join(outDir, MANIFEST_FILE_LOCATION);
98
+ fs.mkdirSync(path.dirname(manifestPath), {
99
+ recursive: true
100
+ });
101
+ fs.writeFileSync(manifestPath, JSON.stringify(widgetSetManifest, null, 2));
102
+ }
95
103
  //# sourceMappingURL=FoundryWidgetBuildPlugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FoundryWidgetBuildPlugin.js","names":["autoVersion","loadFoundryConfig","MANIFEST_FILE_LOCATION","fs","path","extractWidgetConfig","getInputHtmlEntrypoints","standardizeFileExtension","buildWidgetSetManifest","getWidgetBuildOutputs","getWidgetSetInputSpec","isConfigFile","FoundryWidgetBuildPlugin","htmlEntrypoints","configFiles","config","name","enforce","buildStart","options","configResolved","_config","moduleParsed","moduleInfo","id","widgetConfig","ast","standardizedSource","writeBundle","_","bundle","foundryConfig","Error","widgetSetVersion","computeWidgetSetVersion","widgetBuilds","map","input","build","outDir","widgetSetInputSpec","resolve","process","cwd","widgetSetManifest","widgetSet","rid","manifestPath","join","mkdirSync","dirname","recursive","writeFileSync","JSON","stringify"],"sources":["FoundryWidgetBuildPlugin.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { LoadedFoundryConfig } from \"@osdk/foundry-config-json\";\nimport { autoVersion, loadFoundryConfig } from \"@osdk/foundry-config-json\";\nimport type { ParameterConfig, WidgetConfig } from \"@osdk/widget.api\";\nimport { MANIFEST_FILE_LOCATION } from \"@osdk/widget.api\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\nimport { extractWidgetConfig } from \"../common/extractWidgetConfig.js\";\nimport { getInputHtmlEntrypoints } from \"../common/getInputHtmlEntrypoints.js\";\nimport { standardizeFileExtension } from \"../common/standardizeFileExtension.js\";\nimport { buildWidgetSetManifest } from \"./buildWidgetSetManifest.js\";\nimport { getWidgetBuildOutputs } from \"./getWidgetBuildOutputs.js\";\nimport { getWidgetSetInputSpec } from \"./getWidgetSetInputSpec.js\";\nimport { isConfigFile } from \"./isConfigFile.js\";\n\nexport function FoundryWidgetBuildPlugin(): Plugin {\n // The root HTML entrypoints of the build process\n let htmlEntrypoints: string[];\n // Store the configuration per module ID, e.g. /repo/src/widget-one.config.ts -> { ... }\n const configFiles: Record<string, WidgetConfig<ParameterConfig>> = {};\n let config: ResolvedConfig;\n\n return {\n name: \"@osdk:widget-build-plugin\",\n enforce: \"pre\",\n\n /**\n * Capture the entrypoints from the Vite config for use in later build steps.\n */\n buildStart(options) {\n htmlEntrypoints = getInputHtmlEntrypoints(options);\n },\n\n /**\n * Store the resolved Vite config for use in later build steps.\n */\n configResolved(_config) {\n config = _config;\n },\n\n /**\n * Attempt to parse any module that looks like a widget configuration file, storing the result\n * to be matched to entrypoints later.\n */\n moduleParsed(moduleInfo) {\n if (!isConfigFile(moduleInfo.id)) {\n return;\n }\n\n const widgetConfig = extractWidgetConfig(moduleInfo.id, moduleInfo.ast);\n if (widgetConfig != null) {\n const standardizedSource = standardizeFileExtension(moduleInfo.id);\n configFiles[standardizedSource] = widgetConfig;\n }\n },\n\n /**\n * Once the build is complete, generate the widget set manifest based on the entrypoints and\n * configuration files that were found.\n *\n * Write the manifest to the expected location in the dist directory.\n */\n async writeBundle(_, bundle) {\n const foundryConfig = await loadFoundryConfig(\"widgetSet\");\n if (foundryConfig == null) {\n throw new Error(\"foundry.config.json file not found.\");\n }\n\n // Build widget set manifest\n const widgetSetVersion = await computeWidgetSetVersion(foundryConfig);\n const widgetBuilds = htmlEntrypoints.map((input) =>\n getWidgetBuildOutputs(bundle, input, config.build.outDir, configFiles)\n );\n const widgetSetInputSpec = await getWidgetSetInputSpec(\n path.resolve(process.cwd(), \"package.json\"),\n );\n const widgetSetManifest = buildWidgetSetManifest(\n foundryConfig.foundryConfig.widgetSet.rid,\n widgetSetVersion,\n widgetBuilds,\n widgetSetInputSpec,\n );\n\n // Write the manifest to the dist directory\n const manifestPath = path.join(\n config.build.outDir,\n MANIFEST_FILE_LOCATION,\n );\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(\n manifestPath,\n JSON.stringify(widgetSetManifest, null, 2),\n );\n },\n };\n}\n\nasync function computeWidgetSetVersion(\n foundryConfig: LoadedFoundryConfig<\"widgetSet\">,\n): Promise<string> {\n return autoVersion(\n foundryConfig.foundryConfig.widgetSet.autoVersion\n ?? { \"type\": \"package-json\" },\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FoundryWidgetBuildPlugin.js","names":["autoVersion","loadFoundryConfig","MANIFEST_FILE_LOCATION","fs","path","createServer","BUILD_PLUGIN_ID","MODULE_EVALUATION_MODE","getInputHtmlEntrypoints","buildWidgetSetManifest","getWidgetBuildOutputs","getWidgetSetInputSpec","FoundryWidgetBuildPlugin","htmlEntrypoints","config","name","enforce","apply","buildStart","options","configResolved","_config","writeBundle","_","bundle","foundryConfig","Error","server","createModuleEvaluationServer","widgetSetVersion","computeWidgetSetVersion","widgetBuilds","Promise","all","map","input","build","outDir","widgetSetInputSpec","resolve","process","cwd","widgetSetManifest","widgetSet","rid","writeManifest","close","configFile","mode","manifestPath","join","mkdirSync","dirname","recursive","writeFileSync","JSON","stringify"],"sources":["FoundryWidgetBuildPlugin.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { LoadedFoundryConfig } from \"@osdk/foundry-config-json\";\nimport { autoVersion, loadFoundryConfig } from \"@osdk/foundry-config-json\";\nimport type { WidgetSetManifest } from \"@osdk/widget.api\";\nimport { MANIFEST_FILE_LOCATION } from \"@osdk/widget.api\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { Plugin, ResolvedConfig, ViteDevServer } from \"vite\";\nimport { createServer } from \"vite\";\nimport {\n BUILD_PLUGIN_ID,\n MODULE_EVALUATION_MODE,\n} from \"../common/constants.js\";\nimport { getInputHtmlEntrypoints } from \"../common/getInputHtmlEntrypoints.js\";\nimport { buildWidgetSetManifest } from \"./buildWidgetSetManifest.js\";\nimport { getWidgetBuildOutputs } from \"./getWidgetBuildOutputs.js\";\nimport { getWidgetSetInputSpec } from \"./getWidgetSetInputSpec.js\";\n\nexport function FoundryWidgetBuildPlugin(): Plugin {\n // The root HTML entrypoints of the build process\n let htmlEntrypoints: string[];\n // Store the resolved Vite config for use in later build steps\n let config: ResolvedConfig;\n\n return {\n name: BUILD_PLUGIN_ID,\n enforce: \"pre\",\n // Only apply this plugin during build\n apply: \"build\",\n\n /**\n * Capture the entrypoints from the Vite config for use in later build steps.\n */\n buildStart(options) {\n htmlEntrypoints = getInputHtmlEntrypoints(options);\n },\n\n /**\n * Store the resolved Vite config for use in later build steps.\n */\n configResolved(_config) {\n config = _config;\n },\n\n /**\n * Once the build is complete, generate the widget set manifest based on the entrypoints and\n * configuration files that were found.\n *\n * Write the manifest to the expected location in the dist directory.\n */\n async writeBundle(_, bundle) {\n const foundryConfig = await loadFoundryConfig(\"widgetSet\");\n if (foundryConfig == null) {\n throw new Error(\"foundry.config.json file not found.\");\n }\n\n // Create a Vite server to evaluate widget config modules\n const server = await createModuleEvaluationServer(config);\n\n try {\n // Build widget set manifest\n const widgetSetVersion = await computeWidgetSetVersion(foundryConfig);\n const widgetBuilds = await Promise.all(\n htmlEntrypoints.map((input) =>\n getWidgetBuildOutputs(\n bundle,\n input,\n config.build.outDir,\n server,\n )\n ),\n );\n const widgetSetInputSpec = await getWidgetSetInputSpec(\n path.resolve(process.cwd(), \"package.json\"),\n );\n const widgetSetManifest = buildWidgetSetManifest(\n foundryConfig.foundryConfig.widgetSet.rid,\n widgetSetVersion,\n widgetBuilds,\n widgetSetInputSpec,\n );\n\n // Write the manifest to the dist directory\n writeManifest(widgetSetManifest, config.build.outDir);\n } finally {\n await server.close();\n }\n },\n };\n}\n\n/**\n * Create a Vite server for widget config module evaluation during the build process.\n * Must prevent loading the dev plugin to avoid triggering dev mode build steps.\n */\nasync function createModuleEvaluationServer(\n config: ResolvedConfig,\n): Promise<ViteDevServer> {\n return await createServer({\n // Reference the existing config file in order to respect any custom config\n configFile: config.configFile,\n // Custom mode to prevent dev plugin execution\n mode: MODULE_EVALUATION_MODE,\n });\n}\n\nasync function computeWidgetSetVersion(\n foundryConfig: LoadedFoundryConfig<\"widgetSet\">,\n): Promise<string> {\n return autoVersion(\n foundryConfig.foundryConfig.widgetSet.autoVersion\n ?? { \"type\": \"package-json\" },\n );\n}\n\nfunction writeManifest(\n widgetSetManifest: WidgetSetManifest,\n outDir: string,\n): void {\n const manifestPath = path.join(outDir, MANIFEST_FILE_LOCATION);\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(\n manifestPath,\n JSON.stringify(widgetSetManifest, null, 2),\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -14,14 +14,20 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { expect, test, vi } from "vitest";
17
+ import { beforeEach, expect, test, vi } from "vitest";
18
+ import * as extractWidgetConfigModule from "../../common/extractWidgetConfig.js";
18
19
  import * as extractBuildOutputsModule from "../extractBuildOutputs.js";
19
20
  import { getWidgetBuildOutputs } from "../getWidgetBuildOutputs.js";
20
21
  vi.mock("../extractBuildOutputs.js");
22
+ vi.mock("../../common/extractWidgetConfig.js");
21
23
  const MOCK_BUILD_DIR = "/build";
22
24
  const MOCK_INPUT = "index.html";
23
25
  const MOCK_WIDGET_ID = "widget-id";
24
- test("getWidgetBuildOutputs successfully matches widget build outputs", () => {
26
+ const MOCK_SERVER = {};
27
+ beforeEach(() => {
28
+ vi.clearAllMocks();
29
+ });
30
+ test("getWidgetBuildOutputs successfully matches widget build outputs", async () => {
25
31
  const mockBuildOutputs = {
26
32
  scripts: [{
27
33
  type: "script",
@@ -31,25 +37,23 @@ test("getWidgetBuildOutputs successfully matches widget build outputs", () => {
31
37
  stylesheets: ["/styles.css"]
32
38
  };
33
39
  vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue(mockBuildOutputs);
34
- const configFile = "/src/widget.config.js";
35
40
  const widgetConfig = mockWidgetConfig(MOCK_WIDGET_ID);
41
+ vi.mocked(extractWidgetConfigModule.extractWidgetConfig).mockResolvedValue(widgetConfig);
36
42
  const entryChunk = mockChunk({
37
43
  fileName: "chunk.js",
38
44
  isEntry: true,
39
45
  facadeModuleId: "/src/widget.js",
40
- moduleIds: [configFile]
46
+ moduleIds: ["/src/widget.config.js"]
41
47
  });
42
- const result = getWidgetBuildOutputs({
48
+ const result = await getWidgetBuildOutputs({
43
49
  "chunk.js": entryChunk
44
- }, MOCK_INPUT, MOCK_BUILD_DIR, {
45
- [configFile]: widgetConfig
46
- });
50
+ }, MOCK_INPUT, MOCK_BUILD_DIR, MOCK_SERVER);
47
51
  expect(result).toEqual({
48
52
  ...mockBuildOutputs,
49
53
  widgetConfig
50
54
  });
51
55
  });
52
- test("getWidgetBuildOutputs throws error when entrypoint chunk not found", () => {
56
+ test("getWidgetBuildOutputs throws error when entrypoint chunk not found", async () => {
53
57
  vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({
54
58
  scripts: [{
55
59
  type: "script",
@@ -64,11 +68,11 @@ test("getWidgetBuildOutputs throws error when entrypoint chunk not found", () =>
64
68
  facadeModuleId: "/src/widget.js",
65
69
  moduleIds: []
66
70
  });
67
- expect(() => getWidgetBuildOutputs({
71
+ await expect(() => getWidgetBuildOutputs({
68
72
  "chunk.js": nonEntryChunk
69
- }, MOCK_INPUT, MOCK_BUILD_DIR, {})).toThrow("Entrypoint chunk not found for input file: index.html");
73
+ }, MOCK_INPUT, MOCK_BUILD_DIR, MOCK_SERVER)).rejects.toThrow("Entrypoint chunk not found for input file: index.html");
70
74
  });
71
- test("getWidgetBuildOutputs throws error when no config file found", () => {
75
+ test("getWidgetBuildOutputs throws error when no config file found", async () => {
72
76
  vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({
73
77
  scripts: [{
74
78
  type: "script",
@@ -83,11 +87,11 @@ test("getWidgetBuildOutputs throws error when no config file found", () => {
83
87
  facadeModuleId: "/src/widget.js",
84
88
  moduleIds: []
85
89
  });
86
- expect(() => getWidgetBuildOutputs({
90
+ await expect(() => getWidgetBuildOutputs({
87
91
  "chunk.js": entryChunk
88
- }, MOCK_INPUT, MOCK_BUILD_DIR, {})).toThrow("No widget config files found for entrypoint /src/widget.js");
92
+ }, MOCK_INPUT, MOCK_BUILD_DIR, MOCK_SERVER)).rejects.toThrow("No widget config files found for entrypoint /src/widget.js");
89
93
  });
90
- test("getWidgetBuildOutputs throws error when multiple config files found", () => {
94
+ test("getWidgetBuildOutputs throws error when multiple config files found", async () => {
91
95
  vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({
92
96
  scripts: [{
93
97
  type: "script",
@@ -102,11 +106,11 @@ test("getWidgetBuildOutputs throws error when multiple config files found", () =
102
106
  facadeModuleId: "/src/widget.js",
103
107
  moduleIds: ["/src/widget.config.js", "/src/widget.config.ts"]
104
108
  });
105
- expect(() => getWidgetBuildOutputs({
109
+ await expect(() => getWidgetBuildOutputs({
106
110
  "chunk.js": entryChunk
107
- }, MOCK_INPUT, MOCK_BUILD_DIR, {})).toThrow("Multiple widget config files found for entrypoint /src/widget.js");
111
+ }, MOCK_INPUT, MOCK_BUILD_DIR, MOCK_SERVER)).rejects.toThrow("Multiple widget config files found for entrypoint /src/widget.js");
108
112
  });
109
- test("getWidgetBuildOutputs throws error when config file not found in configFiles", () => {
113
+ test("getWidgetBuildOutputs throws error when extractWidgetConfig fails", async () => {
110
114
  vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({
111
115
  scripts: [{
112
116
  type: "script",
@@ -121,9 +125,10 @@ test("getWidgetBuildOutputs throws error when config file not found in configFil
121
125
  facadeModuleId: "/src/widget.js",
122
126
  moduleIds: ["/src/widget.config.js"]
123
127
  });
124
- expect(() => getWidgetBuildOutputs({
128
+ vi.mocked(extractWidgetConfigModule.extractWidgetConfig).mockRejectedValue(new Error("Config extraction failed"));
129
+ await expect(() => getWidgetBuildOutputs({
125
130
  "chunk.js": entryChunk
126
- }, MOCK_INPUT, MOCK_BUILD_DIR, {})).toThrow("No config file found for entrypoint /src/widget.js");
131
+ }, MOCK_INPUT, MOCK_BUILD_DIR, MOCK_SERVER)).rejects.toThrow("Config extraction failed");
127
132
  });
128
133
  function mockChunk(props) {
129
134
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"getWidgetBuildOutputs.test.js","names":["expect","test","vi","extractBuildOutputsModule","getWidgetBuildOutputs","mock","MOCK_BUILD_DIR","MOCK_INPUT","MOCK_WIDGET_ID","mockBuildOutputs","scripts","type","scriptType","src","stylesheets","mocked","extractBuildOutputs","mockReturnValue","configFile","widgetConfig","mockWidgetConfig","entryChunk","mockChunk","fileName","isEntry","facadeModuleId","moduleIds","result","toEqual","nonEntryChunk","toThrow","props","id","name","description","parameters","events"],"sources":["getWidgetBuildOutputs.test.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ParameterConfig, WidgetConfig } from \"@osdk/widget.api\";\nimport type { Rollup } from \"vite\";\nimport { expect, test, vi } from \"vitest\";\nimport * as extractBuildOutputsModule from \"../extractBuildOutputs.js\";\nimport { getWidgetBuildOutputs } from \"../getWidgetBuildOutputs.js\";\n\nvi.mock(\"../extractBuildOutputs.js\");\n\nconst MOCK_BUILD_DIR = \"/build\";\nconst MOCK_INPUT = \"index.html\";\nconst MOCK_WIDGET_ID = \"widget-id\";\n\ntest(\"getWidgetBuildOutputs successfully matches widget build outputs\", () => {\n const mockBuildOutputs = {\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [\"/styles.css\"],\n };\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue(\n mockBuildOutputs,\n );\n\n const configFile = \"/src/widget.config.js\";\n const widgetConfig = mockWidgetConfig(MOCK_WIDGET_ID);\n const configFiles = { [configFile]: widgetConfig };\n\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [configFile],\n });\n\n const result = getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n configFiles,\n );\n expect(result).toEqual({\n ...mockBuildOutputs,\n widgetConfig,\n });\n});\n\ntest(\"getWidgetBuildOutputs throws error when entrypoint chunk not found\", () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/non-existent.js\",\n }],\n stylesheets: [],\n });\n\n const nonEntryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [],\n });\n\n expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": nonEntryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n {},\n )\n )\n .toThrow(\"Entrypoint chunk not found for input file: index.html\");\n});\n\ntest(\"getWidgetBuildOutputs throws error when no config file found\", () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [],\n });\n\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [],\n });\n\n expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n {},\n )\n )\n .toThrow(\"No widget config files found for entrypoint /src/widget.js\");\n});\n\ntest(\"getWidgetBuildOutputs throws error when multiple config files found\", () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [],\n });\n\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [\"/src/widget.config.js\", \"/src/widget.config.ts\"],\n });\n\n expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n {},\n )\n )\n .toThrow(\n \"Multiple widget config files found for entrypoint /src/widget.js\",\n );\n});\n\ntest(\"getWidgetBuildOutputs throws error when config file not found in configFiles\", () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [],\n });\n\n const configFile = \"/src/widget.config.js\";\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [configFile],\n });\n\n expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n {},\n )\n )\n .toThrow(\"No config file found for entrypoint /src/widget.js\");\n});\n\nfunction mockChunk(props: Partial<Rollup.OutputChunk>): Rollup.OutputChunk {\n return {\n type: \"chunk\",\n fileName: \"chunk.js\",\n isEntry: false,\n facadeModuleId: null,\n moduleIds: [],\n ...props,\n } as Rollup.OutputChunk;\n}\n\nfunction mockWidgetConfig(id: string): WidgetConfig<ParameterConfig> {\n return {\n id,\n name: id,\n description: id,\n type: \"workshop\",\n parameters: {},\n events: {},\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"getWidgetBuildOutputs.test.js","names":["beforeEach","expect","test","vi","extractWidgetConfigModule","extractBuildOutputsModule","getWidgetBuildOutputs","mock","MOCK_BUILD_DIR","MOCK_INPUT","MOCK_WIDGET_ID","MOCK_SERVER","clearAllMocks","mockBuildOutputs","scripts","type","scriptType","src","stylesheets","mocked","extractBuildOutputs","mockReturnValue","widgetConfig","mockWidgetConfig","extractWidgetConfig","mockResolvedValue","entryChunk","mockChunk","fileName","isEntry","facadeModuleId","moduleIds","result","toEqual","nonEntryChunk","rejects","toThrow","mockRejectedValue","Error","props","id","name","description","parameters","events"],"sources":["getWidgetBuildOutputs.test.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ParameterConfig, WidgetConfig } from \"@osdk/widget.api\";\nimport type { Rollup, ViteDevServer } from \"vite\";\nimport { beforeEach, expect, test, vi } from \"vitest\";\nimport * as extractWidgetConfigModule from \"../../common/extractWidgetConfig.js\";\nimport * as extractBuildOutputsModule from \"../extractBuildOutputs.js\";\nimport { getWidgetBuildOutputs } from \"../getWidgetBuildOutputs.js\";\n\nvi.mock(\"../extractBuildOutputs.js\");\nvi.mock(\"../../common/extractWidgetConfig.js\");\n\nconst MOCK_BUILD_DIR = \"/build\";\nconst MOCK_INPUT = \"index.html\";\nconst MOCK_WIDGET_ID = \"widget-id\";\nconst MOCK_SERVER = {} as ViteDevServer;\n\nbeforeEach(() => {\n vi.clearAllMocks();\n});\n\ntest(\"getWidgetBuildOutputs successfully matches widget build outputs\", async () => {\n const mockBuildOutputs = {\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [\"/styles.css\"],\n };\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue(\n mockBuildOutputs,\n );\n\n const configFile = \"/src/widget.config.js\";\n const widgetConfig = mockWidgetConfig(MOCK_WIDGET_ID);\n vi.mocked(extractWidgetConfigModule.extractWidgetConfig).mockResolvedValue(\n widgetConfig,\n );\n\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [configFile],\n });\n\n const result = await getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n MOCK_SERVER,\n );\n expect(result).toEqual({\n ...mockBuildOutputs,\n widgetConfig,\n });\n});\n\ntest(\"getWidgetBuildOutputs throws error when entrypoint chunk not found\", async () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/non-existent.js\",\n }],\n stylesheets: [],\n });\n\n const nonEntryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [],\n });\n\n await expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": nonEntryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n MOCK_SERVER,\n )\n )\n .rejects.toThrow(\"Entrypoint chunk not found for input file: index.html\");\n});\n\ntest(\"getWidgetBuildOutputs throws error when no config file found\", async () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [],\n });\n\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [],\n });\n\n await expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n MOCK_SERVER,\n )\n )\n .rejects.toThrow(\n \"No widget config files found for entrypoint /src/widget.js\",\n );\n});\n\ntest(\"getWidgetBuildOutputs throws error when multiple config files found\", async () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [],\n });\n\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [\"/src/widget.config.js\", \"/src/widget.config.ts\"],\n });\n\n await expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n MOCK_SERVER,\n )\n )\n .rejects.toThrow(\n \"Multiple widget config files found for entrypoint /src/widget.js\",\n );\n});\n\ntest(\"getWidgetBuildOutputs throws error when extractWidgetConfig fails\", async () => {\n vi.mocked(extractBuildOutputsModule.extractBuildOutputs).mockReturnValue({\n scripts: [{\n type: \"script\" as const,\n scriptType: \"module\" as const,\n src: \"/chunk.js\",\n }],\n stylesheets: [],\n });\n\n const configFile = \"/src/widget.config.js\";\n const entryChunk = mockChunk({\n fileName: \"chunk.js\",\n isEntry: true,\n facadeModuleId: \"/src/widget.js\",\n moduleIds: [configFile],\n });\n\n vi.mocked(extractWidgetConfigModule.extractWidgetConfig).mockRejectedValue(\n new Error(\"Config extraction failed\"),\n );\n\n await expect(() =>\n getWidgetBuildOutputs(\n { \"chunk.js\": entryChunk },\n MOCK_INPUT,\n MOCK_BUILD_DIR,\n MOCK_SERVER,\n )\n )\n .rejects.toThrow(\"Config extraction failed\");\n});\n\nfunction mockChunk(props: Partial<Rollup.OutputChunk>): Rollup.OutputChunk {\n return {\n type: \"chunk\",\n fileName: \"chunk.js\",\n isEntry: false,\n facadeModuleId: null,\n moduleIds: [],\n ...props,\n } as Rollup.OutputChunk;\n}\n\nfunction mockWidgetConfig(id: string): WidgetConfig<ParameterConfig> {\n return {\n id,\n name: id,\n description: id,\n type: \"workshop\",\n parameters: {},\n events: {},\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -15,10 +15,10 @@
15
15
  */
16
16
 
17
17
  import path from "path";
18
- import { standardizeFileExtension } from "../common/standardizeFileExtension.js";
18
+ import { extractWidgetConfig } from "../common/extractWidgetConfig.js";
19
19
  import { extractBuildOutputs } from "./extractBuildOutputs.js";
20
20
  import { isConfigFile } from "./isConfigFile.js";
21
- export function getWidgetBuildOutputs(bundle, input, buildDir, configFiles) {
21
+ export async function getWidgetBuildOutputs(bundle, input, buildDir, server) {
22
22
  const inputHtmlFilePath = path.resolve(buildDir, path.relative(process.cwd(), input));
23
23
  const buildOutputs = extractBuildOutputs(inputHtmlFilePath);
24
24
  const scriptPaths = new Set(buildOutputs.scripts.map(script => script.src.slice(1)));
@@ -26,13 +26,14 @@ export function getWidgetBuildOutputs(bundle, input, buildDir, configFiles) {
26
26
  if (entrypointChunk == null) {
27
27
  throw new Error(`Entrypoint chunk not found for input file: ${input}`);
28
28
  }
29
- const widgetConfig = getChunkConfigFile(entrypointChunk, configFiles);
29
+ const configModuleId = getChunkConfigModuleId(entrypointChunk);
30
+ const widgetConfig = await extractWidgetConfig(configModuleId, server);
30
31
  return {
31
32
  ...buildOutputs,
32
33
  widgetConfig
33
34
  };
34
35
  }
35
- function getChunkConfigFile(chunk, configFiles) {
36
+ function getChunkConfigModuleId(chunk) {
36
37
  const configModuleIds = chunk.moduleIds.filter(isConfigFile);
37
38
  if (configModuleIds.length === 0) {
38
39
  throw new Error(`No widget config files found for entrypoint ${chunk.facadeModuleId}`);
@@ -40,11 +41,6 @@ function getChunkConfigFile(chunk, configFiles) {
40
41
  if (configModuleIds.length > 1) {
41
42
  throw new Error(`Multiple widget config files found for entrypoint ${chunk.facadeModuleId}`);
42
43
  }
43
- const standardizedSource = standardizeFileExtension(configModuleIds[0]);
44
- const configFile = configFiles[standardizedSource];
45
- if (configFile == null) {
46
- throw new Error(`No config file found for entrypoint ${chunk.facadeModuleId}`);
47
- }
48
- return configFile;
44
+ return configModuleIds[0];
49
45
  }
50
46
  //# sourceMappingURL=getWidgetBuildOutputs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getWidgetBuildOutputs.js","names":["path","standardizeFileExtension","extractBuildOutputs","isConfigFile","getWidgetBuildOutputs","bundle","input","buildDir","configFiles","inputHtmlFilePath","resolve","relative","process","cwd","buildOutputs","scriptPaths","Set","scripts","map","script","src","slice","entrypointChunk","Object","values","find","chunk","type","isEntry","has","fileName","Error","widgetConfig","getChunkConfigFile","configModuleIds","moduleIds","filter","length","facadeModuleId","standardizedSource","configFile"],"sources":["getWidgetBuildOutputs.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ParameterConfig, WidgetConfig } from \"@osdk/widget.api\";\nimport path from \"path\";\nimport type { Rollup } from \"vite\";\nimport { standardizeFileExtension } from \"../common/standardizeFileExtension.js\";\nimport type { BuildOutputs } from \"./extractBuildOutputs.js\";\nimport { extractBuildOutputs } from \"./extractBuildOutputs.js\";\nimport { isConfigFile } from \"./isConfigFile.js\";\n\nexport interface WidgetBuildOutputs extends BuildOutputs {\n widgetConfig: WidgetConfig<ParameterConfig>;\n}\n\nexport function getWidgetBuildOutputs(\n bundle: Rollup.OutputBundle,\n input: string,\n buildDir: string,\n configFiles: Record<string, WidgetConfig<ParameterConfig>>,\n): WidgetBuildOutputs {\n const inputHtmlFilePath = path.resolve(\n buildDir,\n path.relative(process.cwd(), input),\n );\n const buildOutputs = extractBuildOutputs(inputHtmlFilePath);\n const scriptPaths = new Set(\n buildOutputs.scripts.map((script) => script.src.slice(1)),\n );\n const entrypointChunk = Object.values(bundle).find((\n chunk,\n ): chunk is Rollup.OutputChunk =>\n chunk.type === \"chunk\" && chunk.isEntry\n && scriptPaths.has(chunk.fileName)\n );\n if (entrypointChunk == null) {\n throw new Error(`Entrypoint chunk not found for input file: ${input}`);\n }\n const widgetConfig = getChunkConfigFile(entrypointChunk, configFiles);\n return { ...buildOutputs, widgetConfig };\n}\n\nfunction getChunkConfigFile(\n chunk: Rollup.OutputChunk,\n configFiles: Record<string, WidgetConfig<ParameterConfig>>,\n): WidgetConfig<ParameterConfig> {\n const configModuleIds = chunk.moduleIds.filter(isConfigFile);\n if (configModuleIds.length === 0) {\n throw new Error(\n `No widget config files found for entrypoint ${chunk.facadeModuleId}`,\n );\n }\n if (configModuleIds.length > 1) {\n throw new Error(\n `Multiple widget config files found for entrypoint ${chunk.facadeModuleId}`,\n );\n }\n\n const standardizedSource = standardizeFileExtension(configModuleIds[0]);\n const configFile = configFiles[standardizedSource];\n if (configFile == null) {\n throw new Error(\n `No config file found for entrypoint ${chunk.facadeModuleId}`,\n );\n }\n\n return configFile;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,OAAOA,IAAI,MAAM,MAAM;AAEvB,SAASC,wBAAwB,QAAQ,uCAAuC;AAEhF,SAASC,mBAAmB,QAAQ,0BAA0B;AAC9D,SAASC,YAAY,QAAQ,mBAAmB;AAMhD,OAAO,SAASC,qBAAqBA,CACnCC,MAA2B,EAC3BC,KAAa,EACbC,QAAgB,EAChBC,WAA0D,EACtC;EACpB,MAAMC,iBAAiB,GAAGT,IAAI,CAACU,OAAO,CACpCH,QAAQ,EACRP,IAAI,CAACW,QAAQ,CAACC,OAAO,CAACC,GAAG,CAAC,CAAC,EAAEP,KAAK,CACpC,CAAC;EACD,MAAMQ,YAAY,GAAGZ,mBAAmB,CAACO,iBAAiB,CAAC;EAC3D,MAAMM,WAAW,GAAG,IAAIC,GAAG,CACzBF,YAAY,CAACG,OAAO,CAACC,GAAG,CAAEC,MAAM,IAAKA,MAAM,CAACC,GAAG,CAACC,KAAK,CAAC,CAAC,CAAC,CAC1D,CAAC;EACD,MAAMC,eAAe,GAAGC,MAAM,CAACC,MAAM,CAACnB,MAAM,CAAC,CAACoB,IAAI,CAChDC,KAAK,IAELA,KAAK,CAACC,IAAI,KAAK,OAAO,IAAID,KAAK,CAACE,OAAO,IACpCb,WAAW,CAACc,GAAG,CAACH,KAAK,CAACI,QAAQ,CACnC,CAAC;EACD,IAAIR,eAAe,IAAI,IAAI,EAAE;IAC3B,MAAM,IAAIS,KAAK,CAAC,8CAA8CzB,KAAK,EAAE,CAAC;EACxE;EACA,MAAM0B,YAAY,GAAGC,kBAAkB,CAACX,eAAe,EAAEd,WAAW,CAAC;EACrE,OAAO;IAAE,GAAGM,YAAY;IAAEkB;EAAa,CAAC;AAC1C;AAEA,SAASC,kBAAkBA,CACzBP,KAAyB,EACzBlB,WAA0D,EAC3B;EAC/B,MAAM0B,eAAe,GAAGR,KAAK,CAACS,SAAS,CAACC,MAAM,CAACjC,YAAY,CAAC;EAC5D,IAAI+B,eAAe,CAACG,MAAM,KAAK,CAAC,EAAE;IAChC,MAAM,IAAIN,KAAK,CACb,+CAA+CL,KAAK,CAACY,cAAc,EACrE,CAAC;EACH;EACA,IAAIJ,eAAe,CAACG,MAAM,GAAG,CAAC,EAAE;IAC9B,MAAM,IAAIN,KAAK,CACb,qDAAqDL,KAAK,CAACY,cAAc,EAC3E,CAAC;EACH;EAEA,MAAMC,kBAAkB,GAAGtC,wBAAwB,CAACiC,eAAe,CAAC,CAAC,CAAC,CAAC;EACvE,MAAMM,UAAU,GAAGhC,WAAW,CAAC+B,kBAAkB,CAAC;EAClD,IAAIC,UAAU,IAAI,IAAI,EAAE;IACtB,MAAM,IAAIT,KAAK,CACb,uCAAuCL,KAAK,CAACY,cAAc,EAC7D,CAAC;EACH;EAEA,OAAOE,UAAU;AACnB","ignoreList":[]}
1
+ {"version":3,"file":"getWidgetBuildOutputs.js","names":["path","extractWidgetConfig","extractBuildOutputs","isConfigFile","getWidgetBuildOutputs","bundle","input","buildDir","server","inputHtmlFilePath","resolve","relative","process","cwd","buildOutputs","scriptPaths","Set","scripts","map","script","src","slice","entrypointChunk","Object","values","find","chunk","type","isEntry","has","fileName","Error","configModuleId","getChunkConfigModuleId","widgetConfig","configModuleIds","moduleIds","filter","length","facadeModuleId"],"sources":["getWidgetBuildOutputs.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ParameterConfig, WidgetConfig } from \"@osdk/widget.api\";\nimport path from \"path\";\nimport type { Rollup, ViteDevServer } from \"vite\";\nimport { extractWidgetConfig } from \"../common/extractWidgetConfig.js\";\nimport type { BuildOutputs } from \"./extractBuildOutputs.js\";\nimport { extractBuildOutputs } from \"./extractBuildOutputs.js\";\nimport { isConfigFile } from \"./isConfigFile.js\";\n\nexport interface WidgetBuildOutputs extends BuildOutputs {\n widgetConfig: WidgetConfig<ParameterConfig>;\n}\n\nexport async function getWidgetBuildOutputs(\n bundle: Rollup.OutputBundle,\n input: string,\n buildDir: string,\n server: ViteDevServer,\n): Promise<WidgetBuildOutputs> {\n const inputHtmlFilePath = path.resolve(\n buildDir,\n path.relative(process.cwd(), input),\n );\n const buildOutputs = extractBuildOutputs(inputHtmlFilePath);\n const scriptPaths = new Set(\n buildOutputs.scripts.map((script) => script.src.slice(1)),\n );\n const entrypointChunk = Object.values(bundle).find((\n chunk,\n ): chunk is Rollup.OutputChunk =>\n chunk.type === \"chunk\" && chunk.isEntry\n && scriptPaths.has(chunk.fileName)\n );\n if (entrypointChunk == null) {\n throw new Error(`Entrypoint chunk not found for input file: ${input}`);\n }\n const configModuleId = getChunkConfigModuleId(entrypointChunk);\n const widgetConfig = await extractWidgetConfig(configModuleId, server);\n return { ...buildOutputs, widgetConfig };\n}\n\nfunction getChunkConfigModuleId(\n chunk: Rollup.OutputChunk,\n): string {\n const configModuleIds = chunk.moduleIds.filter(isConfigFile);\n if (configModuleIds.length === 0) {\n throw new Error(\n `No widget config files found for entrypoint ${chunk.facadeModuleId}`,\n );\n }\n if (configModuleIds.length > 1) {\n throw new Error(\n `Multiple widget config files found for entrypoint ${chunk.facadeModuleId}`,\n );\n }\n\n return configModuleIds[0];\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,OAAOA,IAAI,MAAM,MAAM;AAEvB,SAASC,mBAAmB,QAAQ,kCAAkC;AAEtE,SAASC,mBAAmB,QAAQ,0BAA0B;AAC9D,SAASC,YAAY,QAAQ,mBAAmB;AAMhD,OAAO,eAAeC,qBAAqBA,CACzCC,MAA2B,EAC3BC,KAAa,EACbC,QAAgB,EAChBC,MAAqB,EACQ;EAC7B,MAAMC,iBAAiB,GAAGT,IAAI,CAACU,OAAO,CACpCH,QAAQ,EACRP,IAAI,CAACW,QAAQ,CAACC,OAAO,CAACC,GAAG,CAAC,CAAC,EAAEP,KAAK,CACpC,CAAC;EACD,MAAMQ,YAAY,GAAGZ,mBAAmB,CAACO,iBAAiB,CAAC;EAC3D,MAAMM,WAAW,GAAG,IAAIC,GAAG,CACzBF,YAAY,CAACG,OAAO,CAACC,GAAG,CAAEC,MAAM,IAAKA,MAAM,CAACC,GAAG,CAACC,KAAK,CAAC,CAAC,CAAC,CAC1D,CAAC;EACD,MAAMC,eAAe,GAAGC,MAAM,CAACC,MAAM,CAACnB,MAAM,CAAC,CAACoB,IAAI,CAChDC,KAAK,IAELA,KAAK,CAACC,IAAI,KAAK,OAAO,IAAID,KAAK,CAACE,OAAO,IACpCb,WAAW,CAACc,GAAG,CAACH,KAAK,CAACI,QAAQ,CACnC,CAAC;EACD,IAAIR,eAAe,IAAI,IAAI,EAAE;IAC3B,MAAM,IAAIS,KAAK,CAAC,8CAA8CzB,KAAK,EAAE,CAAC;EACxE;EACA,MAAM0B,cAAc,GAAGC,sBAAsB,CAACX,eAAe,CAAC;EAC9D,MAAMY,YAAY,GAAG,MAAMjC,mBAAmB,CAAC+B,cAAc,EAAExB,MAAM,CAAC;EACtE,OAAO;IAAE,GAAGM,YAAY;IAAEoB;EAAa,CAAC;AAC1C;AAEA,SAASD,sBAAsBA,CAC7BP,KAAyB,EACjB;EACR,MAAMS,eAAe,GAAGT,KAAK,CAACU,SAAS,CAACC,MAAM,CAAClC,YAAY,CAAC;EAC5D,IAAIgC,eAAe,CAACG,MAAM,KAAK,CAAC,EAAE;IAChC,MAAM,IAAIP,KAAK,CACb,+CAA+CL,KAAK,CAACa,cAAc,EACrE,CAAC;EACH;EACA,IAAIJ,eAAe,CAACG,MAAM,GAAG,CAAC,EAAE;IAC9B,MAAM,IAAIP,KAAK,CACb,qDAAqDL,KAAK,CAACa,cAAc,EAC3E,CAAC;EACH;EAEA,OAAOJ,eAAe,CAAC,CAAC,CAAC;AAC3B","ignoreList":[]}
@@ -16,6 +16,7 @@
16
16
 
17
17
  import { NonIdealState, Spinner, SpinnerSize } from "@blueprintjs/core";
18
18
  import React, { useEffect } from "react";
19
+ import { EntrypointIframe } from "./entrypointIframe.js";
19
20
  const POLLING_INTERVAL = 250;
20
21
  const REDIRECT_DELAY = 500;
21
22
  export const App = () => {
@@ -36,15 +37,15 @@ export const App = () => {
36
37
  if (result.status === "pending") {
37
38
  return;
38
39
  }
40
+ if (result.status === "error") {
41
+ throw new Error(result.error);
42
+ }
39
43
 
40
- // On success or failure, we clear the poll and end the loading state
44
+ // On success, we clear the poll and end the loading state
41
45
  window.clearInterval(poll);
42
- setPageState(result.status === "success" ? {
46
+ setPageState({
43
47
  state: "success",
44
48
  isRedirecting: result.redirectUrl != null
45
- } : {
46
- state: "failed",
47
- error: result.error
48
49
  });
49
50
 
50
51
  // When running in Code Workspaces the parent app will handle the redirect
@@ -55,6 +56,8 @@ export const App = () => {
55
56
  }
56
57
  }).catch(error => {
57
58
  window.clearInterval(poll);
59
+ // eslint-disable-next-line no-console
60
+ console.error("Failed to finish dev mode setup:", error);
58
61
  setPageState({
59
62
  state: "failed",
60
63
  error: error instanceof Error ? error.message : undefined
@@ -83,9 +86,9 @@ export const App = () => {
83
86
  title: "Failed to start dev mode",
84
87
  icon: "error",
85
88
  description: pageState.error
86
- }), entrypointPaths.map(entrypointPath => /*#__PURE__*/React.createElement("iframe", {
87
- key: entrypointPath,
88
- src: entrypointPath
89
+ }), entrypointPaths.map(entrypointPath => /*#__PURE__*/React.createElement(EntrypointIframe, {
90
+ src: entrypointPath,
91
+ key: entrypointPath
89
92
  })));
90
93
  };
91
94
  function loadEntrypoints() {
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","names":["NonIdealState","Spinner","SpinnerSize","React","useEffect","POLLING_INTERVAL","REDIRECT_DELAY","App","entrypointPaths","setEntrypointPaths","useState","pageState","setPageState","state","loadEntrypoints","then","poll","window","setInterval","finish","result","status","clearInterval","isRedirecting","redirectUrl","error","setTimeout","location","href","catch","Error","message","undefined","createElement","className","title","icon","intent","description","size","SMALL","map","entrypointPath","key","src","fetch","res","json"],"sources":["app.tsx"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NonIdealState, Spinner, SpinnerSize } from \"@blueprintjs/core\";\nimport React, { useEffect } from \"react\";\n\ntype PageState =\n | {\n state: \"loading\";\n }\n | {\n state: \"failed\";\n error?: string;\n }\n | {\n state: \"success\";\n isRedirecting: boolean;\n };\n\nconst POLLING_INTERVAL = 250;\nconst REDIRECT_DELAY = 500;\n\nexport const App: React.FC = () => {\n const [entrypointPaths, setEntrypointPaths] = React.useState<string[]>([]);\n const [pageState, setPageState] = React.useState<PageState>({\n state: \"loading\",\n });\n\n // Load entrypoints values on mount\n useEffect(() => {\n void loadEntrypoints().then(setEntrypointPaths);\n }, []);\n\n // Poll the finish endpoint until it returns a success or error\n useEffect(() => {\n const poll = window.setInterval(() => {\n void finish()\n .then((result) => {\n if (result.status === \"pending\") {\n return;\n }\n\n // On success or failure, we clear the poll and end the loading state\n window.clearInterval(poll);\n setPageState(\n result.status === \"success\"\n ? { state: \"success\", isRedirecting: result.redirectUrl != null }\n : { state: \"failed\", error: result.error },\n );\n\n // When running in Code Workspaces the parent app will handle the redirect\n if (result.status === \"success\" && result.redirectUrl != null) {\n setTimeout(() => {\n window.location.href = result.redirectUrl!;\n }, REDIRECT_DELAY);\n }\n })\n .catch((error: unknown) => {\n window.clearInterval(poll);\n setPageState({\n state: \"failed\",\n error: error instanceof Error ? error.message : undefined,\n });\n });\n }, POLLING_INTERVAL);\n return () => window.clearInterval(poll);\n }, []);\n\n return (\n <div className=\"body\">\n {pageState.state === \"loading\" && (\n <NonIdealState\n title=\"Generating developer mode manifest…\"\n icon={<Spinner intent=\"primary\" />}\n />\n )}\n {pageState.state === \"success\" && (\n <NonIdealState\n title=\"Started dev mode\"\n icon=\"tick-circle\"\n description={\n <div className=\"description\">\n <Spinner intent=\"primary\" size={SpinnerSize.SMALL} />{\" \"}\n {pageState.isRedirecting\n ? <span>Redirecting you…</span>\n : <span>Loading preview…</span>}\n </div>\n }\n />\n )}\n {pageState.state === \"failed\" && (\n <NonIdealState\n title=\"Failed to start dev mode\"\n icon=\"error\"\n description={pageState.error}\n />\n )}\n {/* To load the entrypoint info, we have to actually load it in the browser to get vite to follow the module graph. Since we know these files will fail, we just load them in iframes set to display: none to trigger the load hook in vite */}\n {entrypointPaths.map((entrypointPath) => (\n <iframe key={entrypointPath} src={entrypointPath} />\n ))}\n </div>\n );\n};\n\nfunction loadEntrypoints(): Promise<string[]> {\n return fetch(\"../entrypoints\").then((res) => res.json());\n}\n\nfunction finish(): Promise<\n | {\n status: \"success\";\n redirectUrl: string | null;\n }\n | {\n status: \"error\";\n error: string;\n }\n | {\n status: \"pending\";\n }\n> {\n return fetch(\"../finish\").then((res) => res.json());\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"app.js","names":["NonIdealState","Spinner","SpinnerSize","React","useEffect","EntrypointIframe","POLLING_INTERVAL","REDIRECT_DELAY","App","entrypointPaths","setEntrypointPaths","useState","pageState","setPageState","state","loadEntrypoints","then","poll","window","setInterval","finish","result","status","Error","error","clearInterval","isRedirecting","redirectUrl","setTimeout","location","href","catch","console","message","undefined","createElement","className","title","icon","intent","description","size","SMALL","map","entrypointPath","src","key","fetch","res","json"],"sources":["app.tsx"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NonIdealState, Spinner, SpinnerSize } from \"@blueprintjs/core\";\nimport React, { useEffect } from \"react\";\nimport { EntrypointIframe } from \"./entrypointIframe.js\";\n\ntype PageState =\n | {\n state: \"loading\";\n }\n | {\n state: \"failed\";\n error?: string;\n }\n | {\n state: \"success\";\n isRedirecting: boolean;\n };\n\nconst POLLING_INTERVAL = 250;\nconst REDIRECT_DELAY = 500;\n\nexport const App: React.FC = () => {\n const [entrypointPaths, setEntrypointPaths] = React.useState<string[]>([]);\n const [pageState, setPageState] = React.useState<PageState>({\n state: \"loading\",\n });\n\n // Load entrypoints values on mount\n useEffect(() => {\n void loadEntrypoints().then(setEntrypointPaths);\n }, []);\n\n // Poll the finish endpoint until it returns a success or error\n useEffect(() => {\n const poll = window.setInterval(() => {\n void finish()\n .then((result) => {\n if (result.status === \"pending\") {\n return;\n }\n if (result.status === \"error\") {\n throw new Error(result.error);\n }\n\n // On success, we clear the poll and end the loading state\n window.clearInterval(poll);\n setPageState({\n state: \"success\",\n isRedirecting: result.redirectUrl != null,\n });\n\n // When running in Code Workspaces the parent app will handle the redirect\n if (result.status === \"success\" && result.redirectUrl != null) {\n setTimeout(() => {\n window.location.href = result.redirectUrl!;\n }, REDIRECT_DELAY);\n }\n })\n .catch((error: unknown) => {\n window.clearInterval(poll);\n // eslint-disable-next-line no-console\n console.error(\"Failed to finish dev mode setup:\", error);\n setPageState({\n state: \"failed\",\n error: error instanceof Error ? error.message : undefined,\n });\n });\n }, POLLING_INTERVAL);\n return () => window.clearInterval(poll);\n }, []);\n\n return (\n <div className=\"body\">\n {pageState.state === \"loading\" && (\n <NonIdealState\n title=\"Generating developer mode manifest…\"\n icon={<Spinner intent=\"primary\" />}\n />\n )}\n {pageState.state === \"success\" && (\n <NonIdealState\n title=\"Started dev mode\"\n icon=\"tick-circle\"\n description={\n <div className=\"description\">\n <Spinner intent=\"primary\" size={SpinnerSize.SMALL} />{\" \"}\n {pageState.isRedirecting\n ? <span>Redirecting you…</span>\n : <span>Loading preview…</span>}\n </div>\n }\n />\n )}\n {pageState.state === \"failed\" && (\n <NonIdealState\n title=\"Failed to start dev mode\"\n icon=\"error\"\n description={pageState.error}\n />\n )}\n {/* To load the entrypoint info, we have to actually load it in the browser to get vite to follow the module graph. Since we know these files will fail, we just load them in iframes set to display: none to trigger the load hook in vite */}\n {entrypointPaths.map((entrypointPath) => (\n <EntrypointIframe src={entrypointPath} key={entrypointPath} />\n ))}\n </div>\n );\n};\n\nfunction loadEntrypoints(): Promise<string[]> {\n return fetch(\"../entrypoints\").then((res) => res.json());\n}\n\nfunction finish(): Promise<\n | {\n status: \"success\";\n redirectUrl: string | null;\n }\n | {\n status: \"error\";\n error: string;\n }\n | {\n status: \"pending\";\n }\n> {\n return fetch(\"../finish\").then((res) => res.json());\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Copyright 2024 Palantir Technologies, Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import React, { useEffect, useRef } from "react";
18
+ export const EntrypointIframe = ({
19
+ src
20
+ }) => {
21
+ // We expect the widget to not load properly as we don't provide the proper runtime.
22
+ // These errors are not useful to the user as we just put this iframe on the page to
23
+ // trigger vite to load the entrypoints.
24
+ const iframeRef = useRef(null);
25
+ useEffect(() => {
26
+ if (iframeRef.current?.contentWindow != null) {
27
+ const iframeWindow = iframeRef.current.contentWindow;
28
+ iframeWindow.console.log = () => {};
29
+ iframeWindow.console.warn = () => {};
30
+ iframeWindow.console.error = () => {};
31
+ iframeWindow.onerror = () => {
32
+ return true;
33
+ };
34
+ }
35
+ }, []);
36
+ return /*#__PURE__*/React.createElement("iframe", {
37
+ ref: iframeRef,
38
+ src: src
39
+ });
40
+ };
41
+ //# sourceMappingURL=entrypointIframe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypointIframe.js","names":["React","useEffect","useRef","EntrypointIframe","src","iframeRef","current","contentWindow","iframeWindow","console","log","warn","error","onerror","createElement","ref"],"sources":["entrypointIframe.tsx"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect, useRef } from \"react\";\n\nexport const EntrypointIframe: React.FC<{ src: string }> = ({ src }) => {\n // We expect the widget to not load properly as we don't provide the proper runtime.\n // These errors are not useful to the user as we just put this iframe on the page to\n // trigger vite to load the entrypoints.\n const iframeRef = useRef<HTMLIFrameElement>(null);\n useEffect(() => {\n if (iframeRef.current?.contentWindow != null) {\n const iframeWindow = iframeRef.current.contentWindow as Window & {\n console: Console;\n };\n iframeWindow.console.log = () => {};\n iframeWindow.console.warn = () => {};\n iframeWindow.console.error = () => {};\n iframeWindow.onerror = () => {\n return true;\n };\n }\n }, []);\n return <iframe ref={iframeRef} src={src} />;\n};\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAEhD,OAAO,MAAMC,gBAA2C,GAAGA,CAAC;EAAEC;AAAI,CAAC,KAAK;EACtE;EACA;EACA;EACA,MAAMC,SAAS,GAAGH,MAAM,CAAoB,IAAI,CAAC;EACjDD,SAAS,CAAC,MAAM;IACd,IAAII,SAAS,CAACC,OAAO,EAAEC,aAAa,IAAI,IAAI,EAAE;MAC5C,MAAMC,YAAY,GAAGH,SAAS,CAACC,OAAO,CAACC,aAEtC;MACDC,YAAY,CAACC,OAAO,CAACC,GAAG,GAAG,MAAM,CAAC,CAAC;MACnCF,YAAY,CAACC,OAAO,CAACE,IAAI,GAAG,MAAM,CAAC,CAAC;MACpCH,YAAY,CAACC,OAAO,CAACG,KAAK,GAAG,MAAM,CAAC,CAAC;MACrCJ,YAAY,CAACK,OAAO,GAAG,MAAM;QAC3B,OAAO,IAAI;MACb,CAAC;IACH;EACF,CAAC,EAAE,EAAE,CAAC;EACN,oBAAOb,KAAA,CAAAc,aAAA;IAAQC,GAAG,EAAEV,SAAU;IAACD,GAAG,EAAEA;EAAI,CAAE,CAAC;AAC7C,CAAC","ignoreList":[]}