@fluid-app/portal-sdk 0.1.369 → 0.1.371

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/{CardWidget-CqdJHxX0.cjs → CardWidget-BWwI1G0Z.cjs} +2 -2
  2. package/dist/{CardWidget-CqdJHxX0.cjs.map → CardWidget-BWwI1G0Z.cjs.map} +1 -1
  3. package/dist/{CardWidget-DCrXorb0.cjs → CardWidget-aJYbzWG9.cjs} +2 -2
  4. package/dist/{CardWidget-DdV1HDy0.mjs → CardWidget-cIc9cOG9.mjs} +2 -2
  5. package/dist/{CardWidget-DdV1HDy0.mjs.map → CardWidget-cIc9cOG9.mjs.map} +1 -1
  6. package/dist/{ContainerWidget-CYIOGpgy.cjs → ContainerWidget-C2LMzXVj.cjs} +3 -3
  7. package/dist/{ContainerWidget-CZTRim0A.cjs → ContainerWidget-bMMdFhLg.cjs} +2 -2
  8. package/dist/{ContainerWidget-CZTRim0A.cjs.map → ContainerWidget-bMMdFhLg.cjs.map} +1 -1
  9. package/dist/{ContainerWidget-BKaiiPlW.mjs → ContainerWidget-mSWihekF.mjs} +2 -2
  10. package/dist/{ContainerWidget-BKaiiPlW.mjs.map → ContainerWidget-mSWihekF.mjs.map} +1 -1
  11. package/dist/{EmbedWidget-B18Qzd0T.cjs → EmbedWidget-CFqodi8C.cjs} +2 -1
  12. package/dist/{EmbedWidget-CoZgo8aI.cjs → EmbedWidget-D1lbYjuL.cjs} +300 -3
  13. package/dist/EmbedWidget-D1lbYjuL.cjs.map +1 -0
  14. package/dist/{EmbedWidget-BJY7l4pI.mjs → EmbedWidget-p_Ybl0em.mjs} +300 -3
  15. package/dist/EmbedWidget-p_Ybl0em.mjs.map +1 -0
  16. package/dist/{FluidProvider-iStLA04k.cjs → FluidProvider-C6d1TUVm.cjs} +10 -12
  17. package/dist/{FluidProvider-iStLA04k.cjs.map → FluidProvider-C6d1TUVm.cjs.map} +1 -1
  18. package/dist/{FluidProvider-DIhrcma3.mjs → FluidProvider-C80gc4Yi.mjs} +10 -12
  19. package/dist/{FluidProvider-DIhrcma3.mjs.map → FluidProvider-C80gc4Yi.mjs.map} +1 -1
  20. package/dist/{LayoutWidget-xw1zY6cc.cjs → LayoutWidget-BqUbneWw.cjs} +2 -2
  21. package/dist/{LayoutWidget-xw1zY6cc.cjs.map → LayoutWidget-BqUbneWw.cjs.map} +1 -1
  22. package/dist/{LayoutWidget-VU6uFW3-.cjs → LayoutWidget-C1BzDeQI.cjs} +2 -2
  23. package/dist/{LayoutWidget-C0TbnxQW.mjs → LayoutWidget-D3qYKt9F.mjs} +2 -2
  24. package/dist/{LayoutWidget-C0TbnxQW.mjs.map → LayoutWidget-D3qYKt9F.mjs.map} +1 -1
  25. package/dist/{MessagingScreen-BFpKQppV.mjs → MessagingScreen-D3si8TPx.mjs} +7 -7
  26. package/dist/{MessagingScreen-BOAnKE3v.mjs → MessagingScreen-DKzYThAY.mjs} +2 -2
  27. package/dist/{MessagingScreen-BOAnKE3v.mjs.map → MessagingScreen-DKzYThAY.mjs.map} +1 -1
  28. package/dist/{MessagingScreen-y_A92ivV.cjs → MessagingScreen-DqxRu2x3.cjs} +2 -2
  29. package/dist/{MessagingScreen-y_A92ivV.cjs.map → MessagingScreen-DqxRu2x3.cjs.map} +1 -1
  30. package/dist/{MessagingScreen-C5Pejtlt.cjs → MessagingScreen-PZyO11S1.cjs} +7 -7
  31. package/dist/{OrdersScreen-BzibsZC0.mjs → OrdersScreen-B2htbQ2Q.mjs} +2 -2
  32. package/dist/{OrdersScreen-BzibsZC0.mjs.map → OrdersScreen-B2htbQ2Q.mjs.map} +1 -1
  33. package/dist/{OrdersScreen-BlYerRr0.cjs → OrdersScreen-BuX5aWgx.cjs} +7 -7
  34. package/dist/{OrdersScreen-wtdmNSwV.mjs → OrdersScreen-Cgjfo2Fs.mjs} +7 -7
  35. package/dist/{OrdersScreen-B_jWMXAy.cjs → OrdersScreen-CpNvxRDC.cjs} +2 -2
  36. package/dist/{OrdersScreen-B_jWMXAy.cjs.map → OrdersScreen-CpNvxRDC.cjs.map} +1 -1
  37. package/dist/{ProfileScreen-B5bNfcEX.mjs → ProfileScreen-BCwdwO_p.mjs} +3 -3
  38. package/dist/{ProfileScreen-B5bNfcEX.mjs.map → ProfileScreen-BCwdwO_p.mjs.map} +1 -1
  39. package/dist/{ProfileScreen-CUEECEVi.mjs → ProfileScreen-D7UA604p.mjs} +8 -8
  40. package/dist/{ProfileScreen-BF7Xp0EB.cjs → ProfileScreen-DlIXDIeu.cjs} +3 -3
  41. package/dist/{ProfileScreen-BF7Xp0EB.cjs.map → ProfileScreen-DlIXDIeu.cjs.map} +1 -1
  42. package/dist/{ProfileScreen-DXaE0EJ2.cjs → ProfileScreen-MypXufrO.cjs} +8 -8
  43. package/dist/{ScreenRenderer-CKu-Jc1I.mjs → ScreenRenderer-CcT_j-WQ.mjs} +1 -4
  44. package/dist/{ScreenRenderer-CKu-Jc1I.mjs.map → ScreenRenderer-CcT_j-WQ.mjs.map} +1 -1
  45. package/dist/{ScreenRenderer-CZTdJd2G.cjs → ScreenRenderer-Ce8MJPnR.cjs} +1 -4
  46. package/dist/{ScreenRenderer-CZTdJd2G.cjs.map → ScreenRenderer-Ce8MJPnR.cjs.map} +1 -1
  47. package/dist/{ShopScreen-CTdqSSs6.cjs → ShopScreen-29SZwMWF.cjs} +2 -2
  48. package/dist/{ShopScreen-CTdqSSs6.cjs.map → ShopScreen-29SZwMWF.cjs.map} +1 -1
  49. package/dist/{ShopScreen-CIXdmZvI.cjs → ShopScreen-BC9NDysQ.cjs} +7 -7
  50. package/dist/{ShopScreen-CUQtjHcp.mjs → ShopScreen-BKVNW6ya.mjs} +7 -7
  51. package/dist/{ShopScreen-ChWVG5vG.mjs → ShopScreen-CgN-6gic.mjs} +2 -2
  52. package/dist/{ShopScreen-ChWVG5vG.mjs.map → ShopScreen-CgN-6gic.mjs.map} +1 -1
  53. package/dist/{SubscriptionsScreen-CXrorIz1.mjs → SubscriptionsScreen-CPiLzWhm.mjs} +8 -8
  54. package/dist/{SubscriptionsScreen-C8Oc4iYz.cjs → SubscriptionsScreen-Dz6Y_1oD.cjs} +3 -3
  55. package/dist/{SubscriptionsScreen-C8Oc4iYz.cjs.map → SubscriptionsScreen-Dz6Y_1oD.cjs.map} +1 -1
  56. package/dist/{SubscriptionsScreen-CwH8QyDm.mjs → SubscriptionsScreen-M2WaVHH7.mjs} +3 -3
  57. package/dist/{SubscriptionsScreen-CwH8QyDm.mjs.map → SubscriptionsScreen-M2WaVHH7.mjs.map} +1 -1
  58. package/dist/{SubscriptionsScreen-_X2bwjKO.cjs → SubscriptionsScreen-dN42J-MR.cjs} +8 -8
  59. package/dist/{authoring-BlXhd4Sj.d.cts → authoring--rXPyZca.d.cts} +2 -2
  60. package/dist/{authoring-BlXhd4Sj.d.cts.map → authoring--rXPyZca.d.cts.map} +1 -1
  61. package/dist/{authoring-BMuHXNFy.d.mts → authoring-V0sXg_j4.d.mts} +2 -2
  62. package/dist/{authoring-BMuHXNFy.d.mts.map → authoring-V0sXg_j4.d.mts.map} +1 -1
  63. package/dist/index.cjs +23 -25
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.d.cts +19 -8
  66. package/dist/index.d.cts.map +1 -1
  67. package/dist/index.d.mts +19 -9
  68. package/dist/index.d.mts.map +1 -1
  69. package/dist/index.mjs +23 -25
  70. package/dist/index.mjs.map +1 -1
  71. package/dist/preview/preview-entry.cjs +7 -7
  72. package/dist/preview/preview-entry.d.cts +1 -1
  73. package/dist/preview/preview-entry.d.mts +1 -1
  74. package/dist/preview/preview-entry.mjs +7 -7
  75. package/dist/{use-portal-card-add-3ds-flow-DJoxmO7y.cjs → use-portal-card-add-3ds-flow-C0YUg213.cjs} +2 -2
  76. package/dist/{use-portal-card-add-3ds-flow-DJoxmO7y.cjs.map → use-portal-card-add-3ds-flow-C0YUg213.cjs.map} +1 -1
  77. package/dist/{use-portal-card-add-3ds-flow-CKkPV6zg.mjs → use-portal-card-add-3ds-flow-DKXraYw-.mjs} +2 -2
  78. package/dist/{use-portal-card-add-3ds-flow-CKkPV6zg.mjs.map → use-portal-card-add-3ds-flow-DKXraYw-.mjs.map} +1 -1
  79. package/dist/vite/builder-preview-entry.cjs +573 -0
  80. package/dist/vite/builder-preview-entry.cjs.map +1 -0
  81. package/dist/vite/builder-preview-entry.d.cts +11 -0
  82. package/dist/vite/builder-preview-entry.d.cts.map +1 -0
  83. package/dist/vite/builder-preview-entry.d.mts +11 -0
  84. package/dist/vite/builder-preview-entry.d.mts.map +1 -0
  85. package/dist/vite/builder-preview-entry.mjs +571 -0
  86. package/dist/vite/builder-preview-entry.mjs.map +1 -0
  87. package/dist/vite/index.cjs +16 -28
  88. package/dist/vite/index.cjs.map +1 -1
  89. package/dist/vite/index.d.cts.map +1 -1
  90. package/dist/vite/index.d.mts.map +1 -1
  91. package/dist/vite/index.mjs +16 -28
  92. package/dist/vite/index.mjs.map +1 -1
  93. package/dist/{widget-package-descriptor-BnVCE5Fz.d.cts → widget-package-descriptor-ByCz_FNh.d.cts} +177 -9
  94. package/dist/widget-package-descriptor-ByCz_FNh.d.cts.map +1 -0
  95. package/dist/{widget-package-descriptor-Dt8BkF85.d.mts → widget-package-descriptor-CPIPAdUO.d.mts} +177 -9
  96. package/dist/widget-package-descriptor-CPIPAdUO.d.mts.map +1 -0
  97. package/dist/widget-package-utils-BWn56ZFw.cjs +1553 -0
  98. package/dist/widget-package-utils-BWn56ZFw.cjs.map +1 -0
  99. package/dist/widget-package-utils-BdS0B0pI.mjs +1486 -0
  100. package/dist/widget-package-utils-BdS0B0pI.mjs.map +1 -0
  101. package/dist/widgets/authoring.d.cts +1 -1
  102. package/dist/widgets/authoring.d.mts +1 -1
  103. package/package.json +17 -21
  104. package/dist/EmbedWidget-BJY7l4pI.mjs.map +0 -1
  105. package/dist/EmbedWidget-CoZgo8aI.cjs.map +0 -1
  106. package/dist/widget-package-descriptor-BnVCE5Fz.d.cts.map +0 -1
  107. package/dist/widget-package-descriptor-Dt8BkF85.d.mts.map +0 -1
  108. package/dist/widget-package-utils-BkrdrNr7.mjs +0 -582
  109. package/dist/widget-package-utils-BkrdrNr7.mjs.map +0 -1
  110. package/dist/widget-package-utils-C00ijCm-.cjs +0 -650
  111. package/dist/widget-package-utils-C00ijCm-.cjs.map +0 -1
@@ -0,0 +1,1553 @@
1
+ const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-C6d1TUVm.cjs");
3
+ let react = require("react");
4
+ react = require_chunk.__toESM(react);
5
+ let react_jsx_runtime = require("react/jsx-runtime");
6
+ react_jsx_runtime = require_chunk.__toESM(react_jsx_runtime);
7
+ let react_dom = require("react-dom");
8
+ react_dom = require_chunk.__toESM(react_dom);
9
+ //#region src/config/env.ts
10
+ /**
11
+ * Read Vite environment variables at runtime.
12
+ *
13
+ * Isolated into its own module so that Jest tests can mock it
14
+ * (import.meta is a syntax-level construct that CJS/Jest cannot parse).
15
+ */
16
+ function getViteEnv(key) {
17
+ return {}.env?.[key];
18
+ }
19
+ //#endregion
20
+ //#region src/config/defaults.ts
21
+ /**
22
+ * Creates a FluidSDKConfig with sensible defaults.
23
+ *
24
+ * Default behavior:
25
+ * - baseUrl: reads from `VITE_API_URL` env var, falls back to `""` (same-origin relative)
26
+ * - Auth: relies on session cookies sent via `credentials: 'include'`
27
+ *
28
+ * Pass overrides to customize any field:
29
+ * ```ts
30
+ * const config = createDefaultFluidConfig({ baseUrl: "https://my-api.example.com" });
31
+ * ```
32
+ */
33
+ function createDefaultFluidConfig(overrides) {
34
+ return {
35
+ baseUrl: getViteEnv("VITE_API_URL") ?? "",
36
+ smartyEmbeddedKey: getViteEnv("NEXT_PUBLIC_SMARTY_EMBEDDED_KEY"),
37
+ googleMapsApiKey: getViteEnv("NEXT_PUBLIC_GOOGLE_MAPS_API_KEY"),
38
+ ...overrides
39
+ };
40
+ }
41
+ //#endregion
42
+ //#region ../../platform/widget-runtime/src/errors.ts
43
+ var WidgetRuntimeError = class extends Error {
44
+ code;
45
+ packageId;
46
+ version;
47
+ cause;
48
+ constructor(details) {
49
+ super(details.message);
50
+ this.name = "WidgetRuntimeError";
51
+ this.code = details.code;
52
+ this.packageId = details.packageId;
53
+ this.version = details.version;
54
+ this.cause = details.cause;
55
+ }
56
+ };
57
+ function toWidgetRuntimeError(error, fallback) {
58
+ if (error instanceof WidgetRuntimeError) return error;
59
+ return new WidgetRuntimeError({
60
+ ...fallback,
61
+ cause: error
62
+ });
63
+ }
64
+ //#endregion
65
+ //#region ../../platform/widget-runtime/src/fluid-widgets.ts
66
+ const globalMarker$1 = Symbol.for("fluid.widget-runtime.FluidWidgetsGlobal");
67
+ const cleanupRegistrationMarker = Symbol.for("fluid.widget-runtime.FluidWidgetsGlobal.cleanupRegistration");
68
+ function ensureFluidWidgetsGlobal() {
69
+ const existing = window.FluidWidgets;
70
+ if (isFluidWidgetsGlobal(existing)) return existing;
71
+ const registrationsByPackageKey = /* @__PURE__ */ new Map();
72
+ const subscribers = /* @__PURE__ */ new Set();
73
+ const fluidWidgets = {
74
+ [globalMarker$1]: true,
75
+ [cleanupRegistrationMarker](registration, previousRegistration) {
76
+ const registrationKey = createPackageRegistrationKey(registration.packageId, registration.version);
77
+ if (registrationsByPackageKey.get(registrationKey) !== registration) return;
78
+ if (previousRegistration === void 0) {
79
+ registrationsByPackageKey.delete(registrationKey);
80
+ return;
81
+ }
82
+ registrationsByPackageKey.set(registrationKey, previousRegistration);
83
+ },
84
+ registerPackage(registration) {
85
+ const registrationKey = createPackageRegistrationKey(registration.packageId, registration.version);
86
+ const previousRegistration = registrationsByPackageKey.get(registrationKey);
87
+ registrationsByPackageKey.set(registrationKey, registration);
88
+ notify({
89
+ kind: "register",
90
+ registration,
91
+ previousRegistration
92
+ });
93
+ },
94
+ getPackageRegistration(packageId, version) {
95
+ return registrationsByPackageKey.get(createPackageRegistrationKey(packageId, version));
96
+ },
97
+ getRegisteredWidgets() {
98
+ return Array.from(registrationsByPackageKey.values()).flatMap((registration) => registration.widgets.map((widget) => ({
99
+ ...widget,
100
+ packageId: registration.packageId,
101
+ version: registration.version
102
+ })));
103
+ },
104
+ getRegistry() {
105
+ const registry = /* @__PURE__ */ new Map();
106
+ for (const registration of registrationsByPackageKey.values()) for (const widget of registration.widgets) {
107
+ const globalWidget = {
108
+ ...widget,
109
+ packageId: registration.packageId,
110
+ version: registration.version
111
+ };
112
+ registry.set(createGlobalWidgetRegistryKey(registration.packageId, registration.version, widget.type), globalWidget);
113
+ }
114
+ return registry;
115
+ },
116
+ clear(packageId, version) {
117
+ if (packageId === void 0) {
118
+ registrationsByPackageKey.clear();
119
+ notify({ kind: "clear" });
120
+ return;
121
+ }
122
+ let cleared = false;
123
+ for (const [key, registration] of registrationsByPackageKey) if (registration.packageId === packageId && (version === void 0 || registration.version === version)) {
124
+ registrationsByPackageKey.delete(key);
125
+ cleared = true;
126
+ }
127
+ if (cleared) notify({
128
+ kind: "clear",
129
+ packageId,
130
+ version
131
+ });
132
+ },
133
+ subscribe(listener) {
134
+ subscribers.add(listener);
135
+ return () => {
136
+ subscribers.delete(listener);
137
+ };
138
+ }
139
+ };
140
+ window.FluidWidgets = fluidWidgets;
141
+ return fluidWidgets;
142
+ function notify(event) {
143
+ for (const subscriber of Array.from(subscribers)) subscriber(event);
144
+ }
145
+ }
146
+ function cleanupUnexpectedFluidWidgetsRegistration(registration, previousRegistration) {
147
+ const fluidWidgets = window.FluidWidgets;
148
+ if (!isFluidWidgetsGlobal(fluidWidgets)) return;
149
+ fluidWidgets[cleanupRegistrationMarker](registration, previousRegistration);
150
+ }
151
+ function isFluidWidgetsGlobal(value) {
152
+ return value !== void 0 && value[globalMarker$1] === true;
153
+ }
154
+ function createPackageRegistrationKey(packageId, version) {
155
+ return JSON.stringify([packageId, version]);
156
+ }
157
+ function createGlobalWidgetRegistryKey(packageId, version, type) {
158
+ return JSON.stringify([
159
+ packageId,
160
+ version,
161
+ type
162
+ ]);
163
+ }
164
+ const DEFAULT_WIDGET_CONTAINER = "block";
165
+ const widgetPackageTypes$1 = new Set([
166
+ "fluid",
167
+ "company",
168
+ "droplet",
169
+ "partner",
170
+ "internal"
171
+ ]);
172
+ const widgetContainers$1 = new Set([
173
+ "inline",
174
+ "block",
175
+ "card",
176
+ "fullscreen"
177
+ ]);
178
+ const widgetResizableValues$1 = new Set([
179
+ "horizontal",
180
+ "vertical",
181
+ "both"
182
+ ]);
183
+ function readNonEmptyString(value) {
184
+ return typeof value === "string" && value.length > 0 ? value : void 0;
185
+ }
186
+ function hasControlCharacter(value) {
187
+ for (let index = 0; index < value.length; index++) {
188
+ const code = value.charCodeAt(index);
189
+ if (code <= 31 || code >= 127 && code <= 159) return true;
190
+ }
191
+ return false;
192
+ }
193
+ function isWidgetPackageType(value) {
194
+ return typeof value === "string" && widgetPackageTypes$1.has(value);
195
+ }
196
+ function normalizeWidgetPackageType(value) {
197
+ return isWidgetPackageType(value) ? value : null;
198
+ }
199
+ function isWidgetRuntimeContainer(value) {
200
+ return typeof value === "string" && widgetContainers$1.has(value);
201
+ }
202
+ function normalizeWidgetRuntimeContainer(value) {
203
+ return isWidgetRuntimeContainer(value) ? value : DEFAULT_WIDGET_CONTAINER;
204
+ }
205
+ function isWidgetRuntimeResizableString(value) {
206
+ return typeof value === "string" && widgetResizableValues$1.has(value);
207
+ }
208
+ function normalizeWidgetRuntimeResizable(value) {
209
+ if (typeof value === "boolean") return value;
210
+ if (isWidgetRuntimeResizableString(value)) return value;
211
+ if (!isRecord$1(value)) return false;
212
+ const horizontal = value.horizontal === true;
213
+ const vertical = value.vertical === true;
214
+ if (horizontal && vertical) return "both";
215
+ if (horizontal) return "horizontal";
216
+ if (vertical) return "vertical";
217
+ return false;
218
+ }
219
+ function isRecord$1(value) {
220
+ return typeof value === "object" && value !== null && !Array.isArray(value);
221
+ }
222
+ //#endregion
223
+ //#region ../../platform/widget-runtime/src/validation.ts
224
+ const widgetPackageTypes = new Set([
225
+ "fluid",
226
+ "company",
227
+ "droplet",
228
+ "partner",
229
+ "internal"
230
+ ]);
231
+ const widgetContainers = new Set([
232
+ "inline",
233
+ "block",
234
+ "card",
235
+ "fullscreen"
236
+ ]);
237
+ const widgetResizableValues = new Set([
238
+ "horizontal",
239
+ "vertical",
240
+ "both"
241
+ ]);
242
+ function validateWidgetPackageDescriptor(descriptor) {
243
+ if (!isObjectRecord(descriptor)) throwInvalidDescriptor("Widget package descriptor must be an object");
244
+ if (descriptor.manifestVersion !== 1) throwInvalidDescriptor(`Unsupported widget package manifestVersion: ${String(descriptor.manifestVersion)}`, descriptor);
245
+ assertNonEmptyString(descriptor.packageId, "packageId", descriptor);
246
+ assertNonEmptyString(descriptor.version, "version", descriptor);
247
+ assertNonEmptyString(descriptor.remoteEntryUrl, "remoteEntryUrl", descriptor);
248
+ assertValidUrl(descriptor.remoteEntryUrl, "remoteEntryUrl", descriptor);
249
+ if (!widgetPackageTypes.has(descriptor.packageType)) throwInvalidDescriptor(`Unsupported widget packageType: ${String(descriptor.packageType)}`, descriptor);
250
+ if (!Array.isArray(descriptor.cssUrls)) throwInvalidDescriptor("Widget package cssUrls must be an array", descriptor);
251
+ for (const cssUrl of descriptor.cssUrls) {
252
+ if (typeof cssUrl !== "string" || cssUrl.length === 0) throwInvalidDescriptor("Widget package cssUrls must contain only non-empty strings", descriptor);
253
+ assertValidUrl(cssUrl, "cssUrls[]", descriptor);
254
+ }
255
+ if (!Array.isArray(descriptor.widgets) || descriptor.widgets.length === 0) throwInvalidDescriptor("Widget package widgets must be a non-empty array", descriptor);
256
+ const seenTypes = /* @__PURE__ */ new Set();
257
+ for (const widget of descriptor.widgets) {
258
+ validateWidgetDescriptor(widget, descriptor);
259
+ if (seenTypes.has(widget.type)) throwInvalidDescriptor(`Widget package descriptor contains duplicate widget type: ${widget.type}`, descriptor);
260
+ seenTypes.add(widget.type);
261
+ }
262
+ }
263
+ function validateWidgetPackageRegistration(registration, descriptor) {
264
+ if (!registration) throw new WidgetRuntimeError({
265
+ code: "REGISTRATION_MISSING",
266
+ message: `Remote widget package ${descriptor.packageId}@${descriptor.version} did not call window.FluidWidgets.registerPackage`,
267
+ packageId: descriptor.packageId,
268
+ version: descriptor.version
269
+ });
270
+ if (!isObjectRecord(registration)) throwInvalidRegistration("Widget package registration must be an object", descriptor);
271
+ if (registration.packageId !== descriptor.packageId) throw new WidgetRuntimeError({
272
+ code: "REGISTRATION_MISMATCH",
273
+ message: `Remote widget package registered packageId ${String(registration.packageId)} but descriptor expected ${descriptor.packageId}`,
274
+ packageId: descriptor.packageId,
275
+ version: descriptor.version
276
+ });
277
+ if (registration.version !== descriptor.version) throw new WidgetRuntimeError({
278
+ code: "REGISTRATION_MISMATCH",
279
+ message: `Remote widget package ${descriptor.packageId} registered version ${String(registration.version)} but descriptor expected ${descriptor.version}`,
280
+ packageId: descriptor.packageId,
281
+ version: descriptor.version
282
+ });
283
+ if (!Array.isArray(registration.widgets)) throwInvalidRegistration("Widget package registration widgets must be an array", descriptor);
284
+ const descriptorWidgetsByType = new Map(descriptor.widgets.map((widget) => [widget.type, widget]));
285
+ const registeredTypes = /* @__PURE__ */ new Set();
286
+ for (const widget of registration.widgets) {
287
+ validateRuntimeWidgetRegistration(widget, descriptor, descriptorWidgetsByType);
288
+ if (registeredTypes.has(widget.type)) throwInvalidRegistration(`Widget package registration contains duplicate widget type: ${widget.type}`, descriptor);
289
+ registeredTypes.add(widget.type);
290
+ }
291
+ for (const descriptorWidget of descriptor.widgets) if (!registeredTypes.has(descriptorWidget.type)) throwInvalidRegistration(`Widget package registration is missing widget type: ${descriptorWidget.type}`, descriptor);
292
+ }
293
+ function validateWidgetDescriptor(widget, descriptor) {
294
+ if (!isObjectRecord(widget)) throwInvalidDescriptor("Widget descriptor must be an object", descriptor);
295
+ assertNonEmptyString(widget.type, "widgets[].type", descriptor);
296
+ assertNonEmptyString(widget.name, "widgets[].name", descriptor);
297
+ assertNonEmptyString(widget.displayName, "widgets[].displayName", descriptor);
298
+ assertNonEmptyString(widget.description, "widgets[].description", descriptor);
299
+ assertNonEmptyString(widget.icon, "widgets[].icon", descriptor);
300
+ assertNonEmptyString(widget.category, "widgets[].category", descriptor);
301
+ assertNonEmptyString(widget.minSdkVersion, "widgets[].minSdkVersion", descriptor);
302
+ if (!isObjectRecord(widget.propertySchema)) throwInvalidDescriptor("Widget propertySchema must be an object", descriptor);
303
+ validatePropertySchemaWidgetType(widget.propertySchema, widget.type, descriptor, "INVALID_DESCRIPTOR");
304
+ if (!isObjectRecord(widget.defaultProps)) throwInvalidDescriptor("Widget defaultProps must be an object", descriptor);
305
+ if (!widgetContainers.has(widget.container)) throwInvalidDescriptor(`Unsupported widget container: ${String(widget.container)}`, descriptor);
306
+ validateResizable(widget.resizable, descriptor);
307
+ }
308
+ function validateRuntimeWidgetRegistration(widget, descriptor, descriptorWidgetsByType) {
309
+ if (!isObjectRecord(widget)) throwInvalidRegistration("Registered widget must be an object", descriptor);
310
+ assertNonEmptyString(widget.type, "registered widgets[].type", descriptor);
311
+ const descriptorWidget = descriptorWidgetsByType.get(widget.type);
312
+ if (!descriptorWidget) throwInvalidRegistration(`Widget package registration contains unknown widget type: ${widget.type}`, descriptor);
313
+ if (!isWidgetComponent(widget.component)) throwInvalidRegistration(`Registered widget ${widget.type} must include a React component`, descriptor);
314
+ if (!isObjectRecord(widget.propertySchema)) throwInvalidRegistration(`Registered widget ${widget.type} propertySchema must be an object`, descriptor);
315
+ validatePropertySchemaWidgetType(widget.propertySchema, widget.type, descriptor, "INVALID_REGISTRATION");
316
+ if (!isObjectRecord(widget.defaultProps)) throwInvalidRegistration(`Registered widget ${widget.type} defaultProps must be an object`, descriptor);
317
+ validateOptionalRuntimeMetadataStrings(widget, descriptor);
318
+ if (widget.container !== void 0 && !widgetContainers.has(widget.container)) throwInvalidRegistration(`Registered widget ${widget.type} has unsupported container: ${String(widget.container)}`, descriptor);
319
+ if (widget.resizable !== void 0) validateResizable(widget.resizable, descriptor, "INVALID_REGISTRATION");
320
+ validatePropertySchemaWidgetType(descriptorWidget.propertySchema, widget.type, descriptor, "INVALID_DESCRIPTOR");
321
+ }
322
+ function validateOptionalRuntimeMetadataStrings(widget, descriptor) {
323
+ for (const field of [
324
+ "name",
325
+ "displayName",
326
+ "description",
327
+ "icon",
328
+ "category",
329
+ "minSdkVersion"
330
+ ]) {
331
+ const value = widget[field];
332
+ if (value === void 0) continue;
333
+ if (typeof value !== "string" || value.length === 0) throwInvalidRegistration(`Registered widget ${widget.type} ${field} must be a non-empty string when present`, descriptor);
334
+ }
335
+ }
336
+ function validatePropertySchemaWidgetType(propertySchema, widgetType, descriptor, code) {
337
+ if (propertySchema.widgetType !== void 0 && propertySchema.widgetType !== widgetType) throwValidationError(code, `Widget type ${widgetType} must match propertySchema.widgetType ${propertySchema.widgetType}`, descriptor);
338
+ }
339
+ function validateResizable(resizable, descriptor, code = "INVALID_DESCRIPTOR") {
340
+ if (!(typeof resizable === "boolean" || typeof resizable === "string" && widgetResizableValues.has(resizable))) throwValidationError(code, `Unsupported widget resizable value: ${String(resizable)}`, descriptor);
341
+ }
342
+ function throwValidationError(code, message, descriptor) {
343
+ if (code === "INVALID_REGISTRATION") throwInvalidRegistration(message, descriptor);
344
+ throwInvalidDescriptor(message, descriptor);
345
+ }
346
+ function assertNonEmptyString(value, field, descriptor) {
347
+ if (typeof value !== "string" || value.length === 0) throwInvalidDescriptor(`Widget package ${field} must be a non-empty string`, descriptor);
348
+ }
349
+ function assertValidUrl(url, field, descriptor) {
350
+ if (url.trim() !== url || containsUnsafeUrlCharacter(url) || hasAmbiguousHttpScheme$1(url)) throwInvalidDescriptor(`Widget package ${field} contains invalid URL: ${url}`, descriptor);
351
+ if (/^[a-zA-Z][a-zA-Z\d+.-]*:/.exec(url)) {
352
+ let parsedUrl;
353
+ try {
354
+ parsedUrl = new URL(url);
355
+ } catch {
356
+ throwInvalidDescriptor(`Widget package ${field} contains invalid URL: ${url}`, descriptor);
357
+ }
358
+ if (parsedUrl.protocol !== "https:" && !isTrustedLocalHttpUrl(parsedUrl, url)) throwInvalidDescriptor(`Widget package ${field} must be an https absolute URL, a trusted local http URL, or a relative URL: ${url}`, descriptor);
359
+ return;
360
+ }
361
+ if (url.slice(0, 2) === "//") throwInvalidDescriptor(`Widget package ${field} must be an https absolute URL, a trusted local http URL, or a relative URL: ${url}`, descriptor);
362
+ try {
363
+ new URL(url, getValidationBaseUrl());
364
+ } catch {
365
+ throwInvalidDescriptor(`Widget package ${field} contains invalid URL: ${url}`, descriptor);
366
+ }
367
+ }
368
+ function isTrustedLocalHttpUrl(url, rawUrl) {
369
+ if (url.protocol !== "http:") return false;
370
+ const hostname = extractRawHostname(rawUrl).toLowerCase();
371
+ return hostname === "localhost" || hostname === "[::1]" || hostname === "::1" || isLoopbackIpv4Hostname(hostname);
372
+ }
373
+ function extractRawHostname(rawUrl) {
374
+ const authorityStart = rawUrl.indexOf("://") + 3;
375
+ const authorityEnd = findAuthorityEnd(rawUrl, authorityStart);
376
+ const authority = rawUrl.slice(authorityStart, authorityEnd);
377
+ const hostAndPort = authority.slice(authority.lastIndexOf("@") + 1);
378
+ if (hostAndPort.charAt(0) === "[") {
379
+ const bracketEnd = hostAndPort.indexOf("]");
380
+ return bracketEnd === -1 ? hostAndPort : hostAndPort.slice(0, bracketEnd + 1);
381
+ }
382
+ const portStart = hostAndPort.indexOf(":");
383
+ return portStart === -1 ? hostAndPort : hostAndPort.slice(0, portStart);
384
+ }
385
+ function findAuthorityEnd(rawUrl, authorityStart) {
386
+ let authorityEnd = rawUrl.length;
387
+ for (const delimiter of [
388
+ "/",
389
+ "?",
390
+ "#"
391
+ ]) {
392
+ const delimiterIndex = rawUrl.indexOf(delimiter, authorityStart);
393
+ if (delimiterIndex !== -1 && delimiterIndex < authorityEnd) authorityEnd = delimiterIndex;
394
+ }
395
+ return authorityEnd;
396
+ }
397
+ function isLoopbackIpv4Hostname(hostname) {
398
+ const octets = hostname.split(".");
399
+ if (octets.length !== 4 || octets[0] !== "127") return false;
400
+ return octets.every(isBoundedIpv4Octet);
401
+ }
402
+ function isBoundedIpv4Octet(octet) {
403
+ if (!/^\d{1,3}$/.test(octet)) return false;
404
+ if (octet.length > 1 && octet.charAt(0) === "0") return false;
405
+ const value = Number(octet);
406
+ return value >= 0 && value <= 255;
407
+ }
408
+ function containsUnsafeUrlCharacter(url) {
409
+ return hasControlCharacter(url) || url.includes("\\");
410
+ }
411
+ function hasAmbiguousHttpScheme$1(url) {
412
+ return /^https?:(?!\/\/)/i.test(url);
413
+ }
414
+ function getValidationBaseUrl() {
415
+ if (typeof window === "undefined") return "http://localhost";
416
+ return window.location.href;
417
+ }
418
+ function throwInvalidDescriptor(message, descriptor) {
419
+ throw new WidgetRuntimeError({
420
+ code: "INVALID_DESCRIPTOR",
421
+ message,
422
+ packageId: descriptor?.packageId,
423
+ version: descriptor?.version
424
+ });
425
+ }
426
+ function throwInvalidRegistration(message, descriptor) {
427
+ throw new WidgetRuntimeError({
428
+ code: "INVALID_REGISTRATION",
429
+ message,
430
+ packageId: descriptor.packageId,
431
+ version: descriptor.version
432
+ });
433
+ }
434
+ function isObjectRecord(value) {
435
+ return typeof value === "object" && value !== null && !Array.isArray(value);
436
+ }
437
+ function isWidgetComponent(value) {
438
+ if (typeof value === "function") return true;
439
+ return isObjectRecord(value) && typeof value["$$typeof"] === "symbol";
440
+ }
441
+ //#endregion
442
+ //#region ../../platform/widget-runtime/src/loader.ts
443
+ const defaultTimeoutMs = 15e3;
444
+ /**
445
+ * Shared remote script queue for the page.
446
+ *
447
+ * Classic remote scripts register through the shared `window.FluidWidgets`
448
+ * callback, so the loader intentionally appends only one remote entry script at
449
+ * a time across all loader instances. Each queued load waits for the previous
450
+ * load to settle, even when the previous load fails, which keeps registration
451
+ * attribution deterministic and prevents overlapping classic-script remotes
452
+ * from racing their global registrations.
453
+ */
454
+ let remoteScriptLoadQueue;
455
+ const pendingRemoteRegistrationsByPackageKey = /* @__PURE__ */ new Map();
456
+ function createWidgetRuntimeLoader(options = {}) {
457
+ const timeoutMs = options.timeoutMs ?? defaultTimeoutMs;
458
+ const fluidWidgets = ensureFluidWidgetsGlobal();
459
+ const packagesByKey = /* @__PURE__ */ new Map();
460
+ const pendingPackagesByKey = /* @__PURE__ */ new Map();
461
+ const packageGenerationsByKey = /* @__PURE__ */ new Map();
462
+ const cssByKey = /* @__PURE__ */ new Map();
463
+ const widgetsByKey = /* @__PURE__ */ new Map();
464
+ let isApplyingLocalGlobalClear = false;
465
+ fluidWidgets.subscribe((event) => {
466
+ if (isApplyingLocalGlobalClear || event.kind !== "clear") return;
467
+ if (event.packageId === void 0) {
468
+ invalidateCacheKeys(new Set([...packagesByKey.keys(), ...pendingPackagesByKey.keys()]));
469
+ return;
470
+ }
471
+ invalidateCacheKeys(collectMatchingCacheKeys(event.packageId, event.version));
472
+ });
473
+ async function loadPackage(descriptor) {
474
+ try {
475
+ validateWidgetPackageDescriptor(descriptor);
476
+ const cacheKey = createPackageCacheKey(descriptor.packageId, descriptor.version);
477
+ const cachedPackage = packagesByKey.get(cacheKey);
478
+ if (cachedPackage) return createSuccess(cachedPackage);
479
+ const pendingPackage = pendingPackagesByKey.get(cacheKey);
480
+ if (pendingPackage) return await pendingPackage.promise;
481
+ const globalRegistration = fluidWidgets.getPackageRegistration(descriptor.packageId, descriptor.version);
482
+ if (globalRegistration) return createSuccess(cachePreRegisteredPackage(descriptor, cacheKey, createCssLoadRef(cacheKey, getPackageGeneration(cacheKey)), globalRegistration));
483
+ const generation = getPackageGeneration(cacheKey);
484
+ const pendingLoad = {
485
+ cacheKey,
486
+ cssLoadRef: createCssLoadRef(cacheKey, generation),
487
+ generation,
488
+ packageId: descriptor.packageId,
489
+ remoteEntryUrlKey: normalizeAssetUrl(descriptor.remoteEntryUrl, descriptor),
490
+ version: descriptor.version
491
+ };
492
+ addPendingRemoteRegistration(pendingLoad);
493
+ const promise = loadPackageUncached(descriptor, pendingLoad);
494
+ const pendingPackageEntry = {
495
+ load: pendingLoad,
496
+ promise
497
+ };
498
+ promise.then(() => {
499
+ removePendingRemoteRegistration(pendingLoad);
500
+ if (pendingPackagesByKey.get(cacheKey) === pendingPackageEntry) pendingPackagesByKey.delete(cacheKey);
501
+ }, () => {
502
+ removePendingRemoteRegistration(pendingLoad);
503
+ if (pendingPackagesByKey.get(cacheKey) === pendingPackageEntry) pendingPackagesByKey.delete(cacheKey);
504
+ });
505
+ pendingPackagesByKey.set(cacheKey, pendingPackageEntry);
506
+ return await pendingPackageEntry.promise;
507
+ } catch (error) {
508
+ const descriptorIdentity = getDescriptorIdentity(descriptor);
509
+ const runtimeError = toWidgetRuntimeError(error, {
510
+ code: "SCRIPT_LOAD_FAILED",
511
+ message: "Failed to load widget package",
512
+ packageId: descriptorIdentity.packageId,
513
+ version: descriptorIdentity.version
514
+ });
515
+ if (options.throwOnError === true) throw runtimeError;
516
+ return {
517
+ ok: false,
518
+ packageId: descriptorIdentity.packageId ?? "",
519
+ version: descriptorIdentity.version ?? "",
520
+ error: runtimeError
521
+ };
522
+ }
523
+ }
524
+ async function loadPackageUncached(descriptor, pendingLoad) {
525
+ let scriptElement;
526
+ try {
527
+ installCssUrls(descriptor, pendingLoad.cssLoadRef);
528
+ const scriptLoadResult = await loadRemoteEntryScript(descriptor, timeoutMs, options.cacheBust, () => {
529
+ throwIfStalePackageLoad(pendingLoad);
530
+ }, () => isFreshPackageLoad(pendingLoad), pendingLoad.remoteEntryUrlKey);
531
+ scriptElement = scriptLoadResult.scriptElement;
532
+ throwIfStalePackageLoad(pendingLoad);
533
+ const registration = fluidWidgets.getPackageRegistration(descriptor.packageId, descriptor.version) ?? scriptLoadResult.registration;
534
+ const cached = cachePackageRegistrationWithRemoteCleanup(descriptor, pendingLoad.cacheKey, pendingLoad.cssLoadRef, registration, scriptLoadResult, scriptElement);
535
+ throwIfStalePackageLoad(pendingLoad);
536
+ return createSuccess(cached);
537
+ } catch (error) {
538
+ scriptElement?.remove();
539
+ removeCssForLoad(pendingLoad.cssLoadRef);
540
+ throw error;
541
+ }
542
+ }
543
+ async function loadPackages(descriptors) {
544
+ return await Promise.all(descriptors.map(loadPackage));
545
+ }
546
+ function getRegisteredWidgets() {
547
+ return Array.from(widgetsByKey.values());
548
+ }
549
+ function getRegistry() {
550
+ return new Map(widgetsByKey);
551
+ }
552
+ function cachePreRegisteredPackage(descriptor, cacheKey, cssLoadRef, registration) {
553
+ try {
554
+ installCssUrls(descriptor, cssLoadRef);
555
+ return cachePackageRegistration(descriptor, cacheKey, cssLoadRef, registration);
556
+ } catch (error) {
557
+ removeCssForLoad(cssLoadRef);
558
+ throw error;
559
+ }
560
+ }
561
+ function cachePackageRegistrationWithRemoteCleanup(descriptor, cacheKey, cssLoadRef, registration, scriptLoadResult, scriptElement) {
562
+ try {
563
+ return cachePackageRegistration(descriptor, cacheKey, cssLoadRef, registration, scriptElement);
564
+ } catch (error) {
565
+ if (scriptLoadResult.registration !== void 0 && registration === scriptLoadResult.registration) cleanupUnexpectedFluidWidgetsRegistration(scriptLoadResult.registration, scriptLoadResult.previousRegistration);
566
+ throw error;
567
+ }
568
+ }
569
+ function cachePackageRegistration(descriptor, cacheKey, cssLoadRef, registration, scriptElement) {
570
+ validateWidgetPackageRegistration(registration, descriptor);
571
+ const widgets = mergeRegisteredWidgets(descriptor, registration);
572
+ const cached = {
573
+ cacheKey,
574
+ cssLoadRef,
575
+ packageId: descriptor.packageId,
576
+ version: descriptor.version,
577
+ scriptElement,
578
+ widgets
579
+ };
580
+ packagesByKey.set(cacheKey, cached);
581
+ for (const widget of widgets) widgetsByKey.set(createWidgetRegistryKey(widget.packageId, widget.version, widget.type), widget);
582
+ return cached;
583
+ }
584
+ function invalidatePackage(packageId, version) {
585
+ isApplyingLocalGlobalClear = true;
586
+ try {
587
+ fluidWidgets.clear(packageId, version);
588
+ } finally {
589
+ isApplyingLocalGlobalClear = false;
590
+ }
591
+ invalidateCacheKeys(collectMatchingCacheKeys(packageId, version));
592
+ }
593
+ function clear() {
594
+ isApplyingLocalGlobalClear = true;
595
+ try {
596
+ fluidWidgets.clear();
597
+ } finally {
598
+ isApplyingLocalGlobalClear = false;
599
+ }
600
+ invalidateCacheKeys(new Set([...packagesByKey.keys(), ...pendingPackagesByKey.keys()]));
601
+ }
602
+ function collectMatchingCacheKeys(packageId, version) {
603
+ const cacheKeys = /* @__PURE__ */ new Set();
604
+ for (const cachedPackage of packagesByKey.values()) if (matchesPackage(cachedPackage, packageId, version)) cacheKeys.add(cachedPackage.cacheKey);
605
+ for (const pendingPackage of pendingPackagesByKey.values()) if (matchesPackage(pendingPackage.load, packageId, version)) cacheKeys.add(pendingPackage.load.cacheKey);
606
+ return cacheKeys;
607
+ }
608
+ function invalidateCacheKeys(cacheKeys) {
609
+ for (const cacheKey of cacheKeys) invalidatePackageCacheKey(cacheKey);
610
+ }
611
+ function installCssUrls(descriptor, cssLoadRef) {
612
+ const normalizedCssUrls = descriptor.cssUrls.map((cssUrl) => ({ key: normalizeAssetUrl(cssUrl, descriptor) }));
613
+ const keys = [];
614
+ for (const { key } of normalizedCssUrls) {
615
+ const existing = cssByKey.get(key);
616
+ if (existing) {
617
+ existing.packageRefs.add(cssLoadRef);
618
+ keys.push(key);
619
+ continue;
620
+ }
621
+ const linkElement = document.createElement("link");
622
+ linkElement.rel = "stylesheet";
623
+ linkElement.href = key;
624
+ linkElement.dataset.fluidWidgetRuntimeCss = "true";
625
+ linkElement.dataset.fluidWidgetRuntimeCssKey = key;
626
+ document.head.appendChild(linkElement);
627
+ cssByKey.set(key, {
628
+ key,
629
+ element: linkElement,
630
+ packageRefs: new Set([cssLoadRef])
631
+ });
632
+ keys.push(key);
633
+ }
634
+ return keys;
635
+ }
636
+ function invalidatePackageCacheKey(cacheKey) {
637
+ bumpPackageGeneration(cacheKey);
638
+ const pendingPackage = pendingPackagesByKey.get(cacheKey);
639
+ if (pendingPackage) {
640
+ removeCssForLoad(pendingPackage.load.cssLoadRef);
641
+ removePendingRemoteRegistration(pendingPackage.load);
642
+ pendingPackagesByKey.delete(cacheKey);
643
+ }
644
+ removePackage(cacheKey);
645
+ }
646
+ function removePackage(cacheKey) {
647
+ const cachedPackage = packagesByKey.get(cacheKey);
648
+ if (!cachedPackage) return;
649
+ cachedPackage.scriptElement?.remove();
650
+ for (const widget of cachedPackage.widgets) widgetsByKey.delete(createWidgetRegistryKey(widget.packageId, widget.version, widget.type));
651
+ removeCssForLoad(cachedPackage.cssLoadRef);
652
+ packagesByKey.delete(cacheKey);
653
+ }
654
+ function removeCssForLoad(cssLoadRef) {
655
+ for (const entry of Array.from(cssByKey.values())) {
656
+ entry.packageRefs.delete(cssLoadRef);
657
+ if (entry.packageRefs.size === 0) {
658
+ entry.element.remove();
659
+ cssByKey.delete(entry.key);
660
+ }
661
+ }
662
+ }
663
+ function getPackageGeneration(cacheKey) {
664
+ return packageGenerationsByKey.get(cacheKey) ?? 0;
665
+ }
666
+ function bumpPackageGeneration(cacheKey) {
667
+ packageGenerationsByKey.set(cacheKey, getPackageGeneration(cacheKey) + 1);
668
+ }
669
+ function isFreshPackageLoad(pendingLoad) {
670
+ return getPackageGeneration(pendingLoad.cacheKey) === pendingLoad.generation;
671
+ }
672
+ function throwIfStalePackageLoad(pendingLoad) {
673
+ if (isFreshPackageLoad(pendingLoad)) return;
674
+ throw new WidgetRuntimeError({
675
+ code: "SCRIPT_LOAD_FAILED",
676
+ message: `Widget package load ${pendingLoad.packageId}@${pendingLoad.version} was invalidated before it completed`,
677
+ packageId: pendingLoad.packageId,
678
+ version: pendingLoad.version
679
+ });
680
+ }
681
+ function matchesPackage(cachedPackage, packageId, version) {
682
+ if (cachedPackage.packageId !== packageId) return false;
683
+ return version === void 0 || cachedPackage.version === version;
684
+ }
685
+ return {
686
+ loadPackage,
687
+ loadPackages,
688
+ getRegisteredWidgets,
689
+ getRegistry,
690
+ invalidatePackage,
691
+ clear
692
+ };
693
+ }
694
+ function mergeRegisteredWidgets(descriptor, registration) {
695
+ const registrationWidgetsByType = new Map(registration.widgets.map((widget) => [widget.type, widget]));
696
+ return descriptor.widgets.map((descriptorWidget) => {
697
+ const registeredWidget = registrationWidgetsByType.get(descriptorWidget.type);
698
+ if (!registeredWidget) throw new WidgetRuntimeError({
699
+ code: "INVALID_REGISTRATION",
700
+ message: `Widget package registration is missing widget type: ${descriptorWidget.type}`,
701
+ packageId: descriptor.packageId,
702
+ version: descriptor.version
703
+ });
704
+ return {
705
+ ...descriptorWidget,
706
+ ...pickRuntimeMetadataOverrides(registeredWidget),
707
+ packageId: descriptor.packageId,
708
+ packageType: descriptor.packageType,
709
+ version: descriptor.version,
710
+ propertySchema: registeredWidget.propertySchema,
711
+ defaultProps: registeredWidget.defaultProps,
712
+ component: registeredWidget.component
713
+ };
714
+ });
715
+ }
716
+ function pickRuntimeMetadataOverrides(widget) {
717
+ return {
718
+ ...widget.name !== void 0 ? { name: widget.name } : {},
719
+ ...widget.displayName !== void 0 ? { displayName: widget.displayName } : {},
720
+ ...widget.description !== void 0 ? { description: widget.description } : {},
721
+ ...widget.icon !== void 0 ? { icon: widget.icon } : {},
722
+ ...widget.category !== void 0 ? { category: widget.category } : {},
723
+ ...widget.container !== void 0 ? { container: widget.container } : {},
724
+ ...widget.minSdkVersion !== void 0 ? { minSdkVersion: widget.minSdkVersion } : {},
725
+ ...widget.resizable !== void 0 ? { resizable: widget.resizable } : {}
726
+ };
727
+ }
728
+ function loadRemoteEntryScript(descriptor, timeoutMs, cacheBust, assertFreshPackageLoad, isFreshPackageLoad, remoteEntryUrlKey) {
729
+ return enqueueRemoteEntryScriptLoad(async () => {
730
+ assertFreshPackageLoad();
731
+ const registration = ensureFluidWidgetsGlobal().getPackageRegistration(descriptor.packageId, descriptor.version);
732
+ if (registration) return {
733
+ previousRegistration: void 0,
734
+ registration
735
+ };
736
+ return await loadRemoteEntryScriptImmediately(descriptor, timeoutMs, cacheBust, isFreshPackageLoad, remoteEntryUrlKey);
737
+ });
738
+ }
739
+ async function loadRemoteEntryScriptImmediately(descriptor, timeoutMs, cacheBust, isFreshPackageLoad, remoteEntryUrlKey) {
740
+ const fluidWidgets = ensureFluidWidgetsGlobal();
741
+ let previousRegistration;
742
+ let registration;
743
+ const unsubscribe = fluidWidgets.subscribe((event) => {
744
+ if (event.kind !== "register") return;
745
+ if (event.registration.packageId === descriptor.packageId && event.registration.version === descriptor.version) {
746
+ if (isFreshPackageLoad()) {
747
+ previousRegistration = event.previousRegistration;
748
+ registration = event.registration;
749
+ return;
750
+ }
751
+ cleanupUnexpectedFluidWidgetsRegistration(event.registration, event.previousRegistration);
752
+ return;
753
+ }
754
+ if (hasPendingRemoteRegistrationForScript(event.registration, remoteEntryUrlKey)) return;
755
+ cleanupUnexpectedFluidWidgetsRegistration(event.registration, event.previousRegistration);
756
+ });
757
+ const scriptElement = document.createElement("script");
758
+ let timeoutId;
759
+ try {
760
+ await new Promise((resolve, reject) => {
761
+ timeoutId = window.setTimeout(() => {
762
+ reject(new WidgetRuntimeError({
763
+ code: "SCRIPT_TIMEOUT",
764
+ message: `Timed out loading widget package ${descriptor.packageId}@${descriptor.version}`,
765
+ packageId: descriptor.packageId,
766
+ version: descriptor.version
767
+ }));
768
+ }, timeoutMs);
769
+ scriptElement.async = true;
770
+ scriptElement.src = withCacheBust(descriptor.remoteEntryUrl, cacheBust);
771
+ scriptElement.dataset.fluidWidgetRuntimeScript = "true";
772
+ scriptElement.dataset.fluidWidgetRuntimePackageId = descriptor.packageId;
773
+ scriptElement.dataset.fluidWidgetRuntimeVersion = descriptor.version;
774
+ scriptElement.addEventListener("load", () => {
775
+ resolve();
776
+ }, { once: true });
777
+ scriptElement.addEventListener("error", () => {
778
+ reject(new WidgetRuntimeError({
779
+ code: "SCRIPT_LOAD_FAILED",
780
+ message: `Failed to load widget package script ${descriptor.remoteEntryUrl}`,
781
+ packageId: descriptor.packageId,
782
+ version: descriptor.version
783
+ }));
784
+ }, { once: true });
785
+ document.head.appendChild(scriptElement);
786
+ });
787
+ } catch (error) {
788
+ scriptElement.remove();
789
+ throw error;
790
+ } finally {
791
+ unsubscribe();
792
+ if (timeoutId !== void 0) window.clearTimeout(timeoutId);
793
+ }
794
+ return {
795
+ previousRegistration,
796
+ registration,
797
+ scriptElement
798
+ };
799
+ }
800
+ function getDescriptorIdentity(descriptor) {
801
+ if (typeof descriptor !== "object" || descriptor === null) return {};
802
+ return {
803
+ packageId: typeof descriptor.packageId === "string" ? descriptor.packageId : void 0,
804
+ version: typeof descriptor.version === "string" ? descriptor.version : void 0
805
+ };
806
+ }
807
+ function createSuccess(cachedPackage) {
808
+ return {
809
+ ok: true,
810
+ packageId: cachedPackage.packageId,
811
+ version: cachedPackage.version,
812
+ widgets: cachedPackage.widgets
813
+ };
814
+ }
815
+ function createPackageCacheKey(packageId, version) {
816
+ return JSON.stringify([packageId, version]);
817
+ }
818
+ function createCssLoadRef(cacheKey, generation) {
819
+ return JSON.stringify([cacheKey, generation]);
820
+ }
821
+ function createWidgetRegistryKey(packageId, version, type) {
822
+ return JSON.stringify([
823
+ packageId,
824
+ version,
825
+ type
826
+ ]);
827
+ }
828
+ function addPendingRemoteRegistration(pendingLoad) {
829
+ const packageKey = createPackageCacheKey(pendingLoad.packageId, pendingLoad.version);
830
+ const pendingLoads = pendingRemoteRegistrationsByPackageKey.get(packageKey);
831
+ if (pendingLoads) {
832
+ pendingLoads.add(pendingLoad);
833
+ return;
834
+ }
835
+ pendingRemoteRegistrationsByPackageKey.set(packageKey, new Set([pendingLoad]));
836
+ }
837
+ function removePendingRemoteRegistration(pendingLoad) {
838
+ const packageKey = createPackageCacheKey(pendingLoad.packageId, pendingLoad.version);
839
+ const pendingLoads = pendingRemoteRegistrationsByPackageKey.get(packageKey);
840
+ if (!pendingLoads) return;
841
+ pendingLoads.delete(pendingLoad);
842
+ if (pendingLoads.size === 0) pendingRemoteRegistrationsByPackageKey.delete(packageKey);
843
+ }
844
+ function hasPendingRemoteRegistrationForScript(registration, remoteEntryUrlKey) {
845
+ const pendingLoads = pendingRemoteRegistrationsByPackageKey.get(createPackageCacheKey(registration.packageId, registration.version));
846
+ if (!pendingLoads) return false;
847
+ for (const pendingLoad of pendingLoads) if (pendingLoad.remoteEntryUrlKey === remoteEntryUrlKey) return true;
848
+ return false;
849
+ }
850
+ function enqueueRemoteEntryScriptLoad(task) {
851
+ const previousLoad = remoteScriptLoadQueue;
852
+ const resultPromise = previousLoad === void 0 ? task() : previousLoad.then(task, task);
853
+ const currentLoad = resultPromise.then(() => void 0, () => void 0);
854
+ remoteScriptLoadQueue = currentLoad;
855
+ currentLoad.then(() => {
856
+ if (remoteScriptLoadQueue === currentLoad) remoteScriptLoadQueue = void 0;
857
+ });
858
+ return resultPromise;
859
+ }
860
+ function normalizeAssetUrl(url, descriptor) {
861
+ try {
862
+ return new URL(url, window.location.href).href;
863
+ } catch {
864
+ throw new WidgetRuntimeError({
865
+ code: "INVALID_DESCRIPTOR",
866
+ message: `Widget package cssUrls contains invalid URL: ${url}`,
867
+ packageId: descriptor.packageId,
868
+ version: descriptor.version
869
+ });
870
+ }
871
+ }
872
+ function withCacheBust(url, cacheBust) {
873
+ if (cacheBust === void 0 || cacheBust === false) return url;
874
+ const cacheBustValue = typeof cacheBust === "function" ? cacheBust() : cacheBust === true ? String(Date.now()) : cacheBust;
875
+ const nextUrl = new URL(url, window.location.href);
876
+ nextUrl.searchParams.set("fluidWidgetRuntimeCacheBust", cacheBustValue);
877
+ return nextUrl.href;
878
+ }
879
+ //#endregion
880
+ //#region ../../platform/widget-runtime/src/globals.ts
881
+ const globalMarker = Symbol.for("fluid.widget-runtime.FluidSharedGlobals");
882
+ function installFluidWidgetRuntimeHostGlobals(shared = {
883
+ React: react,
884
+ ReactDOM: react_dom,
885
+ ReactJsxRuntime: react_jsx_runtime
886
+ }) {
887
+ ensureFluidWidgetsGlobal();
888
+ const existing = window.FluidShared;
889
+ if (isFluidSharedGlobal(existing)) return existing;
890
+ const widgetRuntime = {
891
+ createWidgetRuntimeLoader,
892
+ installFluidWidgetRuntimeHostGlobals,
893
+ manifestVersion: 1,
894
+ ...shared.WidgetRuntime
895
+ };
896
+ const fluidShared = {
897
+ [globalMarker]: true,
898
+ React: shared.React,
899
+ ReactDOM: shared.ReactDOM,
900
+ ReactJsxRuntime: shared.ReactJsxRuntime,
901
+ WidgetRuntime: widgetRuntime
902
+ };
903
+ window.FluidShared = fluidShared;
904
+ return fluidShared;
905
+ }
906
+ function isFluidSharedGlobal(value) {
907
+ return value !== void 0 && value[globalMarker] === true;
908
+ }
909
+ //#endregion
910
+ //#region ../../platform/widget-runtime/src/components/WidgetRuntimeErrorBoundary.tsx
911
+ var WidgetRuntimeErrorBoundary = class extends react.Component {
912
+ state = { error: null };
913
+ static getDerivedStateFromError(error) {
914
+ return { error };
915
+ }
916
+ componentDidCatch(error, errorInfo) {
917
+ this.props.onError?.(error, errorInfo);
918
+ }
919
+ render() {
920
+ const { error } = this.state;
921
+ if (!error) return this.props.children;
922
+ const reset = () => {
923
+ this.setState({ error: null });
924
+ };
925
+ if (typeof this.props.fallback === "function") return this.props.fallback({
926
+ error,
927
+ reset
928
+ });
929
+ if (this.props.fallback !== void 0) return this.props.fallback;
930
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultWidgetRuntimeErrorFallback, {
931
+ error,
932
+ reset
933
+ });
934
+ }
935
+ };
936
+ function DefaultWidgetRuntimeErrorFallback({ error, reset }) {
937
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
938
+ role: "alert",
939
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: error instanceof WidgetRuntimeError ? "Widget runtime failed" : "Widget failed to render" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
940
+ type: "button",
941
+ onClick: reset,
942
+ children: "Try again"
943
+ })]
944
+ });
945
+ }
946
+ //#endregion
947
+ //#region src/utils/build-widget-registry.ts
948
+ function buildWidgetRegistry(manifests) {
949
+ if (manifests.length === 0) return require_FluidProvider.DEFAULT_SDK_WIDGET_REGISTRY;
950
+ const customEntries = Object.fromEntries(manifests.filter((manifest) => {
951
+ const isBuiltIn = isBuiltInWidgetType(manifest.type);
952
+ if (isBuiltIn) warnBuiltInWidgetCollision("manifest", manifest.type);
953
+ return !isBuiltIn;
954
+ }).map((manifest) => [manifest.type, manifest.component]));
955
+ return {
956
+ ...require_FluidProvider.DEFAULT_SDK_WIDGET_REGISTRY,
957
+ ...customEntries
958
+ };
959
+ }
960
+ function mergeRegisteredWidgetsIntoRegistry(registry, registeredWidgets) {
961
+ if (registeredWidgets.length === 0) return registry;
962
+ const duplicateRuntimeWidgetTypes = getDuplicateWidgetTypes(registeredWidgets);
963
+ const remoteEntries = Object.fromEntries(registeredWidgets.filter((widget) => {
964
+ if (isBuiltInWidgetType(widget.type)) {
965
+ warnBuiltInWidgetCollision("runtime registration", widget.type);
966
+ return false;
967
+ }
968
+ if (duplicateRuntimeWidgetTypes.has(widget.type)) {
969
+ warnDuplicateRuntimeWidgetType(widget.type);
970
+ return false;
971
+ }
972
+ if (isExistingRegistryWidgetType(registry, widget.type)) {
973
+ warnExistingRegistryWidgetCollision(widget.type);
974
+ return false;
975
+ }
976
+ return true;
977
+ }).map((widget) => [widget.type, wrapRuntimeWidgetComponent(widget)]));
978
+ return {
979
+ ...registry,
980
+ ...remoteEntries
981
+ };
982
+ }
983
+ function getDuplicateWidgetTypes(widgets) {
984
+ const counts = /* @__PURE__ */ new Map();
985
+ for (const widget of widgets) counts.set(widget.type, (counts.get(widget.type) ?? 0) + 1);
986
+ return new Set(Array.from(counts.entries()).filter(([, count]) => count > 1).map(([type]) => type));
987
+ }
988
+ function wrapRuntimeWidgetComponent(widget) {
989
+ const RuntimeWidgetComponent = widget.component;
990
+ function RuntimeWidgetWithBoundary(props) {
991
+ return (0, react.createElement)(WidgetRuntimeErrorBoundary, null, (0, react.createElement)(RuntimeWidgetComponent, props));
992
+ }
993
+ RuntimeWidgetWithBoundary.displayName = `WidgetRuntimeErrorBoundary(${widget.type})`;
994
+ return RuntimeWidgetWithBoundary;
995
+ }
996
+ function isBuiltInWidgetType(widgetType) {
997
+ return Object.prototype.hasOwnProperty.call(require_FluidProvider.DEFAULT_SDK_WIDGET_REGISTRY, widgetType);
998
+ }
999
+ function isExistingRegistryWidgetType(registry, widgetType) {
1000
+ return Object.prototype.hasOwnProperty.call(registry, widgetType);
1001
+ }
1002
+ function warnBuiltInWidgetCollision(source, widgetType) {
1003
+ console.warn(`[portal-sdk] Ignoring ${source} for built-in widget type "${widgetType}". Built-in widgets cannot be overridden.`);
1004
+ }
1005
+ function warnDuplicateRuntimeWidgetType(widgetType) {
1006
+ console.warn(`[portal-sdk] Ignoring runtime widget type "${widgetType}" because multiple packages registered the same SDK-facing type.`);
1007
+ }
1008
+ function warnExistingRegistryWidgetCollision(widgetType) {
1009
+ console.warn(`[portal-sdk] Ignoring runtime widget type "${widgetType}" because the SDK registry already contains that type.`);
1010
+ }
1011
+ //#endregion
1012
+ //#region src/utils/widget-package-manifest-url.ts
1013
+ const DEFAULT_WIDGET_PACKAGE_MANIFEST_URL = "/api/app/widget-packages";
1014
+ const VITE_DEV_WIDGET_PACKAGE_MANIFEST_URL = "/__widget-packages__";
1015
+ const VITE_DEV_MODULE_PATH_SEGMENTS = [
1016
+ "/@fs/",
1017
+ "/src/",
1018
+ "/node_modules/.vite/",
1019
+ "/@id/"
1020
+ ];
1021
+ function resolveDefaultWidgetPackageManifestUrl(moduleUrl, options = {}) {
1022
+ const parsedModuleUrl = parseModuleUrl(moduleUrl);
1023
+ if (!parsedModuleUrl) return false;
1024
+ if (options.isViteDev && isViteDevModulePath(parsedModuleUrl.pathname)) return new URL(VITE_DEV_WIDGET_PACKAGE_MANIFEST_URL, parsedModuleUrl.origin).href;
1025
+ return DEFAULT_WIDGET_PACKAGE_MANIFEST_URL;
1026
+ }
1027
+ function parseModuleUrl(moduleUrl) {
1028
+ if (!moduleUrl) return null;
1029
+ try {
1030
+ return new URL(moduleUrl);
1031
+ } catch {
1032
+ return null;
1033
+ }
1034
+ }
1035
+ function isViteDevModulePath(pathname) {
1036
+ return VITE_DEV_MODULE_PATH_SEGMENTS.some((segment) => pathname.includes(segment));
1037
+ }
1038
+ function getDefaultWidgetPackageManifestUrl() {
1039
+ return resolveDefaultWidgetPackageManifestUrl(require("url").pathToFileURL(__filename).href, { isViteDev: isViteDevRuntime() });
1040
+ }
1041
+ function isViteDevRuntime() {
1042
+ return {}.env?.DEV === true;
1043
+ }
1044
+ //#endregion
1045
+ //#region src/utils/load-widget-packages.ts
1046
+ const WIDGET_PACKAGE_DESCRIPTOR_MANIFEST_VERSION = 1;
1047
+ const WIDGET_PACKAGE_DESCRIPTOR_FETCH_TIMEOUT_MS = 5e3;
1048
+ function installAndReadFluidWidgetsRegistry() {
1049
+ if (typeof window === "undefined") return [];
1050
+ installFluidWidgetRuntimeHostGlobals({
1051
+ React: react,
1052
+ ReactDOM: react_dom,
1053
+ ReactJsxRuntime: react_jsx_runtime
1054
+ });
1055
+ return ensureFluidWidgetsGlobal().getRegisteredWidgets();
1056
+ }
1057
+ function subscribeToFluidWidgetsRegistry(listener) {
1058
+ if (typeof window === "undefined") return () => void 0;
1059
+ installFluidWidgetRuntimeHostGlobals({
1060
+ React: react,
1061
+ ReactDOM: react_dom,
1062
+ ReactJsxRuntime: react_jsx_runtime
1063
+ });
1064
+ const fluidWidgets = ensureFluidWidgetsGlobal();
1065
+ return fluidWidgets.subscribe(() => {
1066
+ listener(fluidWidgets.getRegisteredWidgets());
1067
+ });
1068
+ }
1069
+ async function fetchWidgetPackageDescriptors(descriptorEndpointUrl = DEFAULT_WIDGET_PACKAGE_MANIFEST_URL, options = {}) {
1070
+ const abortSignal = createTimeoutAbortSignal(WIDGET_PACKAGE_DESCRIPTOR_FETCH_TIMEOUT_MS);
1071
+ try {
1072
+ const response = await fetch(descriptorEndpointUrl, {
1073
+ credentials: options.credentials ?? "same-origin",
1074
+ signal: abortSignal.signal
1075
+ });
1076
+ if (!response.ok) throw new Error(`[portal] Failed to fetch widget package descriptors from ${descriptorEndpointUrl}: ${response.status} ${response.statusText}`);
1077
+ return parseWidgetPackageDescriptorResponse(await response.json(), descriptorEndpointUrl, options);
1078
+ } finally {
1079
+ abortSignal.cleanup();
1080
+ }
1081
+ }
1082
+ function parseWidgetPackageDescriptorResponse(data, descriptorEndpointUrl = DEFAULT_WIDGET_PACKAGE_MANIFEST_URL, options = {}) {
1083
+ const descriptorEndpointBaseUrl = normalizeDescriptorEndpointUrl(descriptorEndpointUrl);
1084
+ if (!descriptorEndpointBaseUrl) return [];
1085
+ const entries = getWidgetPackageDescriptorEntries(data);
1086
+ if (!entries) return [];
1087
+ const assetOriginPolicy = createRuntimeAssetOriginPolicy(descriptorEndpointBaseUrl, options.allowedOrigins ?? [], options.trustCatalogAssetOrigins === true);
1088
+ const descriptors = [];
1089
+ for (const entry of entries) {
1090
+ const descriptor = normalizeWidgetPackageDescriptor(entry, descriptorEndpointBaseUrl, assetOriginPolicy);
1091
+ if (descriptor) descriptors.push(descriptor);
1092
+ }
1093
+ return descriptors;
1094
+ }
1095
+ async function loadWidgetPackages(widgetPackages) {
1096
+ if (widgetPackages.length === 0) return {
1097
+ registeredWidgets: [],
1098
+ hasFailures: false
1099
+ };
1100
+ installAndReadFluidWidgetsRegistry();
1101
+ const loader = createWidgetRuntimeLoader();
1102
+ const runtimeWidgetPackages = widgetPackages;
1103
+ const results = await loader.loadPackages(runtimeWidgetPackages);
1104
+ let hasFailures = false;
1105
+ for (const result of results) if (!result.ok) {
1106
+ hasFailures = true;
1107
+ console.error(`[portal] Failed to load widget package ${result.packageId}@${result.version}:`, result.error);
1108
+ }
1109
+ return {
1110
+ registeredWidgets: loader.getRegisteredWidgets(),
1111
+ hasFailures
1112
+ };
1113
+ }
1114
+ function createTimeoutAbortSignal(timeoutMs) {
1115
+ if (typeof AbortSignal.timeout === "function") return {
1116
+ signal: AbortSignal.timeout(timeoutMs),
1117
+ cleanup: () => void 0
1118
+ };
1119
+ const controller = new AbortController();
1120
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
1121
+ return {
1122
+ signal: controller.signal,
1123
+ cleanup: () => clearTimeout(timeoutId)
1124
+ };
1125
+ }
1126
+ function getWidgetPackageDescriptorEntries(data) {
1127
+ if (Array.isArray(data)) return data;
1128
+ if (!isRecord(data)) return null;
1129
+ const wrappedEntries = getArrayProperty(data, "packages") ?? getArrayProperty(data, "packageDescriptors") ?? getArrayProperty(data, "widgetPackages");
1130
+ if (wrappedEntries) return wrappedEntries;
1131
+ return looksLikeWidgetPackageEntry(data) ? [data] : null;
1132
+ }
1133
+ function normalizeWidgetPackageDescriptor(entry, descriptorEndpointUrl, assetOriginPolicy) {
1134
+ const candidate = createWidgetPackageDescriptorCandidate(entry);
1135
+ if (candidate.kind === "skipped") return null;
1136
+ if (candidate.kind === "invalid") {
1137
+ warnRejectedMalformedWidgetPackageEntry(entry, candidate.reason, descriptorEndpointUrl);
1138
+ return null;
1139
+ }
1140
+ const remoteEntryUrl = normalizeRuntimeAssetUrl(candidate.descriptor.remoteEntryUrl, descriptorEndpointUrl, assetOriginPolicy);
1141
+ if (!remoteEntryUrl.ok) {
1142
+ warnRejectedWidgetPackageDescriptor(candidate.descriptor, "remoteEntryUrl", remoteEntryUrl.failure, descriptorEndpointUrl);
1143
+ return null;
1144
+ }
1145
+ const cssUrls = [];
1146
+ for (const cssUrl of candidate.descriptor.cssUrls) {
1147
+ const normalizedCssUrl = normalizeRuntimeAssetUrl(cssUrl, descriptorEndpointUrl, assetOriginPolicy);
1148
+ if (!normalizedCssUrl.ok) {
1149
+ warnRejectedWidgetPackageDescriptor(candidate.descriptor, "cssUrls", normalizedCssUrl.failure, descriptorEndpointUrl);
1150
+ return null;
1151
+ }
1152
+ cssUrls.push(normalizedCssUrl.url);
1153
+ }
1154
+ const descriptor = {
1155
+ ...candidate.descriptor,
1156
+ remoteEntryUrl: remoteEntryUrl.url,
1157
+ cssUrls
1158
+ };
1159
+ const validationError = validateDescriptorCandidate(descriptor);
1160
+ if (validationError) {
1161
+ warnRejectedMalformedWidgetPackageEntry(entry, validationError, descriptorEndpointUrl);
1162
+ return null;
1163
+ }
1164
+ return descriptor;
1165
+ }
1166
+ function createWidgetPackageDescriptorCandidate(entry) {
1167
+ if (!isRecord(entry)) return {
1168
+ kind: "invalid",
1169
+ reason: "entry must be an object"
1170
+ };
1171
+ const manifest = isRecord(entry.manifest) ? entry.manifest : void 0;
1172
+ if (entry.disabled === true || entry.enabled === false) return { kind: "skipped" };
1173
+ if (isRuntimeWidgetPackageDescriptorAttempt(entry)) return createStrictRuntimeWidgetPackageDescriptorCandidate(entry);
1174
+ if (isCatalogWidgetPackageEntry(entry, manifest)) return createCatalogWidgetPackageDescriptorCandidate(entry, manifest);
1175
+ return createRuntimeWidgetPackageDescriptorCandidate(entry, manifest);
1176
+ }
1177
+ function createStrictRuntimeWidgetPackageDescriptorCandidate(entry) {
1178
+ return createDescriptorCandidate({
1179
+ manifestVersion: normalizeManifestVersion(entry.manifestVersion, { defaultWhenMissing: false }),
1180
+ packageId: readNonEmptyString(entry.packageId),
1181
+ packageType: normalizeWidgetPackageType(entry.packageType),
1182
+ version: readNonEmptyString(entry.version),
1183
+ remoteEntryUrl: readNonEmptyString(entry.remoteEntryUrl),
1184
+ cssUrls: normalizeRuntimeCssUrls(entry.cssUrls),
1185
+ widgets: normalizeRuntimeWidgets(entry.widgets),
1186
+ packageTypeError: "packageType must be one of fluid, company, droplet, partner, or internal",
1187
+ widgetsError: "manifest.widgets/widgets must be a non-empty array"
1188
+ });
1189
+ }
1190
+ function createRuntimeWidgetPackageDescriptorCandidate(entry, manifest) {
1191
+ const packageId = readNonEmptyString(entry.packageId) ?? readNonEmptyString(manifest?.packageId);
1192
+ const version = readNonEmptyString(entry.version) ?? readNonEmptyString(manifest?.version);
1193
+ const remoteEntryUrl = readNonEmptyString(entry.remoteEntryUrl) ?? readNonEmptyString(manifest?.remoteEntryUrl);
1194
+ const packageType = normalizeWidgetPackageType(entry.packageType) ?? normalizeWidgetPackageType(manifest?.packageType);
1195
+ return createDescriptorCandidate({
1196
+ manifestVersion: normalizeManifestVersion(entry.manifestVersion ?? manifest?.manifestVersion, { defaultWhenMissing: false }),
1197
+ packageId,
1198
+ packageType,
1199
+ version,
1200
+ remoteEntryUrl,
1201
+ cssUrls: normalizeRuntimeCssUrls(entry.cssUrls ?? manifest?.cssUrls),
1202
+ widgets: normalizeRuntimeWidgets(manifest?.widgets ?? entry.widgets),
1203
+ packageTypeError: "packageType must be one of fluid, company, droplet, partner, or internal",
1204
+ widgetsError: "manifest.widgets/widgets must be a non-empty array"
1205
+ });
1206
+ }
1207
+ function createCatalogWidgetPackageDescriptorCandidate(entry, manifest) {
1208
+ const packageId = readNonEmptyString(entry.packageId) ?? readNonEmptyString(manifest?.packageId);
1209
+ const version = readNonEmptyString(entry.version) ?? readNonEmptyString(manifest?.version);
1210
+ const remoteEntryUrl = readNonEmptyString(entry.scriptUrl) ?? readNonEmptyString(entry.remoteEntryUrl) ?? readNonEmptyString(manifest?.scriptUrl) ?? readNonEmptyString(manifest?.remoteEntryUrl);
1211
+ const packageType = normalizeWidgetPackageType(entry.source) ?? normalizeWidgetPackageType(entry.packageType) ?? normalizeWidgetPackageType(manifest?.source) ?? normalizeWidgetPackageType(manifest?.packageType) ?? "company";
1212
+ const manifestVersion = normalizeManifestVersion(entry.manifestVersion ?? manifest?.manifestVersion, { defaultWhenMissing: true });
1213
+ const cssUrls = normalizeCssUrls(entry.cssUrls ?? manifest?.cssUrls);
1214
+ const rawWidgets = manifest?.widgets ?? entry.widgets;
1215
+ return createDescriptorCandidate({
1216
+ manifestVersion,
1217
+ packageId,
1218
+ packageType,
1219
+ version,
1220
+ remoteEntryUrl,
1221
+ cssUrls,
1222
+ widgets: Array.isArray(rawWidgets) ? normalizeCatalogWidgets(rawWidgets, packageId) : null,
1223
+ packageTypeError: "packageType/source must be one of fluid, company, droplet, partner, internal, or omitted for company catalog packages",
1224
+ widgetsError: "manifest.widgets/widgets must contain at least one valid widget"
1225
+ });
1226
+ }
1227
+ function createDescriptorCandidate(fields) {
1228
+ if (!fields.manifestVersion) return {
1229
+ kind: "invalid",
1230
+ reason: "unsupported manifestVersion"
1231
+ };
1232
+ if (!fields.packageId) return {
1233
+ kind: "invalid",
1234
+ reason: "packageId must be a non-empty string"
1235
+ };
1236
+ if (!fields.version) return {
1237
+ kind: "invalid",
1238
+ reason: "version must be a non-empty string"
1239
+ };
1240
+ if (!fields.packageType) return {
1241
+ kind: "invalid",
1242
+ reason: fields.packageTypeError
1243
+ };
1244
+ if (!fields.remoteEntryUrl) return {
1245
+ kind: "invalid",
1246
+ reason: "remoteEntryUrl/scriptUrl must be a non-empty string"
1247
+ };
1248
+ if (!fields.cssUrls) return {
1249
+ kind: "invalid",
1250
+ reason: "cssUrls must be an array of strings"
1251
+ };
1252
+ if (!fields.widgets || fields.widgets.length === 0) return {
1253
+ kind: "invalid",
1254
+ reason: fields.widgetsError
1255
+ };
1256
+ return {
1257
+ kind: "valid",
1258
+ descriptor: {
1259
+ manifestVersion: fields.manifestVersion,
1260
+ packageId: fields.packageId,
1261
+ packageType: fields.packageType,
1262
+ version: fields.version,
1263
+ remoteEntryUrl: fields.remoteEntryUrl,
1264
+ cssUrls: fields.cssUrls,
1265
+ widgets: fields.widgets
1266
+ }
1267
+ };
1268
+ }
1269
+ function validateDescriptorCandidate(descriptor) {
1270
+ try {
1271
+ validateWidgetPackageDescriptor(descriptor);
1272
+ return null;
1273
+ } catch (error) {
1274
+ return error instanceof Error ? error.message : String(error);
1275
+ }
1276
+ }
1277
+ function isRuntimeWidgetPackageDescriptorAttempt(entry) {
1278
+ return entry.manifestVersion !== void 0 && entry.packageId !== void 0 && entry.packageType !== void 0 && entry.version !== void 0 && entry.remoteEntryUrl !== void 0 && entry.cssUrls !== void 0 && entry.widgets !== void 0;
1279
+ }
1280
+ function isCatalogWidgetPackageEntry(entry, manifest) {
1281
+ return entry.source !== void 0 || entry.scriptUrl !== void 0 || entry.manifestUrl !== void 0 || manifest?.source !== void 0 || manifest?.scriptUrl !== void 0 || manifest?.manifestUrl !== void 0 || manifest?.widgets !== void 0;
1282
+ }
1283
+ function normalizeManifestVersion(value, options) {
1284
+ if (value === WIDGET_PACKAGE_DESCRIPTOR_MANIFEST_VERSION) return WIDGET_PACKAGE_DESCRIPTOR_MANIFEST_VERSION;
1285
+ if (value === void 0 && options.defaultWhenMissing) return WIDGET_PACKAGE_DESCRIPTOR_MANIFEST_VERSION;
1286
+ return null;
1287
+ }
1288
+ function normalizeCssUrls(value) {
1289
+ return normalizeCssUrlList(value, { undefinedValue: [] });
1290
+ }
1291
+ function normalizeRuntimeCssUrls(value) {
1292
+ return normalizeCssUrlList(value, { undefinedValue: null });
1293
+ }
1294
+ function normalizeCssUrlList(value, options) {
1295
+ if (value === void 0) return options.undefinedValue;
1296
+ if (!Array.isArray(value)) return null;
1297
+ const cssUrls = [];
1298
+ for (const cssUrl of value) {
1299
+ const normalizedCssUrl = readNonEmptyString(cssUrl);
1300
+ if (!normalizedCssUrl) return null;
1301
+ cssUrls.push(normalizedCssUrl);
1302
+ }
1303
+ return cssUrls;
1304
+ }
1305
+ function normalizeRuntimeWidgets(value) {
1306
+ if (!Array.isArray(value)) return null;
1307
+ return value;
1308
+ }
1309
+ function normalizeCatalogWidgets(value, packageId) {
1310
+ const widgets = [];
1311
+ value.forEach((widget, index) => {
1312
+ const normalizedWidget = normalizeWidgetDescriptor(widget, {
1313
+ fallbackType: packageId === void 0 ? void 0 : `${packageId}-widget-${index + 1}`,
1314
+ overwritePropertySchemaWidgetType: true
1315
+ });
1316
+ if (normalizedWidget) widgets.push(normalizedWidget);
1317
+ });
1318
+ return widgets;
1319
+ }
1320
+ function normalizeWidgetDescriptor(widget, options = {}) {
1321
+ if (!isRecord(widget)) return null;
1322
+ const type = readNonEmptyString(widget.type) ?? readNonEmptyString(widget.name) ?? options.fallbackType;
1323
+ if (!type) return null;
1324
+ const name = readNonEmptyString(widget.name) ?? type;
1325
+ const displayName = readNonEmptyString(widget.displayName) ?? name;
1326
+ return {
1327
+ type,
1328
+ name,
1329
+ displayName,
1330
+ description: readNonEmptyString(widget.description) ?? `Custom widget ${displayName}`,
1331
+ icon: readNonEmptyString(widget.icon) ?? "box",
1332
+ category: readNonEmptyString(widget.category) ?? "components",
1333
+ propertySchema: normalizePropertySchema(widget.propertySchema, type, { overwriteWidgetType: options.overwritePropertySchemaWidgetType === true }),
1334
+ defaultProps: isRecord(widget.defaultProps) ? widget.defaultProps : {},
1335
+ container: normalizeContainer(widget.container),
1336
+ minSdkVersion: readNonEmptyString(widget.minSdkVersion) ?? "0.0.0",
1337
+ resizable: normalizeResizable(widget.resizable)
1338
+ };
1339
+ }
1340
+ function normalizePropertySchema(value, widgetType, options = { overwriteWidgetType: false }) {
1341
+ if (!isRecord(value)) return { widgetType };
1342
+ if (options.overwriteWidgetType || value.widgetType === void 0) return {
1343
+ ...value,
1344
+ widgetType
1345
+ };
1346
+ return value;
1347
+ }
1348
+ function normalizeContainer(value) {
1349
+ return normalizeWidgetRuntimeContainer(value);
1350
+ }
1351
+ function normalizeResizable(value) {
1352
+ return normalizeWidgetRuntimeResizable(value);
1353
+ }
1354
+ function normalizeRuntimeAssetUrl(url, baseUrl, assetOriginPolicy) {
1355
+ if (hasUnsafeRawRuntimeAssetUrlSyntax(url)) return {
1356
+ ok: false,
1357
+ failure: {
1358
+ inputUrl: url,
1359
+ reason: "invalid-url"
1360
+ }
1361
+ };
1362
+ try {
1363
+ const parsedUrl = new URL(url, baseUrl);
1364
+ if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") return {
1365
+ ok: false,
1366
+ failure: {
1367
+ inputUrl: url,
1368
+ resolvedUrl: parsedUrl.href,
1369
+ reason: "unsupported-protocol"
1370
+ }
1371
+ };
1372
+ if (assetOriginPolicy.allowedOrigins.has(parsedUrl.origin)) return {
1373
+ ok: true,
1374
+ url: parsedUrl.href
1375
+ };
1376
+ if (assetOriginPolicy.allowSharedWidgetArtifactBucket && parsedUrl.href.startsWith("https://storage.googleapis.com/portal-widgets/")) return {
1377
+ ok: true,
1378
+ url: parsedUrl.href
1379
+ };
1380
+ return {
1381
+ ok: false,
1382
+ failure: {
1383
+ inputUrl: url,
1384
+ resolvedUrl: parsedUrl.href,
1385
+ reason: "untrusted-origin"
1386
+ }
1387
+ };
1388
+ } catch {
1389
+ return {
1390
+ ok: false,
1391
+ failure: {
1392
+ inputUrl: url,
1393
+ reason: "invalid-url"
1394
+ }
1395
+ };
1396
+ }
1397
+ }
1398
+ function warnRejectedWidgetPackageDescriptor(descriptor, assetField, failure, descriptorEndpointUrl) {
1399
+ console.warn(`[portal] Dropping widget package descriptor ${descriptor.packageId}@${descriptor.version} from ${descriptorEndpointUrl.href}: ${assetField} "${failure.inputUrl}" ${formatRuntimeAssetUrlFailure(failure)}.`);
1400
+ }
1401
+ function warnRejectedMalformedWidgetPackageEntry(entry, reason, descriptorEndpointUrl) {
1402
+ console.warn(`[portal] Dropping widget package catalog entry ${formatWidgetPackageEntryIdentity(entry)} from ${descriptorEndpointUrl.href}: ${reason}.`);
1403
+ }
1404
+ function formatWidgetPackageEntryIdentity(entry) {
1405
+ if (!isRecord(entry)) return "<unknown>";
1406
+ const packageId = readNonEmptyString(entry.packageId);
1407
+ const version = readNonEmptyString(entry.version);
1408
+ if (packageId && version) return `${packageId}@${version}`;
1409
+ if (packageId) return packageId;
1410
+ return "<unknown>";
1411
+ }
1412
+ function formatRuntimeAssetUrlFailure(failure) {
1413
+ const resolvedUrl = failure.resolvedUrl ? ` (resolved as ${failure.resolvedUrl})` : "";
1414
+ switch (failure.reason) {
1415
+ case "invalid-url": return "is not a valid URL";
1416
+ case "unsupported-protocol": return `uses an unsupported protocol${resolvedUrl}`;
1417
+ case "untrusted-origin": return `resolved to an untrusted origin${resolvedUrl}`;
1418
+ }
1419
+ }
1420
+ function createRuntimeAssetOriginPolicy(descriptorEndpointUrl, allowedOrigins, trustCatalogAssetOrigins) {
1421
+ const origins = /* @__PURE__ */ new Set();
1422
+ if (!trustCatalogAssetOrigins) origins.add(descriptorEndpointUrl.origin);
1423
+ for (const origin of allowedOrigins) {
1424
+ const normalizedOrigin = normalizeAllowedOrigin(origin);
1425
+ if (normalizedOrigin) origins.add(normalizedOrigin);
1426
+ else console.warn(`[portal] Ignoring invalid widget package allowed origin "${origin}". Expected an http(s) absolute URL origin.`);
1427
+ }
1428
+ return {
1429
+ allowSharedWidgetArtifactBucket: trustCatalogAssetOrigins,
1430
+ allowedOrigins: origins
1431
+ };
1432
+ }
1433
+ function hasUnsafeRawRuntimeAssetUrlSyntax(url) {
1434
+ return url.trim() !== url || hasControlCharacter(url) || url.includes("\\") || url.startsWith("//") || hasAmbiguousHttpScheme(url);
1435
+ }
1436
+ function hasAmbiguousHttpScheme(url) {
1437
+ return /^https?:(?!\/\/)/i.test(url);
1438
+ }
1439
+ function normalizeAllowedOrigin(origin) {
1440
+ try {
1441
+ const parsedOrigin = new URL(origin);
1442
+ if (parsedOrigin.protocol !== "http:" && parsedOrigin.protocol !== "https:") return null;
1443
+ return parsedOrigin.origin;
1444
+ } catch {
1445
+ return null;
1446
+ }
1447
+ }
1448
+ function normalizeDescriptorEndpointUrl(url) {
1449
+ try {
1450
+ return new URL(url, getWindowLocationHref());
1451
+ } catch {
1452
+ return null;
1453
+ }
1454
+ }
1455
+ function getWindowLocationHref() {
1456
+ return typeof window === "undefined" ? void 0 : window.location.href;
1457
+ }
1458
+ function looksLikeWidgetPackageEntry(value) {
1459
+ return value.packageId !== void 0 || value.remoteEntryUrl !== void 0 || value.scriptUrl !== void 0 || value.manifest !== void 0 || value.widgets !== void 0;
1460
+ }
1461
+ function getArrayProperty(value, key) {
1462
+ const property = value[key];
1463
+ return Array.isArray(property) ? property : void 0;
1464
+ }
1465
+ function isRecord(value) {
1466
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1467
+ }
1468
+ //#endregion
1469
+ //#region src/utils/widget-package-utils.ts
1470
+ function resolveHostedWidgetPackageManifestUrl(descriptorEndpointUrl, baseUrl) {
1471
+ try {
1472
+ return new URL(descriptorEndpointUrl, baseUrl).href;
1473
+ } catch {
1474
+ return descriptorEndpointUrl;
1475
+ }
1476
+ }
1477
+ function dedupeWidgetPackagesByPackageIdAndVersion(widgetPackages) {
1478
+ const widgetPackagesByIdAndVersion = /* @__PURE__ */ new Map();
1479
+ for (const widgetPackage of widgetPackages) {
1480
+ const key = JSON.stringify([widgetPackage.packageId, widgetPackage.version]);
1481
+ if (!widgetPackagesByIdAndVersion.has(key)) widgetPackagesByIdAndVersion.set(key, widgetPackage);
1482
+ }
1483
+ return Array.from(widgetPackagesByIdAndVersion.values());
1484
+ }
1485
+ //#endregion
1486
+ Object.defineProperty(exports, "DEFAULT_WIDGET_PACKAGE_MANIFEST_URL", {
1487
+ enumerable: true,
1488
+ get: function() {
1489
+ return DEFAULT_WIDGET_PACKAGE_MANIFEST_URL;
1490
+ }
1491
+ });
1492
+ Object.defineProperty(exports, "buildWidgetRegistry", {
1493
+ enumerable: true,
1494
+ get: function() {
1495
+ return buildWidgetRegistry;
1496
+ }
1497
+ });
1498
+ Object.defineProperty(exports, "createDefaultFluidConfig", {
1499
+ enumerable: true,
1500
+ get: function() {
1501
+ return createDefaultFluidConfig;
1502
+ }
1503
+ });
1504
+ Object.defineProperty(exports, "dedupeWidgetPackagesByPackageIdAndVersion", {
1505
+ enumerable: true,
1506
+ get: function() {
1507
+ return dedupeWidgetPackagesByPackageIdAndVersion;
1508
+ }
1509
+ });
1510
+ Object.defineProperty(exports, "fetchWidgetPackageDescriptors", {
1511
+ enumerable: true,
1512
+ get: function() {
1513
+ return fetchWidgetPackageDescriptors;
1514
+ }
1515
+ });
1516
+ Object.defineProperty(exports, "getDefaultWidgetPackageManifestUrl", {
1517
+ enumerable: true,
1518
+ get: function() {
1519
+ return getDefaultWidgetPackageManifestUrl;
1520
+ }
1521
+ });
1522
+ Object.defineProperty(exports, "installAndReadFluidWidgetsRegistry", {
1523
+ enumerable: true,
1524
+ get: function() {
1525
+ return installAndReadFluidWidgetsRegistry;
1526
+ }
1527
+ });
1528
+ Object.defineProperty(exports, "loadWidgetPackages", {
1529
+ enumerable: true,
1530
+ get: function() {
1531
+ return loadWidgetPackages;
1532
+ }
1533
+ });
1534
+ Object.defineProperty(exports, "mergeRegisteredWidgetsIntoRegistry", {
1535
+ enumerable: true,
1536
+ get: function() {
1537
+ return mergeRegisteredWidgetsIntoRegistry;
1538
+ }
1539
+ });
1540
+ Object.defineProperty(exports, "resolveHostedWidgetPackageManifestUrl", {
1541
+ enumerable: true,
1542
+ get: function() {
1543
+ return resolveHostedWidgetPackageManifestUrl;
1544
+ }
1545
+ });
1546
+ Object.defineProperty(exports, "subscribeToFluidWidgetsRegistry", {
1547
+ enumerable: true,
1548
+ get: function() {
1549
+ return subscribeToFluidWidgetsRegistry;
1550
+ }
1551
+ });
1552
+
1553
+ //# sourceMappingURL=widget-package-utils-BWn56ZFw.cjs.map