@osdk/widget.vite-plugin 3.3.0-beta.1 → 3.3.0-beta.11
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 +76 -0
- package/build/esm/build-plugin/__tests__/validateWidgetSet.test.js +44 -0
- package/build/esm/build-plugin/__tests__/validateWidgetSet.test.js.map +1 -0
- package/build/esm/build-plugin/buildWidgetSetManifest.js +2 -0
- package/build/esm/build-plugin/buildWidgetSetManifest.js.map +1 -1
- package/build/esm/build-plugin/validateWidgetSet.js +30 -0
- package/build/esm/build-plugin/validateWidgetSet.js.map +1 -0
- package/build/esm/client/app.js +22 -6
- package/build/esm/client/app.js.map +1 -1
- package/build/esm/common/__tests__/extractWidgetConfig.test.js +3 -3
- package/build/esm/common/__tests__/extractWidgetConfig.test.js.map +1 -1
- package/build/esm/common/__tests__/standardizePathAndFileExtension.test.js +77 -0
- package/build/esm/common/__tests__/standardizePathAndFileExtension.test.js.map +1 -0
- package/build/esm/common/extractWidgetConfig.js +4 -1
- package/build/esm/common/extractWidgetConfig.js.map +1 -1
- package/build/esm/common/{standardizeFileExtension.js → standardizePathAndFileExtension.js} +13 -4
- package/build/esm/common/standardizePathAndFileExtension.js.map +1 -0
- package/build/esm/dev-plugin/FoundryWidgetDevPlugin.js +41 -11
- package/build/esm/dev-plugin/FoundryWidgetDevPlugin.js.map +1 -1
- package/build/esm/dev-plugin/__tests__/validateDevEnvironment.test.js +66 -0
- package/build/esm/dev-plugin/__tests__/validateDevEnvironment.test.js.map +1 -0
- package/build/esm/dev-plugin/publishDevModeSettings.js +19 -3
- package/build/esm/dev-plugin/publishDevModeSettings.js.map +1 -1
- package/build/esm/dev-plugin/validateDevEnvironment.js +33 -0
- package/build/esm/dev-plugin/validateDevEnvironment.js.map +1 -0
- package/build/site/assets/{allPaths-C9RDB26n.js → allPaths-DAStXfot.js} +1 -1
- package/build/site/assets/{allPathsLoader-DXy-gD-r.js → allPathsLoader-Xesz75gG.js} +2 -2
- package/build/site/assets/{index-D9t4xczX.js → index-C5U_5Xge.js} +10 -10
- package/build/site/assets/{index-CxjWve_y.css → index-DjCw4U9Z.css} +1 -1
- package/build/site/assets/{splitPathsBySizeLoader-CEcIKoAH.js → splitPathsBySizeLoader-DLaQMX-t.js} +1 -1
- package/build/site/index.html +2 -2
- package/build/types/build-plugin/__tests__/validateWidgetSet.test.d.ts +1 -0
- package/build/types/build-plugin/__tests__/validateWidgetSet.test.d.ts.map +1 -0
- package/build/types/build-plugin/buildWidgetSetManifest.d.ts.map +1 -1
- package/build/types/build-plugin/validateWidgetSet.d.ts +2 -0
- package/build/types/build-plugin/validateWidgetSet.d.ts.map +1 -0
- package/build/types/client/app.d.ts.map +1 -1
- package/build/types/common/__tests__/standardizePathAndFileExtension.test.d.ts +1 -0
- package/build/types/common/__tests__/standardizePathAndFileExtension.test.d.ts.map +1 -0
- package/build/types/common/standardizePathAndFileExtension.d.ts +9 -0
- package/build/types/common/standardizePathAndFileExtension.d.ts.map +1 -0
- package/build/types/dev-plugin/FoundryWidgetDevPlugin.d.ts.map +1 -1
- package/build/types/dev-plugin/__tests__/validateDevEnvironment.test.d.ts +1 -0
- package/build/types/dev-plugin/__tests__/validateDevEnvironment.test.d.ts.map +1 -0
- package/build/types/dev-plugin/publishDevModeSettings.d.ts.map +1 -1
- package/build/types/dev-plugin/validateDevEnvironment.d.ts +2 -0
- package/build/types/dev-plugin/validateDevEnvironment.d.ts.map +1 -0
- package/package.json +4 -4
- package/build/esm/common/standardizeFileExtension.js.map +0 -1
- package/build/types/common/standardizeFileExtension.d.ts +0 -6
- package/build/types/common/standardizeFileExtension.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# @osdk/widget.vite-plugin
|
|
2
2
|
|
|
3
|
+
## 3.3.0-beta.11
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e6a96c0: Validate widget sets before building their manifest
|
|
8
|
+
- 5bd88fc: Fix InvalidDevModeFilePath errors
|
|
9
|
+
- 27f2122: warn when using wrong dev command
|
|
10
|
+
- e95637e: Fix Windows dev mode
|
|
11
|
+
- 953c649: Use Vite logger instead of console.warn in validateDevEnvironment
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- @osdk/widget.api@3.3.0-beta.11
|
|
16
|
+
|
|
17
|
+
## 3.3.0-beta.10
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- @osdk/widget.api@3.3.0-beta.10
|
|
22
|
+
|
|
23
|
+
## 3.3.0-beta.9
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- @osdk/widget.api@3.3.0-beta.9
|
|
28
|
+
|
|
29
|
+
## 3.3.0-beta.8
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- @osdk/widget.api@3.3.0-beta.8
|
|
34
|
+
|
|
35
|
+
## 3.3.0-beta.7
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- @osdk/widget.api@3.3.0-beta.7
|
|
40
|
+
|
|
41
|
+
## 3.3.0-beta.6
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- @osdk/widget.api@3.3.0-beta.6
|
|
46
|
+
|
|
47
|
+
## 3.3.0-beta.5
|
|
48
|
+
|
|
49
|
+
### Minor Changes
|
|
50
|
+
|
|
51
|
+
- 1940934: Support extension-less widget config import and improve reporting when config files not found
|
|
52
|
+
- cc33fec: improve dev mode error surfacing
|
|
53
|
+
- 54e674e: Fix widget dev mode with tailwind causing project imports
|
|
54
|
+
- edb062f: Propagate validation error cause in message for widget config validation
|
|
55
|
+
|
|
56
|
+
### Patch Changes
|
|
57
|
+
|
|
58
|
+
- @osdk/widget.api@3.3.0-beta.5
|
|
59
|
+
|
|
60
|
+
## 3.3.0-beta.4
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- @osdk/widget.api@3.3.0-beta.4
|
|
65
|
+
|
|
66
|
+
## 3.3.0-beta.3
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- @osdk/widget.api@3.3.0-beta.3
|
|
71
|
+
|
|
72
|
+
## 3.3.0-beta.2
|
|
73
|
+
|
|
74
|
+
### Patch Changes
|
|
75
|
+
|
|
76
|
+
- Updated dependencies [4d37e98]
|
|
77
|
+
- @osdk/widget.api@3.3.0-beta.2
|
|
78
|
+
|
|
3
79
|
## 3.2.0-beta.5
|
|
4
80
|
|
|
5
81
|
### Patch Changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 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 { describe, expect, it } from "vitest";
|
|
18
|
+
import { validateWidgetSet } from "../validateWidgetSet.js";
|
|
19
|
+
describe("validateWidgetSet", () => {
|
|
20
|
+
describe("validateWidgetIds", () => {
|
|
21
|
+
it("should not throw when all widget IDs are unique", () => {
|
|
22
|
+
const widgetBuilds = [createWidgetBuild("widget1"), createWidgetBuild("widget2"), createWidgetBuild("widget3")];
|
|
23
|
+
expect(() => validateWidgetSet(widgetBuilds)).not.toThrow();
|
|
24
|
+
});
|
|
25
|
+
it("should throw when duplicate widget IDs are found", () => {
|
|
26
|
+
const widgetBuilds = [createWidgetBuild("widget1"), createWidgetBuild("widget2"), createWidgetBuild("widget1")];
|
|
27
|
+
expect(() => validateWidgetSet(widgetBuilds)).toThrow("Duplicate widget ID: widget1. Each widget must have a unique ID.");
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
function createWidgetBuild(id) {
|
|
32
|
+
return {
|
|
33
|
+
widgetConfig: {
|
|
34
|
+
id,
|
|
35
|
+
name: `Widget ${id}`,
|
|
36
|
+
type: "workshop",
|
|
37
|
+
parameters: {},
|
|
38
|
+
events: {}
|
|
39
|
+
},
|
|
40
|
+
scripts: [],
|
|
41
|
+
stylesheets: []
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=validateWidgetSet.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateWidgetSet.test.js","names":["describe","expect","it","validateWidgetSet","widgetBuilds","createWidgetBuild","not","toThrow","id","widgetConfig","name","type","parameters","events","scripts","stylesheets"],"sources":["validateWidgetSet.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 { describe, expect, it } from \"vitest\";\nimport type { WidgetBuildOutputs } from \"../getWidgetBuildOutputs.js\";\nimport { validateWidgetSet } from \"../validateWidgetSet.js\";\n\ndescribe(\"validateWidgetSet\", () => {\n describe(\"validateWidgetIds\", () => {\n it(\"should not throw when all widget IDs are unique\", () => {\n const widgetBuilds: WidgetBuildOutputs[] = [\n createWidgetBuild(\"widget1\"),\n createWidgetBuild(\"widget2\"),\n createWidgetBuild(\"widget3\"),\n ];\n\n expect(() => validateWidgetSet(widgetBuilds)).not.toThrow();\n });\n\n it(\"should throw when duplicate widget IDs are found\", () => {\n const widgetBuilds: WidgetBuildOutputs[] = [\n createWidgetBuild(\"widget1\"),\n createWidgetBuild(\"widget2\"),\n createWidgetBuild(\"widget1\"),\n ];\n\n expect(() => validateWidgetSet(widgetBuilds)).toThrow(\n \"Duplicate widget ID: widget1. Each widget must have a unique ID.\",\n );\n });\n });\n});\n\nfunction createWidgetBuild(id: string): WidgetBuildOutputs {\n return {\n widgetConfig: {\n id,\n name: `Widget ${id}`,\n type: \"workshop\",\n parameters: {},\n events: {},\n },\n scripts: [],\n stylesheets: [],\n };\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,QAAQ;AAE7C,SAASC,iBAAiB,QAAQ,yBAAyB;AAE3DH,QAAQ,CAAC,mBAAmB,EAAE,MAAM;EAClCA,QAAQ,CAAC,mBAAmB,EAAE,MAAM;IAClCE,EAAE,CAAC,iDAAiD,EAAE,MAAM;MAC1D,MAAME,YAAkC,GAAG,CACzCC,iBAAiB,CAAC,SAAS,CAAC,EAC5BA,iBAAiB,CAAC,SAAS,CAAC,EAC5BA,iBAAiB,CAAC,SAAS,CAAC,CAC7B;MAEDJ,MAAM,CAAC,MAAME,iBAAiB,CAACC,YAAY,CAAC,CAAC,CAACE,GAAG,CAACC,OAAO,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEFL,EAAE,CAAC,kDAAkD,EAAE,MAAM;MAC3D,MAAME,YAAkC,GAAG,CACzCC,iBAAiB,CAAC,SAAS,CAAC,EAC5BA,iBAAiB,CAAC,SAAS,CAAC,EAC5BA,iBAAiB,CAAC,SAAS,CAAC,CAC7B;MAEDJ,MAAM,CAAC,MAAME,iBAAiB,CAACC,YAAY,CAAC,CAAC,CAACG,OAAO,CACnD,kEACF,CAAC;IACH,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,SAASF,iBAAiBA,CAACG,EAAU,EAAsB;EACzD,OAAO;IACLC,YAAY,EAAE;MACZD,EAAE;MACFE,IAAI,EAAE,UAAUF,EAAE,EAAE;MACpBG,IAAI,EAAE,UAAU;MAChBC,UAAU,EAAE,CAAC,CAAC;MACdC,MAAM,EAAE,CAAC;IACX,CAAC;IACDC,OAAO,EAAE,EAAE;IACXC,WAAW,EAAE;EACf,CAAC;AACH","ignoreList":[]}
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { validateWidgetSet } from "./validateWidgetSet.js";
|
|
17
18
|
export function buildWidgetSetManifest(widgetSetRid, widgetSetVersion, widgetBuilds, widgetSetInputSpec) {
|
|
19
|
+
validateWidgetSet(widgetBuilds);
|
|
18
20
|
return {
|
|
19
21
|
manifestVersion: "1.0.0",
|
|
20
22
|
widgetSet: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildWidgetSetManifest.js","names":["buildWidgetSetManifest","widgetSetRid","widgetSetVersion","widgetBuilds","widgetSetInputSpec","manifestVersion","widgetSet","rid","version","widgets","Object","fromEntries","map","buildWidgetManifest","widgetManifest","id","inputSpec","widgetBuild","widgetConfig","name","description","type","entrypointJs","scripts","script","path","trimLeadingSlash","src","scriptType","entrypointCss","stylesheets","parameters","convertParameters","events","entries","key","param","convertParameter","parameter","objectType","internalDoNotUseMetadata","Error","displayName","objectTypeRids","startsWith","slice"],"sources":["buildWidgetSetManifest.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 {\n ManifestParameterDefinition,\n ParameterDefinition,\n WidgetManifestConfig,\n WidgetSetInputSpec,\n WidgetSetManifest,\n} from \"@osdk/widget.api\";\nimport type { WidgetBuildOutputs } from \"./getWidgetBuildOutputs.js\";\n\nexport function buildWidgetSetManifest(\n widgetSetRid: string,\n widgetSetVersion: string,\n widgetBuilds: WidgetBuildOutputs[],\n widgetSetInputSpec: WidgetSetInputSpec,\n): WidgetSetManifest {\n return {\n manifestVersion: \"1.0.0\",\n widgetSet: {\n rid: widgetSetRid,\n version: widgetSetVersion,\n widgets: Object.fromEntries(\n widgetBuilds\n .map(buildWidgetManifest)\n .map((widgetManifest) => [widgetManifest.id, widgetManifest]),\n ),\n inputSpec: widgetSetInputSpec,\n },\n };\n}\n\nfunction buildWidgetManifest(\n widgetBuild: WidgetBuildOutputs,\n): WidgetManifestConfig {\n const widgetConfig = widgetBuild.widgetConfig;\n return {\n id: widgetConfig.id,\n name: widgetConfig.name,\n description: widgetConfig.description,\n type: \"workshopWidgetV1\",\n entrypointJs: widgetBuild.scripts.map((script) => ({\n path: trimLeadingSlash(script.src),\n type: script.scriptType,\n })),\n entrypointCss: widgetBuild.stylesheets.map((path) => ({\n path: trimLeadingSlash(path),\n })),\n parameters: convertParameters(widgetConfig.parameters),\n events: widgetConfig.events,\n };\n}\n\nfunction convertParameters(\n parameters: Record<string, ParameterDefinition>,\n): Record<string, ManifestParameterDefinition> {\n return Object.fromEntries(\n Object.entries(parameters).map(([key, param]) => [\n key,\n convertParameter(param),\n ]),\n );\n}\n\nfunction convertParameter(\n parameter: ParameterDefinition,\n): ManifestParameterDefinition {\n if (parameter.type === \"objectSet\") {\n // Config has already been validated so rid must be present\n if (parameter.objectType.internalDoNotUseMetadata == null) {\n throw new Error(\"Expected internal metadata to be present\");\n }\n return {\n type: \"objectSet\",\n displayName: parameter.displayName,\n objectTypeRids: [parameter.objectType.internalDoNotUseMetadata.rid],\n };\n }\n return parameter;\n}\n\nfunction trimLeadingSlash(path: string): string {\n return path.startsWith(\"/\") ? path.slice(1) : path;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"file":"buildWidgetSetManifest.js","names":["validateWidgetSet","buildWidgetSetManifest","widgetSetRid","widgetSetVersion","widgetBuilds","widgetSetInputSpec","manifestVersion","widgetSet","rid","version","widgets","Object","fromEntries","map","buildWidgetManifest","widgetManifest","id","inputSpec","widgetBuild","widgetConfig","name","description","type","entrypointJs","scripts","script","path","trimLeadingSlash","src","scriptType","entrypointCss","stylesheets","parameters","convertParameters","events","entries","key","param","convertParameter","parameter","objectType","internalDoNotUseMetadata","Error","displayName","objectTypeRids","startsWith","slice"],"sources":["buildWidgetSetManifest.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 {\n ManifestParameterDefinition,\n ParameterDefinition,\n WidgetManifestConfig,\n WidgetSetInputSpec,\n WidgetSetManifest,\n} from \"@osdk/widget.api\";\nimport type { WidgetBuildOutputs } from \"./getWidgetBuildOutputs.js\";\nimport { validateWidgetSet } from \"./validateWidgetSet.js\";\n\nexport function buildWidgetSetManifest(\n widgetSetRid: string,\n widgetSetVersion: string,\n widgetBuilds: WidgetBuildOutputs[],\n widgetSetInputSpec: WidgetSetInputSpec,\n): WidgetSetManifest {\n validateWidgetSet(widgetBuilds);\n return {\n manifestVersion: \"1.0.0\",\n widgetSet: {\n rid: widgetSetRid,\n version: widgetSetVersion,\n widgets: Object.fromEntries(\n widgetBuilds\n .map(buildWidgetManifest)\n .map((widgetManifest) => [widgetManifest.id, widgetManifest]),\n ),\n inputSpec: widgetSetInputSpec,\n },\n };\n}\n\nfunction buildWidgetManifest(\n widgetBuild: WidgetBuildOutputs,\n): WidgetManifestConfig {\n const widgetConfig = widgetBuild.widgetConfig;\n return {\n id: widgetConfig.id,\n name: widgetConfig.name,\n description: widgetConfig.description,\n type: \"workshopWidgetV1\",\n entrypointJs: widgetBuild.scripts.map((script) => ({\n path: trimLeadingSlash(script.src),\n type: script.scriptType,\n })),\n entrypointCss: widgetBuild.stylesheets.map((path) => ({\n path: trimLeadingSlash(path),\n })),\n parameters: convertParameters(widgetConfig.parameters),\n events: widgetConfig.events,\n };\n}\n\nfunction convertParameters(\n parameters: Record<string, ParameterDefinition>,\n): Record<string, ManifestParameterDefinition> {\n return Object.fromEntries(\n Object.entries(parameters).map(([key, param]) => [\n key,\n convertParameter(param),\n ]),\n );\n}\n\nfunction convertParameter(\n parameter: ParameterDefinition,\n): ManifestParameterDefinition {\n if (parameter.type === \"objectSet\") {\n // Config has already been validated so rid must be present\n if (parameter.objectType.internalDoNotUseMetadata == null) {\n throw new Error(\"Expected internal metadata to be present\");\n }\n return {\n type: \"objectSet\",\n displayName: parameter.displayName,\n objectTypeRids: [parameter.objectType.internalDoNotUseMetadata.rid],\n };\n }\n return parameter;\n}\n\nfunction trimLeadingSlash(path: string): string {\n return path.startsWith(\"/\") ? path.slice(1) : path;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAUA,SAASA,iBAAiB,QAAQ,wBAAwB;AAE1D,OAAO,SAASC,sBAAsBA,CACpCC,YAAoB,EACpBC,gBAAwB,EACxBC,YAAkC,EAClCC,kBAAsC,EACnB;EACnBL,iBAAiB,CAACI,YAAY,CAAC;EAC/B,OAAO;IACLE,eAAe,EAAE,OAAO;IACxBC,SAAS,EAAE;MACTC,GAAG,EAAEN,YAAY;MACjBO,OAAO,EAAEN,gBAAgB;MACzBO,OAAO,EAAEC,MAAM,CAACC,WAAW,CACzBR,YAAY,CACTS,GAAG,CAACC,mBAAmB,CAAC,CACxBD,GAAG,CAAEE,cAAc,IAAK,CAACA,cAAc,CAACC,EAAE,EAAED,cAAc,CAAC,CAChE,CAAC;MACDE,SAAS,EAAEZ;IACb;EACF,CAAC;AACH;AAEA,SAASS,mBAAmBA,CAC1BI,WAA+B,EACT;EACtB,MAAMC,YAAY,GAAGD,WAAW,CAACC,YAAY;EAC7C,OAAO;IACLH,EAAE,EAAEG,YAAY,CAACH,EAAE;IACnBI,IAAI,EAAED,YAAY,CAACC,IAAI;IACvBC,WAAW,EAAEF,YAAY,CAACE,WAAW;IACrCC,IAAI,EAAE,kBAAkB;IACxBC,YAAY,EAAEL,WAAW,CAACM,OAAO,CAACX,GAAG,CAAEY,MAAM,KAAM;MACjDC,IAAI,EAAEC,gBAAgB,CAACF,MAAM,CAACG,GAAG,CAAC;MAClCN,IAAI,EAAEG,MAAM,CAACI;IACf,CAAC,CAAC,CAAC;IACHC,aAAa,EAAEZ,WAAW,CAACa,WAAW,CAAClB,GAAG,CAAEa,IAAI,KAAM;MACpDA,IAAI,EAAEC,gBAAgB,CAACD,IAAI;IAC7B,CAAC,CAAC,CAAC;IACHM,UAAU,EAAEC,iBAAiB,CAACd,YAAY,CAACa,UAAU,CAAC;IACtDE,MAAM,EAAEf,YAAY,CAACe;EACvB,CAAC;AACH;AAEA,SAASD,iBAAiBA,CACxBD,UAA+C,EACF;EAC7C,OAAOrB,MAAM,CAACC,WAAW,CACvBD,MAAM,CAACwB,OAAO,CAACH,UAAU,CAAC,CAACnB,GAAG,CAAC,CAAC,CAACuB,GAAG,EAAEC,KAAK,CAAC,KAAK,CAC/CD,GAAG,EACHE,gBAAgB,CAACD,KAAK,CAAC,CACxB,CACH,CAAC;AACH;AAEA,SAASC,gBAAgBA,CACvBC,SAA8B,EACD;EAC7B,IAAIA,SAAS,CAACjB,IAAI,KAAK,WAAW,EAAE;IAClC;IACA,IAAIiB,SAAS,CAACC,UAAU,CAACC,wBAAwB,IAAI,IAAI,EAAE;MACzD,MAAM,IAAIC,KAAK,CAAC,0CAA0C,CAAC;IAC7D;IACA,OAAO;MACLpB,IAAI,EAAE,WAAW;MACjBqB,WAAW,EAAEJ,SAAS,CAACI,WAAW;MAClCC,cAAc,EAAE,CAACL,SAAS,CAACC,UAAU,CAACC,wBAAwB,CAACjC,GAAG;IACpE,CAAC;EACH;EACA,OAAO+B,SAAS;AAClB;AAEA,SAASZ,gBAAgBA,CAACD,IAAY,EAAU;EAC9C,OAAOA,IAAI,CAACmB,UAAU,CAAC,GAAG,CAAC,GAAGnB,IAAI,CAACoB,KAAK,CAAC,CAAC,CAAC,GAAGpB,IAAI;AACpD","ignoreList":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 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
|
+
export function validateWidgetSet(widgetBuilds) {
|
|
18
|
+
validateWidgetIds(widgetBuilds);
|
|
19
|
+
}
|
|
20
|
+
function validateWidgetIds(widgetBuilds) {
|
|
21
|
+
const widgetIds = new Set();
|
|
22
|
+
for (const widgetBuild of widgetBuilds) {
|
|
23
|
+
const widgetConfigId = widgetBuild.widgetConfig.id;
|
|
24
|
+
if (widgetIds.has(widgetConfigId)) {
|
|
25
|
+
throw new Error(`Duplicate widget ID: ${widgetConfigId}. Each widget must have a unique ID.`);
|
|
26
|
+
}
|
|
27
|
+
widgetIds.add(widgetConfigId);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=validateWidgetSet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateWidgetSet.js","names":["validateWidgetSet","widgetBuilds","validateWidgetIds","widgetIds","Set","widgetBuild","widgetConfigId","widgetConfig","id","has","Error","add"],"sources":["validateWidgetSet.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 { WidgetBuildOutputs } from \"./getWidgetBuildOutputs.js\";\n\nexport function validateWidgetSet(widgetBuilds: WidgetBuildOutputs[]): void {\n validateWidgetIds(widgetBuilds);\n}\n\nfunction validateWidgetIds(widgetBuilds: WidgetBuildOutputs[]): void {\n const widgetIds = new Set<string>();\n for (const widgetBuild of widgetBuilds) {\n const widgetConfigId = widgetBuild.widgetConfig.id;\n if (widgetIds.has(widgetConfigId)) {\n throw new Error(\n `Duplicate widget ID: ${widgetConfigId}. Each widget must have a unique ID.`,\n );\n }\n widgetIds.add(widgetConfigId);\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA,OAAO,SAASA,iBAAiBA,CAACC,YAAkC,EAAQ;EAC1EC,iBAAiB,CAACD,YAAY,CAAC;AACjC;AAEA,SAASC,iBAAiBA,CAACD,YAAkC,EAAQ;EACnE,MAAME,SAAS,GAAG,IAAIC,GAAG,CAAS,CAAC;EACnC,KAAK,MAAMC,WAAW,IAAIJ,YAAY,EAAE;IACtC,MAAMK,cAAc,GAAGD,WAAW,CAACE,YAAY,CAACC,EAAE;IAClD,IAAIL,SAAS,CAACM,GAAG,CAACH,cAAc,CAAC,EAAE;MACjC,MAAM,IAAII,KAAK,CACb,wBAAwBJ,cAAc,sCACxC,CAAC;IACH;IACAH,SAAS,CAACQ,GAAG,CAACL,cAAc,CAAC;EAC/B;AACF","ignoreList":[]}
|
package/build/esm/client/app.js
CHANGED
|
@@ -14,16 +14,23 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { NonIdealState, Spinner, SpinnerSize } from "@blueprintjs/core";
|
|
17
|
+
import { NonIdealState, Pre, Spinner, SpinnerSize } from "@blueprintjs/core";
|
|
18
18
|
import React, { useEffect } from "react";
|
|
19
19
|
import { EntrypointIframe } from "./entrypointIframe.js";
|
|
20
20
|
const POLLING_INTERVAL = 250;
|
|
21
21
|
const REDIRECT_DELAY = 500;
|
|
22
|
+
class ResponseError extends Error {
|
|
23
|
+
constructor(message, response) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.response = response;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
22
28
|
export const App = () => {
|
|
23
29
|
const [entrypointPaths, setEntrypointPaths] = React.useState([]);
|
|
24
30
|
const [pageState, setPageState] = React.useState({
|
|
25
31
|
state: "loading"
|
|
26
32
|
});
|
|
33
|
+
const numAttempts = React.useRef(0);
|
|
27
34
|
|
|
28
35
|
// Load entrypoints values on mount
|
|
29
36
|
useEffect(() => {
|
|
@@ -33,11 +40,15 @@ export const App = () => {
|
|
|
33
40
|
// Poll the finish endpoint until it returns a success or error
|
|
34
41
|
useEffect(() => {
|
|
35
42
|
const poll = window.setInterval(() => {
|
|
36
|
-
void finish().then(result => {
|
|
43
|
+
void finish(numAttempts.current).then(result => {
|
|
37
44
|
if (result.status === "pending") {
|
|
45
|
+
numAttempts.current++;
|
|
38
46
|
return;
|
|
39
47
|
}
|
|
40
48
|
if (result.status === "error") {
|
|
49
|
+
if (result.response != null) {
|
|
50
|
+
throw new ResponseError(result.error, result.response);
|
|
51
|
+
}
|
|
41
52
|
throw new Error(result.error);
|
|
42
53
|
}
|
|
43
54
|
|
|
@@ -60,7 +71,8 @@ export const App = () => {
|
|
|
60
71
|
console.error("Failed to finish dev mode setup:", error);
|
|
61
72
|
setPageState({
|
|
62
73
|
state: "failed",
|
|
63
|
-
error: error instanceof Error ? error.message : undefined
|
|
74
|
+
error: error instanceof Error ? error.message : undefined,
|
|
75
|
+
response: error instanceof ResponseError ? error.response : undefined
|
|
64
76
|
});
|
|
65
77
|
});
|
|
66
78
|
}, POLLING_INTERVAL);
|
|
@@ -85,7 +97,11 @@ export const App = () => {
|
|
|
85
97
|
}), pageState.state === "failed" && /*#__PURE__*/React.createElement(NonIdealState, {
|
|
86
98
|
title: "Failed to start dev mode",
|
|
87
99
|
icon: "error",
|
|
88
|
-
description: pageState.
|
|
100
|
+
description: /*#__PURE__*/React.createElement(React.Fragment, null, pageState.response != null && /*#__PURE__*/React.createElement(Pre, {
|
|
101
|
+
className: "response-block"
|
|
102
|
+
}, pageState.response), /*#__PURE__*/React.createElement(Pre, {
|
|
103
|
+
className: "response-block"
|
|
104
|
+
}, pageState.error))
|
|
89
105
|
}), entrypointPaths.map(entrypointPath => /*#__PURE__*/React.createElement(EntrypointIframe, {
|
|
90
106
|
src: entrypointPath,
|
|
91
107
|
key: entrypointPath
|
|
@@ -94,7 +110,7 @@ export const App = () => {
|
|
|
94
110
|
function loadEntrypoints() {
|
|
95
111
|
return fetch("../entrypoints").then(res => res.json());
|
|
96
112
|
}
|
|
97
|
-
function finish() {
|
|
98
|
-
return fetch(
|
|
113
|
+
function finish(attempt) {
|
|
114
|
+
return fetch(`../finish?attempt=${attempt}`).then(res => res.json());
|
|
99
115
|
}
|
|
100
116
|
//# sourceMappingURL=app.js.map
|
|
@@ -1 +1 @@
|
|
|
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","
|
|
1
|
+
{"version":3,"file":"app.js","names":["NonIdealState","Pre","Spinner","SpinnerSize","React","useEffect","EntrypointIframe","POLLING_INTERVAL","REDIRECT_DELAY","ResponseError","Error","constructor","message","response","App","entrypointPaths","setEntrypointPaths","useState","pageState","setPageState","state","numAttempts","useRef","loadEntrypoints","then","poll","window","setInterval","finish","current","result","status","error","clearInterval","isRedirecting","redirectUrl","setTimeout","location","href","catch","console","undefined","createElement","className","title","icon","intent","description","size","SMALL","Fragment","map","entrypointPath","src","key","fetch","res","json","attempt"],"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, Pre, 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 response?: string;\n }\n | {\n state: \"success\";\n isRedirecting: boolean;\n };\n\nconst POLLING_INTERVAL = 250;\nconst REDIRECT_DELAY = 500;\n\nclass ResponseError extends Error {\n public readonly response: string;\n\n constructor(message: string, response: string) {\n super(message);\n this.response = response;\n }\n}\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 const numAttempts = React.useRef(0);\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(numAttempts.current)\n .then((result) => {\n if (result.status === \"pending\") {\n numAttempts.current++;\n return;\n }\n if (result.status === \"error\") {\n if (result.response != null) {\n throw new ResponseError(result.error, result.response);\n }\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 response: error instanceof ResponseError\n ? error.response\n : 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={\n <>\n {pageState.response != null && (\n <Pre className=\"response-block\">{pageState.response}</Pre>\n )}\n <Pre className=\"response-block\">{pageState.error}</Pre>\n </>\n }\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(attempt: number): Promise<\n | {\n status: \"success\";\n redirectUrl: string | null;\n }\n | {\n status: \"error\";\n error: string;\n response?: string;\n }\n | {\n status: \"pending\";\n }\n> {\n return fetch(`../finish?attempt=${attempt}`).then((res) => res.json());\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,GAAG,EAAEC,OAAO,EAAEC,WAAW,QAAQ,mBAAmB;AAC5E,OAAOC,KAAK,IAAIC,SAAS,QAAQ,OAAO;AACxC,SAASC,gBAAgB,QAAQ,uBAAuB;AAgBxD,MAAMC,gBAAgB,GAAG,GAAG;AAC5B,MAAMC,cAAc,GAAG,GAAG;AAE1B,MAAMC,aAAa,SAASC,KAAK,CAAC;EAGhCC,WAAWA,CAACC,OAAe,EAAEC,QAAgB,EAAE;IAC7C,KAAK,CAACD,OAAO,CAAC;IACd,IAAI,CAACC,QAAQ,GAAGA,QAAQ;EAC1B;AACF;AAEA,OAAO,MAAMC,GAAa,GAAGA,CAAA,KAAM;EACjC,MAAM,CAACC,eAAe,EAAEC,kBAAkB,CAAC,GAAGZ,KAAK,CAACa,QAAQ,CAAW,EAAE,CAAC;EAC1E,MAAM,CAACC,SAAS,EAAEC,YAAY,CAAC,GAAGf,KAAK,CAACa,QAAQ,CAAY;IAC1DG,KAAK,EAAE;EACT,CAAC,CAAC;EACF,MAAMC,WAAW,GAAGjB,KAAK,CAACkB,MAAM,CAAC,CAAC,CAAC;;EAEnC;EACAjB,SAAS,CAAC,MAAM;IACd,KAAKkB,eAAe,CAAC,CAAC,CAACC,IAAI,CAACR,kBAAkB,CAAC;EACjD,CAAC,EAAE,EAAE,CAAC;;EAEN;EACAX,SAAS,CAAC,MAAM;IACd,MAAMoB,IAAI,GAAGC,MAAM,CAACC,WAAW,CAAC,MAAM;MACpC,KAAKC,MAAM,CAACP,WAAW,CAACQ,OAAO,CAAC,CAC7BL,IAAI,CAAEM,MAAM,IAAK;QAChB,IAAIA,MAAM,CAACC,MAAM,KAAK,SAAS,EAAE;UAC/BV,WAAW,CAACQ,OAAO,EAAE;UACrB;QACF;QACA,IAAIC,MAAM,CAACC,MAAM,KAAK,OAAO,EAAE;UAC7B,IAAID,MAAM,CAACjB,QAAQ,IAAI,IAAI,EAAE;YAC3B,MAAM,IAAIJ,aAAa,CAACqB,MAAM,CAACE,KAAK,EAAEF,MAAM,CAACjB,QAAQ,CAAC;UACxD;UACA,MAAM,IAAIH,KAAK,CAACoB,MAAM,CAACE,KAAK,CAAC;QAC/B;;QAEA;QACAN,MAAM,CAACO,aAAa,CAACR,IAAI,CAAC;QAC1BN,YAAY,CAAC;UACXC,KAAK,EAAE,SAAS;UAChBc,aAAa,EAAEJ,MAAM,CAACK,WAAW,IAAI;QACvC,CAAC,CAAC;;QAEF;QACA,IAAIL,MAAM,CAACC,MAAM,KAAK,SAAS,IAAID,MAAM,CAACK,WAAW,IAAI,IAAI,EAAE;UAC7DC,UAAU,CAAC,MAAM;YACfV,MAAM,CAACW,QAAQ,CAACC,IAAI,GAAGR,MAAM,CAACK,WAAY;UAC5C,CAAC,EAAE3B,cAAc,CAAC;QACpB;MACF,CAAC,CAAC,CACD+B,KAAK,CAAEP,KAAc,IAAK;QACzBN,MAAM,CAACO,aAAa,CAACR,IAAI,CAAC;QAC1B;QACAe,OAAO,CAACR,KAAK,CAAC,kCAAkC,EAAEA,KAAK,CAAC;QACxDb,YAAY,CAAC;UACXC,KAAK,EAAE,QAAQ;UACfY,KAAK,EAAEA,KAAK,YAAYtB,KAAK,GAAGsB,KAAK,CAACpB,OAAO,GAAG6B,SAAS;UACzD5B,QAAQ,EAAEmB,KAAK,YAAYvB,aAAa,GACpCuB,KAAK,CAACnB,QAAQ,GACd4B;QACN,CAAC,CAAC;MACJ,CAAC,CAAC;IACN,CAAC,EAAElC,gBAAgB,CAAC;IACpB,OAAO,MAAMmB,MAAM,CAACO,aAAa,CAACR,IAAI,CAAC;EACzC,CAAC,EAAE,EAAE,CAAC;EAEN,oBACErB,KAAA,CAAAsC,aAAA;IAAKC,SAAS,EAAC;EAAM,GAClBzB,SAAS,CAACE,KAAK,KAAK,SAAS,iBAC5BhB,KAAA,CAAAsC,aAAA,CAAC1C,aAAa;IACZ4C,KAAK,EAAC,0CAAqC;IAC3CC,IAAI,eAAEzC,KAAA,CAAAsC,aAAA,CAACxC,OAAO;MAAC4C,MAAM,EAAC;IAAS,CAAE;EAAE,CACpC,CACF,EACA5B,SAAS,CAACE,KAAK,KAAK,SAAS,iBAC5BhB,KAAA,CAAAsC,aAAA,CAAC1C,aAAa;IACZ4C,KAAK,EAAC,kBAAkB;IACxBC,IAAI,EAAC,aAAa;IAClBE,WAAW,eACT3C,KAAA,CAAAsC,aAAA;MAAKC,SAAS,EAAC;IAAa,gBAC1BvC,KAAA,CAAAsC,aAAA,CAACxC,OAAO;MAAC4C,MAAM,EAAC,SAAS;MAACE,IAAI,EAAE7C,WAAW,CAAC8C;IAAM,CAAE,CAAC,EAAC,GAAG,EACxD/B,SAAS,CAACgB,aAAa,gBACpB9B,KAAA,CAAAsC,aAAA,eAAM,uBAAsB,CAAC,gBAC7BtC,KAAA,CAAAsC,aAAA,eAAM,uBAAsB,CAC7B;EACN,CACF,CACF,EACAxB,SAAS,CAACE,KAAK,KAAK,QAAQ,iBAC3BhB,KAAA,CAAAsC,aAAA,CAAC1C,aAAa;IACZ4C,KAAK,EAAC,0BAA0B;IAChCC,IAAI,EAAC,OAAO;IACZE,WAAW,eACT3C,KAAA,CAAAsC,aAAA,CAAAtC,KAAA,CAAA8C,QAAA,QACGhC,SAAS,CAACL,QAAQ,IAAI,IAAI,iBACzBT,KAAA,CAAAsC,aAAA,CAACzC,GAAG;MAAC0C,SAAS,EAAC;IAAgB,GAAEzB,SAAS,CAACL,QAAc,CAC1D,eACDT,KAAA,CAAAsC,aAAA,CAACzC,GAAG;MAAC0C,SAAS,EAAC;IAAgB,GAAEzB,SAAS,CAACc,KAAW,CACtD;EACH,CACF,CACF,EAEAjB,eAAe,CAACoC,GAAG,CAAEC,cAAc,iBAClChD,KAAA,CAAAsC,aAAA,CAACpC,gBAAgB;IAAC+C,GAAG,EAAED,cAAe;IAACE,GAAG,EAAEF;EAAe,CAAE,CAC9D,CACE,CAAC;AAEV,CAAC;AAED,SAAS7B,eAAeA,CAAA,EAAsB;EAC5C,OAAOgC,KAAK,CAAC,gBAAgB,CAAC,CAAC/B,IAAI,CAAEgC,GAAG,IAAKA,GAAG,CAACC,IAAI,CAAC,CAAC,CAAC;AAC1D;AAEA,SAAS7B,MAAMA,CAAC8B,OAAe,EAa7B;EACA,OAAOH,KAAK,CAAC,qBAAqBG,OAAO,EAAE,CAAC,CAAClC,IAAI,CAAEgC,GAAG,IAAKA,GAAG,CAACC,IAAI,CAAC,CAAC,CAAC;AACxE","ignoreList":[]}
|
|
@@ -46,7 +46,7 @@ describe("extractWidgetConfig", () => {
|
|
|
46
46
|
throw new Error(`Widget id "${config.id}" does not match allowed pattern (must be camelCase)`);
|
|
47
47
|
});
|
|
48
48
|
await expect(extractWidgetConfig("/path/to/config.ts", MOCK_SERVER)).rejects.toThrow(expect.objectContaining({
|
|
49
|
-
message: "
|
|
49
|
+
message: "Encountered error: 'Widget id \"Invalid-Id\" does not match allowed pattern (must be camelCase)' while loading widget config from /path/to/config.ts",
|
|
50
50
|
cause: expect.objectContaining({
|
|
51
51
|
message: `Widget id "Invalid-Id" does not match allowed pattern (must be camelCase)`
|
|
52
52
|
})
|
|
@@ -59,7 +59,7 @@ describe("extractWidgetConfig", () => {
|
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
await expect(extractWidgetConfig("/path/to/config.ts", MOCK_SERVER)).rejects.toThrow(expect.objectContaining({
|
|
62
|
-
message: "
|
|
62
|
+
message: "Encountered error: 'No default export found in /path/to/config.ts' while loading widget config from /path/to/config.ts",
|
|
63
63
|
cause: expect.objectContaining({
|
|
64
64
|
message: "No default export found in /path/to/config.ts"
|
|
65
65
|
})
|
|
@@ -67,7 +67,7 @@ describe("extractWidgetConfig", () => {
|
|
|
67
67
|
});
|
|
68
68
|
test("throws for invalid module path", async () => {
|
|
69
69
|
vi.mocked(MOCK_SERVER.ssrLoadModule).mockRejectedValue(new Error("Module loading failed"));
|
|
70
|
-
await expect(extractWidgetConfig("/invalid/path/config.ts", MOCK_SERVER)).rejects.toThrow("
|
|
70
|
+
await expect(extractWidgetConfig("/invalid/path/config.ts", MOCK_SERVER)).rejects.toThrow("Encountered error: 'Module loading failed' while loading widget config from /invalid/path/config.ts");
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
73
|
const MOCK_CONFIG = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractWidgetConfig.test.js","names":["beforeEach","describe","expect","test","vi","extractWidgetConfig","validateWidgetConfigModule","MOCK_SERVER","ssrLoadModule","fn","restoreAllMocks","mocked","mockResolvedValue","default","MOCK_CONFIG","validateSpy","spyOn","result","toEqual","toHaveBeenCalledWith","id","name","type","parameters","mockImplementation","config","Error","rejects","toThrow","objectContaining","message","cause","notDefault","mockRejectedValue","description","paramOne","displayName","paramTwo","events","updateParameters","parameterUpdateIds"],"sources":["extractWidgetConfig.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 { ViteDevServer } from \"vite\";\nimport { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport { extractWidgetConfig } from \"../extractWidgetConfig.js\";\nimport * as validateWidgetConfigModule from \"../validateWidgetConfig.js\";\n\nconst MOCK_SERVER = {\n ssrLoadModule: vi.fn(),\n} as unknown as ViteDevServer;\n\ndescribe(\"extractWidgetConfig\", () => {\n beforeEach(() => {\n vi.restoreAllMocks();\n });\n\n test(\"extracts valid widget configuration\", async () => {\n vi.mocked(MOCK_SERVER.ssrLoadModule).mockResolvedValue({\n default: MOCK_CONFIG,\n });\n\n const validateSpy = vi.spyOn(\n validateWidgetConfigModule,\n \"validateWidgetConfig\",\n );\n\n const result = await extractWidgetConfig(\"/path/to/config.ts\", MOCK_SERVER);\n expect(result).toEqual(MOCK_CONFIG);\n expect(validateSpy).toHaveBeenCalledWith(MOCK_CONFIG);\n });\n\n test(\"throws for invalid widget configuration\", async () => {\n const INVALID_CONFIG = {\n id: \"Invalid-Id\",\n name: \"Test Widget\",\n type: \"workshop\",\n parameters: {},\n };\n\n vi.mocked(MOCK_SERVER.ssrLoadModule).mockResolvedValue({\n default: INVALID_CONFIG,\n });\n\n vi.spyOn(validateWidgetConfigModule, \"validateWidgetConfig\")\n .mockImplementation(config => {\n throw new Error(\n `Widget id \"${config.id}\" does not match allowed pattern (must be camelCase)`,\n );\n });\n\n await expect(extractWidgetConfig(\"/path/to/config.ts\", MOCK_SERVER))\n .rejects.toThrow(\n expect.objectContaining({\n message:
|
|
1
|
+
{"version":3,"file":"extractWidgetConfig.test.js","names":["beforeEach","describe","expect","test","vi","extractWidgetConfig","validateWidgetConfigModule","MOCK_SERVER","ssrLoadModule","fn","restoreAllMocks","mocked","mockResolvedValue","default","MOCK_CONFIG","validateSpy","spyOn","result","toEqual","toHaveBeenCalledWith","id","name","type","parameters","mockImplementation","config","Error","rejects","toThrow","objectContaining","message","cause","notDefault","mockRejectedValue","description","paramOne","displayName","paramTwo","events","updateParameters","parameterUpdateIds"],"sources":["extractWidgetConfig.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 { ViteDevServer } from \"vite\";\nimport { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport { extractWidgetConfig } from \"../extractWidgetConfig.js\";\nimport * as validateWidgetConfigModule from \"../validateWidgetConfig.js\";\n\nconst MOCK_SERVER = {\n ssrLoadModule: vi.fn(),\n} as unknown as ViteDevServer;\n\ndescribe(\"extractWidgetConfig\", () => {\n beforeEach(() => {\n vi.restoreAllMocks();\n });\n\n test(\"extracts valid widget configuration\", async () => {\n vi.mocked(MOCK_SERVER.ssrLoadModule).mockResolvedValue({\n default: MOCK_CONFIG,\n });\n\n const validateSpy = vi.spyOn(\n validateWidgetConfigModule,\n \"validateWidgetConfig\",\n );\n\n const result = await extractWidgetConfig(\"/path/to/config.ts\", MOCK_SERVER);\n expect(result).toEqual(MOCK_CONFIG);\n expect(validateSpy).toHaveBeenCalledWith(MOCK_CONFIG);\n });\n\n test(\"throws for invalid widget configuration\", async () => {\n const INVALID_CONFIG = {\n id: \"Invalid-Id\",\n name: \"Test Widget\",\n type: \"workshop\",\n parameters: {},\n };\n\n vi.mocked(MOCK_SERVER.ssrLoadModule).mockResolvedValue({\n default: INVALID_CONFIG,\n });\n\n vi.spyOn(validateWidgetConfigModule, \"validateWidgetConfig\")\n .mockImplementation(config => {\n throw new Error(\n `Widget id \"${config.id}\" does not match allowed pattern (must be camelCase)`,\n );\n });\n\n await expect(extractWidgetConfig(\"/path/to/config.ts\", MOCK_SERVER))\n .rejects.toThrow(\n expect.objectContaining({\n message:\n \"Encountered error: 'Widget id \\\"Invalid-Id\\\" does not match allowed pattern (must be camelCase)' while loading widget config from /path/to/config.ts\",\n cause: expect.objectContaining({\n message:\n `Widget id \"Invalid-Id\" does not match allowed pattern (must be camelCase)`,\n }),\n }),\n );\n });\n\n test(\"throws for missing default export\", async () => {\n vi.mocked(MOCK_SERVER.ssrLoadModule).mockResolvedValue({\n notDefault: { id: \"test\" },\n });\n\n await expect(extractWidgetConfig(\"/path/to/config.ts\", MOCK_SERVER))\n .rejects.toThrow(\n expect.objectContaining({\n message:\n \"Encountered error: 'No default export found in /path/to/config.ts' while loading widget config from /path/to/config.ts\",\n cause: expect.objectContaining({\n message: \"No default export found in /path/to/config.ts\",\n }),\n }),\n );\n });\n\n test(\"throws for invalid module path\", async () => {\n vi.mocked(MOCK_SERVER.ssrLoadModule).mockRejectedValue(\n new Error(\"Module loading failed\"),\n );\n\n await expect(extractWidgetConfig(\"/invalid/path/config.ts\", MOCK_SERVER))\n .rejects.toThrow(\n \"Encountered error: 'Module loading failed' while loading widget config from /invalid/path/config.ts\",\n );\n });\n});\n\nconst MOCK_CONFIG = {\n id: \"testWidget\",\n name: \"Test Widget\",\n description: \"A test widget\",\n type: \"workshop\",\n parameters: {\n paramOne: {\n displayName: \"Parameter One\",\n type: \"string\",\n },\n paramTwo: {\n displayName: \"Parameter Two\",\n type: \"string\",\n },\n },\n events: {\n updateParameters: {\n displayName: \"Update Parameters\",\n parameterUpdateIds: [\"paramOne\", \"paramTwo\"],\n },\n },\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 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 { describe, expect, it } from "vitest";
|
|
18
|
+
import { standardizePathAndFileExtension } from "../standardizePathAndFileExtension.js";
|
|
19
|
+
describe("standardizePathAndFileExtension", () => {
|
|
20
|
+
describe("file extension standardization", () => {
|
|
21
|
+
it("should replace .ts extension with .js", () => {
|
|
22
|
+
expect(standardizePathAndFileExtension("/path/to/file.ts")).toBe("/path/to/file.js");
|
|
23
|
+
});
|
|
24
|
+
it("should replace .tsx extension with .js", () => {
|
|
25
|
+
expect(standardizePathAndFileExtension("/path/to/component.tsx")).toBe("/path/to/component.js");
|
|
26
|
+
});
|
|
27
|
+
it("should replace .jsx extension with .js", () => {
|
|
28
|
+
expect(standardizePathAndFileExtension("/path/to/component.jsx")).toBe("/path/to/component.js");
|
|
29
|
+
});
|
|
30
|
+
it("should keep .js extension as is", () => {
|
|
31
|
+
expect(standardizePathAndFileExtension("/path/to/file.js")).toBe("/path/to/file.js");
|
|
32
|
+
});
|
|
33
|
+
it("should append .js to config files", () => {
|
|
34
|
+
expect(standardizePathAndFileExtension("/path/to/widget.config")).toBe("/path/to/widget.config.js");
|
|
35
|
+
});
|
|
36
|
+
it("should handle files without extensions", () => {
|
|
37
|
+
expect(standardizePathAndFileExtension("/path/to/file")).toBe("/path/to/file");
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe("path normalization", () => {
|
|
41
|
+
it("should normalize Windows paths with backslashes to forward slashes", () => {
|
|
42
|
+
expect(standardizePathAndFileExtension("C:\\Users\\project\\src\\file.ts")).toBe("C:/Users/project/src/file.js");
|
|
43
|
+
});
|
|
44
|
+
it("should normalize Windows paths with mixed separators", () => {
|
|
45
|
+
expect(standardizePathAndFileExtension("C:\\Users/project\\src/file.tsx")).toBe("C:/Users/project/src/file.js");
|
|
46
|
+
});
|
|
47
|
+
it("should preserve paths that already use forward slashes", () => {
|
|
48
|
+
expect(standardizePathAndFileExtension("/Users/project/src/file.ts")).toBe("/Users/project/src/file.js");
|
|
49
|
+
});
|
|
50
|
+
it("should handle Windows config file paths", () => {
|
|
51
|
+
expect(standardizePathAndFileExtension("D:\\workspace\\widgets\\my-widget.config")).toBe("D:/workspace/widgets/my-widget.config.js");
|
|
52
|
+
});
|
|
53
|
+
it("should handle Windows paths without file extensions", () => {
|
|
54
|
+
expect(standardizePathAndFileExtension("C:\\Users\\project\\README")).toBe("C:/Users/project/README");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe("edge cases", () => {
|
|
58
|
+
it("should handle empty string", () => {
|
|
59
|
+
expect(standardizePathAndFileExtension("")).toBe("");
|
|
60
|
+
});
|
|
61
|
+
it("should handle paths with multiple dots", () => {
|
|
62
|
+
expect(standardizePathAndFileExtension("/path/to/file.test.ts")).toBe("/path/to/file.test.js");
|
|
63
|
+
});
|
|
64
|
+
it("should handle Windows paths with multiple dots", () => {
|
|
65
|
+
expect(standardizePathAndFileExtension("C:\\path\\to\\file.test.tsx")).toBe("C:/path/to/file.test.js");
|
|
66
|
+
});
|
|
67
|
+
it("should handle virtual paths with @fs prefix", () => {
|
|
68
|
+
expect(standardizePathAndFileExtension("/@fs/C:\\Users\\project\\src\\file.ts")).toBe("/@fs/C:/Users/project/src/file.js");
|
|
69
|
+
});
|
|
70
|
+
it("should handle paths with /src/ directory for Windows", () => {
|
|
71
|
+
const result = standardizePathAndFileExtension("C:\\projects\\my-app\\src\\components\\Widget.tsx");
|
|
72
|
+
expect(result).toBe("C:/projects/my-app/src/components/Widget.js");
|
|
73
|
+
expect(result.includes("/src/")).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=standardizePathAndFileExtension.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standardizePathAndFileExtension.test.js","names":["describe","expect","it","standardizePathAndFileExtension","toBe","result","includes"],"sources":["standardizePathAndFileExtension.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 { describe, expect, it } from \"vitest\";\nimport { standardizePathAndFileExtension } from \"../standardizePathAndFileExtension.js\";\n\ndescribe(\"standardizePathAndFileExtension\", () => {\n describe(\"file extension standardization\", () => {\n it(\"should replace .ts extension with .js\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/file.ts\")).toBe(\n \"/path/to/file.js\",\n );\n });\n\n it(\"should replace .tsx extension with .js\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/component.tsx\")).toBe(\n \"/path/to/component.js\",\n );\n });\n\n it(\"should replace .jsx extension with .js\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/component.jsx\")).toBe(\n \"/path/to/component.js\",\n );\n });\n\n it(\"should keep .js extension as is\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/file.js\")).toBe(\n \"/path/to/file.js\",\n );\n });\n\n it(\"should append .js to config files\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/widget.config\")).toBe(\n \"/path/to/widget.config.js\",\n );\n });\n\n it(\"should handle files without extensions\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/file\")).toBe(\n \"/path/to/file\",\n );\n });\n });\n\n describe(\"path normalization\", () => {\n it(\"should normalize Windows paths with backslashes to forward slashes\", () => {\n expect(\n standardizePathAndFileExtension(\"C:\\\\Users\\\\project\\\\src\\\\file.ts\"),\n ).toBe(\"C:/Users/project/src/file.js\");\n });\n\n it(\"should normalize Windows paths with mixed separators\", () => {\n expect(standardizePathAndFileExtension(\"C:\\\\Users/project\\\\src/file.tsx\"))\n .toBe(\"C:/Users/project/src/file.js\");\n });\n\n it(\"should preserve paths that already use forward slashes\", () => {\n expect(standardizePathAndFileExtension(\"/Users/project/src/file.ts\"))\n .toBe(\"/Users/project/src/file.js\");\n });\n\n it(\"should handle Windows config file paths\", () => {\n expect(\n standardizePathAndFileExtension(\n \"D:\\\\workspace\\\\widgets\\\\my-widget.config\",\n ),\n ).toBe(\"D:/workspace/widgets/my-widget.config.js\");\n });\n\n it(\"should handle Windows paths without file extensions\", () => {\n expect(standardizePathAndFileExtension(\"C:\\\\Users\\\\project\\\\README\"))\n .toBe(\"C:/Users/project/README\");\n });\n });\n\n describe(\"edge cases\", () => {\n it(\"should handle empty string\", () => {\n expect(standardizePathAndFileExtension(\"\")).toBe(\"\");\n });\n\n it(\"should handle paths with multiple dots\", () => {\n expect(standardizePathAndFileExtension(\"/path/to/file.test.ts\")).toBe(\n \"/path/to/file.test.js\",\n );\n });\n\n it(\"should handle Windows paths with multiple dots\", () => {\n expect(standardizePathAndFileExtension(\"C:\\\\path\\\\to\\\\file.test.tsx\"))\n .toBe(\"C:/path/to/file.test.js\");\n });\n\n it(\"should handle virtual paths with @fs prefix\", () => {\n expect(\n standardizePathAndFileExtension(\n \"/@fs/C:\\\\Users\\\\project\\\\src\\\\file.ts\",\n ),\n ).toBe(\"/@fs/C:/Users/project/src/file.js\");\n });\n\n it(\"should handle paths with /src/ directory for Windows\", () => {\n const windowsPath = \"C:\\\\projects\\\\my-app\\\\src\\\\components\\\\Widget.tsx\";\n const result = standardizePathAndFileExtension(windowsPath);\n expect(result).toBe(\"C:/projects/my-app/src/components/Widget.js\");\n expect(result.includes(\"/src/\")).toBe(true);\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -22,10 +22,13 @@ export async function extractWidgetConfig(moduleId, server) {
|
|
|
22
22
|
if (config == null) {
|
|
23
23
|
throw new Error(`No default export found in ${moduleId}`);
|
|
24
24
|
}
|
|
25
|
+
if (typeof config !== "object" || config["id"] == null && config["name"] == null) {
|
|
26
|
+
server.config.logger.warn(`Config object does not look like a widget config: ${JSON.stringify(config)}`);
|
|
27
|
+
}
|
|
25
28
|
validateWidgetConfig(config);
|
|
26
29
|
return config;
|
|
27
30
|
} catch (error) {
|
|
28
|
-
throw new Error(`
|
|
31
|
+
throw new Error(`Encountered error: '${error instanceof Error ? error.message : error}' while loading widget config from ${moduleId}`, {
|
|
29
32
|
cause: error
|
|
30
33
|
});
|
|
31
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractWidgetConfig.js","names":["validateWidgetConfig","extractWidgetConfig","moduleId","server","configModule","ssrLoadModule","config","default","Error","error","cause"],"sources":["extractWidgetConfig.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 { ViteDevServer } from \"vite\";\nimport { validateWidgetConfig } from \"./validateWidgetConfig.js\";\n\nexport async function extractWidgetConfig(\n moduleId: string,\n server: ViteDevServer,\n): Promise<WidgetConfig<ParameterConfig>> {\n try {\n const configModule = await server.ssrLoadModule(moduleId);\n const config = configModule.default;\n\n if (config == null) {\n throw new Error(`No default export found in ${moduleId}`);\n }\n\n validateWidgetConfig(config);\n return config as WidgetConfig<ParameterConfig>;\n } catch (error) {\n throw new Error(`
|
|
1
|
+
{"version":3,"file":"extractWidgetConfig.js","names":["validateWidgetConfig","extractWidgetConfig","moduleId","server","configModule","ssrLoadModule","config","default","Error","logger","warn","JSON","stringify","error","message","cause"],"sources":["extractWidgetConfig.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 { ViteDevServer } from \"vite\";\nimport { validateWidgetConfig } from \"./validateWidgetConfig.js\";\n\nexport async function extractWidgetConfig(\n moduleId: string,\n server: ViteDevServer,\n): Promise<WidgetConfig<ParameterConfig>> {\n try {\n const configModule = await server.ssrLoadModule(moduleId);\n const config = configModule.default;\n\n if (config == null) {\n throw new Error(`No default export found in ${moduleId}`);\n }\n\n if (\n typeof config !== \"object\"\n || (config[\"id\"] == null && config[\"name\"] == null)\n ) {\n server.config.logger.warn(\n `Config object does not look like a widget config: ${\n JSON.stringify(config)\n }`,\n );\n }\n\n validateWidgetConfig(config);\n return config as WidgetConfig<ParameterConfig>;\n } catch (error) {\n throw new Error(\n `Encountered error: '${(error instanceof Error\n ? error.message\n : error)}' while loading widget config from ${moduleId}`,\n { cause: error },\n );\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA,SAASA,oBAAoB,QAAQ,2BAA2B;AAEhE,OAAO,eAAeC,mBAAmBA,CACvCC,QAAgB,EAChBC,MAAqB,EACmB;EACxC,IAAI;IACF,MAAMC,YAAY,GAAG,MAAMD,MAAM,CAACE,aAAa,CAACH,QAAQ,CAAC;IACzD,MAAMI,MAAM,GAAGF,YAAY,CAACG,OAAO;IAEnC,IAAID,MAAM,IAAI,IAAI,EAAE;MAClB,MAAM,IAAIE,KAAK,CAAC,8BAA8BN,QAAQ,EAAE,CAAC;IAC3D;IAEA,IACE,OAAOI,MAAM,KAAK,QAAQ,IACtBA,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,IAAIA,MAAM,CAAC,MAAM,CAAC,IAAI,IAAK,EACnD;MACAH,MAAM,CAACG,MAAM,CAACG,MAAM,CAACC,IAAI,CACvB,qDACEC,IAAI,CAACC,SAAS,CAACN,MAAM,CAAC,EAE1B,CAAC;IACH;IAEAN,oBAAoB,CAACM,MAAM,CAAC;IAC5B,OAAOA,MAAM;EACf,CAAC,CAAC,OAAOO,KAAK,EAAE;IACd,MAAM,IAAIL,KAAK,CACb,uBAAwBK,KAAK,YAAYL,KAAK,GAC1CK,KAAK,CAACC,OAAO,GACbD,KAAK,sCAAuCX,QAAQ,EAAE,EAC1D;MAAEa,KAAK,EAAEF;IAAM,CACjB,CAAC;EACH;AACF","ignoreList":[]}
|
|
@@ -14,12 +14,21 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { CONFIG_FILE_SUFFIX } from "./constants.js";
|
|
18
|
+
|
|
17
19
|
/**
|
|
18
20
|
* Users may import `.js` files in their code, where the source file is actually a `.ts`, `.tsx`, or
|
|
19
21
|
* `.jsx` file on disk. This standardizes these file extension to `.js` so that we can match imports
|
|
20
|
-
* to source files.
|
|
22
|
+
* to source files. Additionally, extension-less imports may be used depending on the module
|
|
23
|
+
* resolution setting so we append `.js` to config file imports to standardize those as well.
|
|
24
|
+
*
|
|
25
|
+
* Additionally, replaces Windows-style backslashes with forward slashes for path consistency.
|
|
21
26
|
*/
|
|
22
|
-
export function
|
|
23
|
-
|
|
27
|
+
export function standardizePathAndFileExtension(file) {
|
|
28
|
+
const normalizedPath = file.replace(/\\/g, "/");
|
|
29
|
+
if (normalizedPath.endsWith(CONFIG_FILE_SUFFIX)) {
|
|
30
|
+
return normalizedPath + ".js";
|
|
31
|
+
}
|
|
32
|
+
return normalizedPath.replace(/\.[jt]sx?$/, ".js");
|
|
24
33
|
}
|
|
25
|
-
//# sourceMappingURL=
|
|
34
|
+
//# sourceMappingURL=standardizePathAndFileExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standardizePathAndFileExtension.js","names":["CONFIG_FILE_SUFFIX","standardizePathAndFileExtension","file","normalizedPath","replace","endsWith"],"sources":["standardizePathAndFileExtension.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 { CONFIG_FILE_SUFFIX } from \"./constants.js\";\n\n/**\n * Users may import `.js` files in their code, where the source file is actually a `.ts`, `.tsx`, or\n * `.jsx` file on disk. This standardizes these file extension to `.js` so that we can match imports\n * to source files. Additionally, extension-less imports may be used depending on the module\n * resolution setting so we append `.js` to config file imports to standardize those as well.\n *\n * Additionally, replaces Windows-style backslashes with forward slashes for path consistency.\n */\nexport function standardizePathAndFileExtension(file: string): string {\n const normalizedPath = file.replace(/\\\\/g, \"/\");\n if (normalizedPath.endsWith(CONFIG_FILE_SUFFIX)) {\n return normalizedPath + \".js\";\n }\n return normalizedPath.replace(/\\.[jt]sx?$/, \".js\");\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,kBAAkB,QAAQ,gBAAgB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,+BAA+BA,CAACC,IAAY,EAAU;EACpE,MAAMC,cAAc,GAAGD,IAAI,CAACE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;EAC/C,IAAID,cAAc,CAACE,QAAQ,CAACL,kBAAkB,CAAC,EAAE;IAC/C,OAAOG,cAAc,GAAG,KAAK;EAC/B;EACA,OAAOA,cAAc,CAACC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC;AACpD","ignoreList":[]}
|