@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.
- package/CHANGELOG.md +12 -0
- package/build/esm/build-plugin/FoundryWidgetBuildPlugin.js +39 -31
- package/build/esm/build-plugin/FoundryWidgetBuildPlugin.js.map +1 -1
- package/build/esm/build-plugin/__tests__/getWidgetBuildOutputs.test.js +25 -20
- package/build/esm/build-plugin/__tests__/getWidgetBuildOutputs.test.js.map +1 -1
- package/build/esm/build-plugin/getWidgetBuildOutputs.js +6 -10
- package/build/esm/build-plugin/getWidgetBuildOutputs.js.map +1 -1
- package/build/esm/client/app.js +11 -8
- package/build/esm/client/app.js.map +1 -1
- package/build/esm/client/entrypointIframe.js +41 -0
- package/build/esm/client/entrypointIframe.js.map +1 -0
- package/build/esm/common/__tests__/extractWidgetConfig.test.js +73 -0
- package/build/esm/common/__tests__/extractWidgetConfig.test.js.map +1 -0
- package/build/esm/common/constants.js +5 -0
- package/build/esm/common/constants.js.map +1 -1
- package/build/esm/common/extractWidgetConfig.js +11 -49
- package/build/esm/common/extractWidgetConfig.js.map +1 -1
- package/build/esm/dev-plugin/FoundryWidgetDevPlugin.js +15 -28
- package/build/esm/dev-plugin/FoundryWidgetDevPlugin.js.map +1 -1
- package/build/esm/dev-plugin/__tests__/getWidgetIdOverrideMap.test.js +13 -8
- package/build/esm/dev-plugin/__tests__/getWidgetIdOverrideMap.test.js.map +1 -1
- package/build/esm/dev-plugin/getWidgetIdOverrideMap.js +6 -6
- package/build/esm/dev-plugin/getWidgetIdOverrideMap.js.map +1 -1
- package/build/esm/dev-plugin/publishDevModeSettings.js +4 -4
- package/build/esm/dev-plugin/publishDevModeSettings.js.map +1 -1
- package/build/site/assets/{allPaths--FceqVry.js → allPaths-DcyFnTvZ.js} +1 -1
- package/build/site/assets/{allPathsLoader-DZfabLiK.js → allPathsLoader-DHYhi3rh.js} +2 -2
- package/build/site/assets/{index-npVd4hRG.js → index-Dm4x3YrF.js} +9 -9
- package/build/site/assets/{splitPathsBySizeLoader-CCtHMC1A.js → splitPathsBySizeLoader-CtOeozdm.js} +1 -1
- package/build/site/index.html +1 -1
- package/build/types/build-plugin/FoundryWidgetBuildPlugin.d.ts.map +1 -1
- package/build/types/build-plugin/getWidgetBuildOutputs.d.ts +2 -2
- package/build/types/build-plugin/getWidgetBuildOutputs.d.ts.map +1 -1
- package/build/types/client/app.d.ts.map +1 -1
- package/build/types/client/entrypointIframe.d.ts +4 -0
- package/build/types/client/entrypointIframe.d.ts.map +1 -0
- package/build/types/common/__tests__/extractWidgetConfig.test.d.ts +1 -0
- package/build/types/common/__tests__/extractWidgetConfig.test.d.ts.map +1 -0
- package/build/types/common/constants.d.ts +3 -0
- package/build/types/common/constants.d.ts.map +1 -1
- package/build/types/common/extractWidgetConfig.d.ts +2 -2
- package/build/types/common/extractWidgetConfig.d.ts.map +1 -1
- package/build/types/dev-plugin/FoundryWidgetDevPlugin.d.ts.map +1 -1
- package/build/types/dev-plugin/getWidgetIdOverrideMap.d.ts +1 -2
- package/build/types/dev-plugin/getWidgetIdOverrideMap.d.ts.map +1 -1
- package/build/types/dev-plugin/publishDevModeSettings.d.ts.map +1 -1
- 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 {
|
|
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
|
|
32
|
-
const configFiles = {};
|
|
30
|
+
// Store the resolved Vite config for use in later build steps
|
|
33
31
|
let config;
|
|
34
32
|
return {
|
|
35
|
-
name:
|
|
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
|
-
//
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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","
|
|
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
|
-
|
|
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: [
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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 {
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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","
|
|
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":[]}
|
package/build/esm/client/app.js
CHANGED
|
@@ -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
|
|
44
|
+
// On success, we clear the poll and end the loading state
|
|
41
45
|
window.clearInterval(poll);
|
|
42
|
-
setPageState(
|
|
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(
|
|
87
|
-
|
|
88
|
-
|
|
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","
|
|
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":[]}
|