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