@adobe/uix-host-react 1.1.8 → 1.1.9-nightly.20260522

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Extensible.d.ts","sourceRoot":"","sources":["../../src/components/Extensible.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAIzB,cAAc;AACd,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IACnE;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,kBAAkB,EAAE,kBAAkB,CAAC;IACvC;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,sBAAsB,CAAC,EAAE,CACvB,UAAU,EAAE,mBAAmB,KAC5B,mBAAmB,CAAC;CAC1B;AAoDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,sBAAsB,GACvB,EAAE,iBAAiB,CAAC,eAAe,CAAC,qBAoHpC;AACD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"Extensible.d.ts","sourceRoot":"","sources":["../../src/components/Extensible.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA+C,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAIzB,cAAc;AACd,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IACnE;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,kBAAkB,EAAE,kBAAkB,CAAC;IACvC;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,sBAAsB,CAAC,EAAE,CACvB,UAAU,EAAE,mBAAmB,KAC5B,mBAAmB,CAAC;CAC1B;AAoDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,sBAAsB,GACvB,EAAE,iBAAiB,CAAC,eAAe,CAAC,qBA+GpC;AACD,eAAe,UAAU,CAAC"}
@@ -29,6 +29,10 @@ export interface ExtensibleDefaultProps extends Omit<HostConfig, "hostName"> {
29
29
  experienceShellEnvironment?: "prod" | "stage";
30
30
  extensionsListCallback?: (extensions: InstalledExtensions) => InstalledExtensions;
31
31
  }
32
+ /**
33
+ * ExtensibleWrapper component that provides extension support to React applications.
34
+ * @public
35
+ */
32
36
  export declare const ExtensibleWrapper: ({ appName, children, guestOptions, runtimeContainer, debug, sharedContext, experienceShellEnvironment, queryString, service, extensionPoint, version, disableExtensionManager, authConfig, scope, extensionsListCallback, }: PropsWithChildren<ExtensibleDefaultProps>) => ReactElement;
33
37
  export default ExtensibleWrapper;
34
38
  //# sourceMappingURL=ExtensibleWrapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensibleWrapper.d.ts","sourceRoot":"","sources":["../../../src/components/ExtensibleWrapper/ExtensibleWrapper.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG7D,OAAO,EAEL,mBAAmB,EAGnB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC;AAQzB,cAAc;AACd,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IAC1E;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,sBAAsB,CAAC,EAAE,CACvB,UAAU,EAAE,mBAAmB,KAC5B,mBAAmB,CAAC;CAC1B;AAED,eAAO,MAAM,iBAAiB,gOAgB3B,kBAAkB,sBAAsB,CAAC,KAAG,YAgE9C,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"ExtensibleWrapper.d.ts","sourceRoot":"","sources":["../../../src/components/ExtensibleWrapper/ExtensibleWrapper.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG7D,OAAO,EAEL,mBAAmB,EAGnB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC;AAQzB,cAAc;AACd,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IAC1E;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,sBAAsB,CAAC,EAAE,CACvB,UAAU,EAAE,mBAAmB,KAC5B,mBAAmB,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,gOAgB3B,kBAAkB,sBAAsB,CAAC,KAAG,YAgE9C,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -15,10 +15,12 @@
15
15
  * from Adobe.
16
16
  **************************************************************************/
17
17
  import { ExtensionsProvider, InstalledExtensions } from "@adobe/uix-host";
18
+ /** @internal */
18
19
  type ExtensionPoint = {
19
20
  extensionPoint: string;
20
21
  url: string;
21
22
  };
23
+ /** @public */
22
24
  export type ExtensionManagerExtension = {
23
25
  id: string;
24
26
  name: string;
@@ -32,10 +34,12 @@ export type ExtensionManagerExtension = {
32
34
  scope: Record<string, unknown>;
33
35
  configuration?: Record<string, unknown>;
34
36
  };
37
+ /** @internal */
35
38
  type AuthEMConfig = {
36
39
  schema: "Bearer" | "Basic";
37
40
  imsToken: string;
38
41
  };
42
+ /** @public */
39
43
  export interface ExtensionManagerConfig {
40
44
  apiKey: string;
41
45
  auth: AuthEMConfig;
@@ -46,7 +50,10 @@ export interface ExtensionManagerConfig {
46
50
  baseUrl: string;
47
51
  scope?: Record<string, string>;
48
52
  }
49
- /** Authentication configuration, including IMS Org ID, access token, and API key */
53
+ /**
54
+ * Authentication configuration, including IMS Org ID, access token, and API key
55
+ * @public
56
+ */
50
57
  export interface AuthConfig {
51
58
  /** IMS Org ID */
52
59
  imsOrg: string;
@@ -55,13 +62,19 @@ export interface AuthConfig {
55
62
  /** API key */
56
63
  apiKey: string;
57
64
  }
58
- /** Discovery configuration, including environment and repo Id */
65
+ /**
66
+ * Discovery configuration, including environment and repo Id
67
+ * @public
68
+ */
59
69
  export interface DiscoveryConfig {
60
70
  /** Environment level for backend Extension resolution services */
61
71
  experienceShellEnvironment?: "prod" | "stage";
62
72
  scope?: Record<string, string>;
63
73
  }
64
- /** Extension point ID */
74
+ /**
75
+ * Extension point ID
76
+ * @public
77
+ */
65
78
  export interface ExtensionPointId {
66
79
  /** Service name */
67
80
  service: string;
@@ -74,6 +87,7 @@ export interface ExtensionPointId {
74
87
  * Sets up new ExtensionsProvider with authentication and discovery information needed to fetch the list of
75
88
  * Extensions from AppRegistry and Extension Manager service, along with the query string portion of URL
76
89
  * to extract the information about development Extensions
90
+ * @public
77
91
  */
78
92
  export interface ExtensionsProviderConfig {
79
93
  /** Discovery configuration */
@@ -84,18 +98,21 @@ export interface ExtensionsProviderConfig {
84
98
  extensionPointId: ExtensionPointId;
85
99
  providerConfig: ExtensionProviderConfig;
86
100
  }
101
+ /** @public */
87
102
  export interface ExtensionProviderConfig {
88
103
  extensionManagerUrl?: string;
89
104
  appRegistryUrl?: string;
90
105
  disableExtensionManager?: boolean;
91
106
  }
107
+ /** @internal */
92
108
  export declare const getExtensionRegistryBaseUrl: (environment: "prod" | "stage" | undefined, registry: string | null) => string;
109
+ /** @internal */
93
110
  export declare const getExtensionManagerBaseUrl: (environment: "prod" | "stage" | undefined, extensionManager: string | null) => string;
94
111
  /**
95
112
  * Extracts programId and envId from the repo value
96
113
  * @param repo - the repo value
97
114
  * @returns object with programId and envId
98
- * @ignore
115
+ * @internal
99
116
  */
100
117
  export declare function extractProgramIdEnvId(repo: string): {
101
118
  programId: string;
@@ -105,11 +122,11 @@ export declare function extractProgramIdEnvId(repo: string): {
105
122
  * Builds the URL for fetching extensions from the Extension Manager service
106
123
  * @param config - the Extension Manager configuration
107
124
  * @returns the URL for fetching extensions
108
- * @ignore
125
+ * @internal
109
126
  */
110
127
  export declare function buildExtensionManagerUrl(config: ExtensionManagerConfig): string;
111
128
  /**
112
- * @ignore
129
+ * @internal
113
130
  */
114
131
  export declare function fetchExtensionsFromExtensionManager(config: ExtensionManagerConfig): Promise<ExtensionManagerExtension[]>;
115
132
  /**
@@ -117,12 +134,12 @@ export declare function fetchExtensionsFromExtensionManager(config: ExtensionMan
117
134
  * merges them into a list of Extensions. If an extension is disabled in the Extension Manager, it is removed from
118
135
  * the list.
119
136
  * Extension list from the App Registry is used as a base.
120
- * @ignore
137
+ * @internal
121
138
  */
122
139
  export declare function mergeExtensions(appRegistryExtensions: InstalledExtensions, extensionManagerExtensions: ExtensionManagerExtension[], extensionPointId: ExtensionPointId): InstalledExtensions;
123
140
  /**
124
141
  * Creates an extension manager extension provider
125
- * @ignore
142
+ * @internal
126
143
  */
127
144
  export declare function createExtensionManagerExtensionsProvider(discoveryConfig: DiscoveryConfig, authConfig: AuthConfig, providerConfig: ExtensionProviderConfig, extensionPointId: ExtensionPointId): ExtensionsProvider;
128
145
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionManagerProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ExtensibleWrapper/ExtensionManagerProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ExtensionManagerProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ExtensibleWrapper/ExtensionManagerProvider.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@
16
16
  **************************************************************************/
17
17
  import { ExtensionsProvider } from "@adobe/uix-host";
18
18
  import { ExtensionPointId } from "./ExtensionManagerProvider";
19
+ /** @public */
19
20
  export interface ExtUrlParams {
20
21
  [key: string]: string;
21
22
  }
@@ -23,21 +24,22 @@ export interface ExtUrlParams {
23
24
  * Validates if a URL is safe and only allows HTTP/HTTPS protocols
24
25
  * @param url - The URL string to validate
25
26
  * @returns true if the URL is valid and uses HTTP/HTTPS protocol, false otherwise
27
+ * @public
26
28
  */
27
29
  export declare function isValidHttpUrl(url: string): boolean;
28
30
  /**
29
31
  * Extracts extension URLs from the query string
30
- * @ignore
32
+ * @internal
31
33
  */
32
34
  export declare function extractExtUrlParams(queryString: string | undefined): ExtUrlParams;
33
35
  /**
34
36
  * Generates an extension ID from the extension URL
35
- * @ignore
37
+ * @internal
36
38
  */
37
39
  export declare function generateExtensionId(extensionUrl: string): string;
38
40
  /**
39
41
  * Creates an ExtensionsProvider that provides extensions from the URL
40
- * @ignore
42
+ * @internal
41
43
  */
42
44
  export declare function createUrlExtensionsProvider(extensionPointId: ExtensionPointId, queryString: string | undefined): ExtensionsProvider;
43
45
  //# sourceMappingURL=UrlExtensionProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UrlExtensionProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ExtensibleWrapper/UrlExtensionProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;4EAe4E;AAC5E,OAAO,EAAE,kBAAkB,EAAuB,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9D,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,YAAY,CAWd;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,kBAAkB,CAoCpB"}
1
+ {"version":3,"file":"UrlExtensionProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ExtensibleWrapper/UrlExtensionProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;4EAe4E;AAC5E,OAAO,EAAE,kBAAkB,EAAuB,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9D,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,YAAY,CAWd;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,kBAAkB,CAoCpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useExtensions.d.ts","sourceRoot":"","sources":["../../src/hooks/useExtensions.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,eAAe,EAEf,UAAU,EACX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAc,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,iBAAiB,CAAC;AAK5D;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,SAAS,CACvD,SAAQ,eAAe;IACvB,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;CAC1B;AAED,cAAc;AACd,MAAM,WAAW,mBAAmB,CAClC,QAAQ,SAAS,SAAS,EAC1B,QAAQ,SAAS,UAAU;IAE3B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC3B;AAED,cAAc;AACd,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,SAAS;IACtD;;;;OAIG;IACH,UAAU,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,SAAS,EAC1B,QAAQ,SAAS,UAAU,EAE3B,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACtE,IAAI,GAAE,OAAO,EAAO,GACnB,mBAAmB,CAAC,QAAQ,CAAC,CAqH/B"}
1
+ {"version":3,"file":"useExtensions.d.ts","sourceRoot":"","sources":["../../src/hooks/useExtensions.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,eAAe,EAEf,UAAU,EACX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAc,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,iBAAiB,CAAC;AAK5D;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,SAAS,CACvD,SAAQ,eAAe;IACvB,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;CAC1B;AAED,cAAc;AACd,MAAM,WAAW,mBAAmB,CAClC,QAAQ,SAAS,SAAS,EAC1B,QAAQ,SAAS,UAAU;IAE3B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC3B;AAED,cAAc;AACd,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,SAAS;IACtD;;;;OAIG;IACH,UAAU,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,SAAS,EAC1B,QAAQ,SAAS,UAAU,EAE3B,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACtE,IAAI,GAAE,OAAO,EAAO,GACnB,mBAAmB,CAAC,QAAQ,CAAC,CAoI/B"}
package/dist/index.js CHANGED
@@ -136,19 +136,11 @@ function Extensible({
136
136
  loadExtensions(host);
137
137
  }
138
138
  }, [debug, hostName, runtimeContainer, extensions]);
139
- if (!host) {
140
- return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, children);
141
- }
142
- return /* @__PURE__ */ React__default.default.createElement(
143
- ExtensionContext.Provider,
144
- {
145
- value: {
146
- host,
147
- extensionListFetched
148
- }
149
- },
150
- children
139
+ const contextValue = React.useMemo(
140
+ () => ({ host, extensionListFetched }),
141
+ [host, extensionListFetched]
151
142
  );
143
+ return /* @__PURE__ */ React__default.default.createElement(ExtensionContext.Provider, { value: contextValue }, children);
152
144
  }
153
145
  var OutsideOfExtensionContextError = class extends Error {
154
146
  constructor(msg) {
@@ -529,14 +521,7 @@ var ExtensibleWrapper = ({
529
521
  };
530
522
  var NO_EXTENSIONS = [];
531
523
  function useExtensions(configFactory, deps = []) {
532
- const { host, error } = useHost();
533
- if (error) {
534
- return {
535
- extensions: NO_EXTENSIONS,
536
- loading: false,
537
- error
538
- };
539
- }
524
+ const { host, error: contextError } = useHost();
540
525
  const [hostError, setHostError] = React.useState();
541
526
  const extensionPoints = React.useContext(ExtensibleComponentBoundaryContext);
542
527
  const boundryExtensionPointsAsString = extensionPoints == null ? void 0 : extensionPoints.map(
@@ -551,8 +536,13 @@ function useExtensions(configFactory, deps = []) {
551
536
  requires,
552
537
  provides,
553
538
  updateOn = "each"
554
- } = React.useMemo(() => configFactory(host), baseDeps);
539
+ } = React.useMemo(
540
+ () => host ? configFactory(host) : {},
541
+ baseDeps
542
+ );
555
543
  const getExtensions = React.useCallback(() => {
544
+ if (!host)
545
+ return NO_EXTENSIONS;
556
546
  const newExtensions = [];
557
547
  const guests = host.getLoadedGuests(requires);
558
548
  for (const guest of guests) {
@@ -568,6 +558,9 @@ function useExtensions(configFactory, deps = []) {
568
558
  }, [...baseDeps, requires]);
569
559
  const subscribe = React.useCallback(
570
560
  (handler) => {
561
+ if (!host)
562
+ return () => {
563
+ };
571
564
  const eventName = updateOn === "all" ? "loadallguests" : "guestload";
572
565
  host.addEventListener(eventName, handler);
573
566
  return () => {
@@ -577,13 +570,17 @@ function useExtensions(configFactory, deps = []) {
577
570
  [...baseDeps, updateOn]
578
571
  );
579
572
  const subscribeToUnload = React.useCallback((handler) => {
573
+ if (!host)
574
+ return () => {
575
+ };
580
576
  host.addEventListener("guestunload", handler);
581
577
  return () => {
582
578
  host.removeEventListener("guestunload", handler);
583
579
  };
584
580
  }, baseDeps);
585
- const [extensions, setExtensions] = React.useState(() => getExtensions());
581
+ const [extensions, setExtensions] = React.useState(NO_EXTENSIONS);
586
582
  React.useEffect(() => {
583
+ setExtensions(getExtensions());
587
584
  return subscribe(() => setExtensions(getExtensions()));
588
585
  }, [subscribe]);
589
586
  const unloadExtentionCallback = (e) => {
@@ -608,13 +605,21 @@ function useExtensions(configFactory, deps = []) {
608
605
  }
609
606
  }
610
607
  }, [provides, extensions]);
611
- React.useEffect(
612
- () => host.addEventListener(
608
+ React.useEffect(() => {
609
+ if (!host)
610
+ return;
611
+ return host.addEventListener(
613
612
  "error",
614
613
  (event) => setHostError(event.detail.error)
615
- ),
616
- baseDeps
617
- );
614
+ );
615
+ }, baseDeps);
616
+ if (contextError) {
617
+ return {
618
+ extensions: NO_EXTENSIONS,
619
+ loading: false,
620
+ error: contextError
621
+ };
622
+ }
618
623
  return {
619
624
  extensions,
620
625
  loading: extensions.length === 0 ? false : host.loading,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/Extensible.tsx","../src/extension-context.ts","../src/components/GuestUIFrame.tsx","../src/hooks/useHost.ts","../src/components/ExtensibleComponentBoundary.tsx","../src/components/ExtensibleWrapper/ExtensibleWrapper.tsx","../src/components/ExtensibleWrapper/ExtensionManagerProvider.ts","../src/components/ExtensibleWrapper/UrlExtensionProvider.ts","../src/hooks/useExtensions.ts","../src/hooks/useExtensionListFetched.ts"],"names":["React","useEffect","useRef","Host","createContext","useContext","useMemo","useState"],"mappings":"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","sourcesContent":["/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nexport * from \"@adobe/uix-host\";\nexport * from \"./components/index.js\";\nexport * from \"./hooks/index.js\";\nexport * from \"./extension-context\";\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport React, { useState, useEffect, useRef } from \"react\";\nimport type { PropsWithChildren } from \"react\";\nimport type {\n InstalledExtensions,\n ExtensionsProvider,\n HostConfig,\n PortOptions,\n SharedContextValues,\n} from \"@adobe/uix-host\";\nimport { Host } from \"@adobe/uix-host\";\nimport { ExtensionContext } from \"../extension-context.js\";\n\n/** @public */\nexport interface ExtensibleProps extends Omit<HostConfig, \"hostName\"> {\n /**\n * Unique name for identifying this extensible app. May be used as metadata in\n * extension registry in the future.\n */\n appName?: string;\n /**\n * Function which returns a promise for the full list of extensions.\n */\n extensionsProvider: ExtensionsProvider;\n /**\n * {@inheritDoc HostConfig.guestOptions}\n */\n guestOptions?: PortOptions;\n /**\n * {@inheritDoc HostConfig.sharedContext}\n */\n sharedContext?: SharedContextValues;\n extensionsListCallback?: (\n extensions: InstalledExtensions\n ) => InstalledExtensions;\n}\n\nfunction areExtensionsDifferent(\n set1: InstalledExtensions,\n set2: InstalledExtensions\n) {\n const ids1 = Object.keys(set1).sort();\n const ids2 = Object.keys(set2).sort();\n\n if (ids1.length !== ids2.length) {\n return true;\n }\n\n let isDifferent = false;\n\n ids1.forEach((id) => {\n if (isDifferent) {\n return;\n }\n\n const ext1 = set1[id];\n const ext2 = set2[id];\n\n if (typeof ext1 !== typeof ext2) {\n isDifferent = true;\n return;\n }\n\n if (typeof ext1 === \"string\" && typeof ext2 === \"string\") {\n if (ext1 !== ext2) {\n isDifferent = true;\n return;\n }\n }\n\n if (typeof ext1 === \"object\" && typeof ext2 === \"object\") {\n if (\n ext1.url !== ext2.url ||\n JSON.stringify(ext1.extensionPoints) !==\n JSON.stringify(ext2.extensionPoints) ||\n JSON.stringify(ext1.configuration) !==\n JSON.stringify(ext2.configuration)\n ) {\n isDifferent = true;\n return;\n }\n }\n });\n\n return isDifferent;\n}\n\n/**\n * Declares an extensible area in an app, and provides host and extension\n * objects to all descendents. The {@link useExtensions} hook can only be called\n * in a descendent of this component.\n *\n * @remarks\n * For many apps, there will be only one Extensible provider, fairly high in the\n * component tree. It is a context provider component that may be bundled with\n * other context providers in your app architecture.\n *\n * Each Extensible element creates one {@link @adobe/uix-host#Host} object and\n * one call to an extensions provider. If multiple Extensible elements are used,\n * this may cause redundant calls. Such a design should be carefully considered.\n *\n * @public\n */\nexport function Extensible({\n appName,\n children,\n extensionsProvider,\n guestOptions,\n runtimeContainer,\n debug,\n sharedContext,\n extensionsListCallback,\n}: PropsWithChildren<ExtensibleProps>) {\n const hostName = appName || window.location.host || \"mainframe\";\n\n const [extensions, setExtensions] = useState<InstalledExtensions>({});\n const [extensionListFetched, setExtensionListFetched] =\n useState<boolean>(false);\n const prevSharedContext = useRef(JSON.stringify(sharedContext));\n useEffect(() => {\n let cancelled = false;\n\n extensionsProvider()\n .then((loaded: InstalledExtensions) => {\n if (cancelled) {\n return;\n }\n setExtensions((prev) => {\n let newExtensions = loaded;\n\n if (extensionsListCallback && loaded) {\n newExtensions = extensionsListCallback(newExtensions);\n }\n\n const shouldUpdate = areExtensionsDifferent(prev, newExtensions);\n\n if (shouldUpdate) {\n return newExtensions;\n } else {\n return prev;\n }\n });\n })\n .catch((e: Error | unknown) => {\n if (!cancelled) {\n console.error(\"Fetching list of extensions failed!\", e);\n }\n })\n .finally(() => {\n if (!cancelled) {\n setExtensionListFetched(true);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [extensionsProvider, extensionsListCallback]);\n\n const [host, setHost] = useState<Host>();\n const hostRef = useRef<Host>();\n\n useEffect(() => {\n return () => {\n if (hostRef.current) {\n hostRef.current.unload().catch(() => {});\n hostRef.current = undefined;\n }\n };\n }, []);\n\n useEffect(() => {\n function logError(msg: string) {\n return (e: Error | unknown) => {\n const error = e instanceof Error ? e : new Error(String(e));\n console.error(msg, error, extensions, guestOptions);\n };\n }\n\n if (!extensions || !Object.keys(extensions).length) {\n return;\n }\n\n const loadExtensions = (hostInstance: Host) => {\n hostInstance\n .load(extensions, guestOptions)\n .catch(logError(\"Load of extensions failed!\"));\n };\n\n const sharedContextChanged =\n prevSharedContext.current !== JSON.stringify(sharedContext);\n\n if (sharedContextChanged) {\n prevSharedContext.current = JSON.stringify(sharedContext);\n }\n if (!host || sharedContextChanged) {\n if (hostRef.current) {\n hostRef.current.unload().catch(() => {});\n }\n const newHost = new Host({\n debug,\n hostName,\n runtimeContainer,\n sharedContext,\n });\n hostRef.current = newHost;\n setHost(newHost);\n loadExtensions(newHost);\n } else {\n loadExtensions(host);\n }\n }, [debug, hostName, runtimeContainer, extensions]);\n\n // skip render before host is initialized\n if (!host) {\n return <>{children}</>;\n }\n\n return (\n <ExtensionContext.Provider\n value={{\n host: host,\n extensionListFetched: extensionListFetched,\n }}\n >\n {children}\n </ExtensionContext.Provider>\n );\n}\nexport default Extensible;\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * @hidden\n */\nimport { createContext } from \"react\";\nimport { Host } from \"@adobe/uix-host\";\n\n/**\n * Context container with Host object and extensions load status.\n *\n * @internal\n */\nexport type ExtensibilityContext = {\n host: Host;\n extensionListFetched: boolean;\n};\n\n/**\n * @internal\n */\nexport const ExtensionContext = createContext<ExtensibilityContext>(\n {} as unknown as ExtensibilityContext\n);\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { CrossRealmObject, UIFrameRect, VirtualApi } from \"@adobe/uix-core\";\nimport React, { useEffect, useRef } from \"react\";\nimport type { IframeHTMLAttributes } from \"react\";\nimport { useHost } from \"../hooks/useHost.js\";\nimport type { AttrTokens, SandboxToken } from \"@adobe/uix-host\";\nimport { makeSandboxAttrs, requiredIframeProps } from \"@adobe/uix-host\";\n\n/**\n * @internal\n */\ntype ReactIframeProps = IframeHTMLAttributes<HTMLIFrameElement>;\n\n/**\n * @public\n */\ntype FrameProps = Omit<ReactIframeProps, \"sandbox\">;\n\n/** @public */\nexport interface GuestUIProps extends FrameProps {\n guestId: string;\n /**\n * Receives the Penpal context when the frame is mounted.\n */\n onConnect?: () => void;\n /**\n * Called when the frame disconnects and unmounts.\n */\n onDisconnect?: () => void;\n /**\n * Called when the connection process throws an exception\n */\n onConnectionError?: (error: Error) => void;\n /**\n * Called when the document in the iframe changes size.\n */\n onResize?: (dimensions: UIFrameRect) => void;\n /**\n * Additional sandbox attributes GuestUIFrame might need.\n */\n sandbox?: AttrTokens<SandboxToken>;\n /**\n * Optional custom URL or path.\n */\n src: string;\n /**\n * Host methods to provide only to the guest inside all iframes.\n */\n methods?: VirtualApi;\n /**\n * Host methods to provide only to the guest inside this iframe.\n */\n privateMethods?: VirtualApi;\n}\n\nconst defaultIFrameProps: FrameProps = {\n width: \"100%\",\n height: \"100%\",\n style: {\n display: \"block\",\n border: \"none\",\n },\n};\n\nconst defaultSandbox = \"allow-scripts allow-forms allow-same-origin\";\n\n/**\n * An iframe that attaches to a running GuestServer, to display visible UI pages\n * delivered by the Extension server.\n * @public\n */\nexport const GuestUIFrame = ({\n guestId,\n src = \"\",\n onConnect,\n onDisconnect,\n onConnectionError,\n onResize,\n methods,\n privateMethods,\n sandbox = \"\",\n style,\n ...customIFrameProps\n}: GuestUIProps) => {\n const ref = useRef<HTMLIFrameElement>();\n const { host } = useHost();\n if (!host) {\n return null;\n }\n const guest = host.guests.get(guestId);\n const frameUrl = new URL(src, guest.url.href);\n\n useEffect(() => {\n if (ref.current) {\n let mounted = true;\n let connection: CrossRealmObject<VirtualApi>;\n const connectionFrame = ref.current;\n if (methods) {\n guest.provide(methods);\n }\n const connecting = guest.attachUI(connectionFrame, privateMethods);\n connecting\n .then((c) => {\n connection = c;\n if (!mounted) {\n c.tunnel.destroy();\n } else if (onConnect) {\n onConnect();\n }\n })\n .catch((error: Error) => {\n if (mounted && !connection && connectionFrame === ref.current) {\n const frameError = new Error(\n `GuestUIFrame connection failed: ${\n (error && error.stack) || error\n }`\n );\n Object.assign(frameError, {\n original: error,\n ref,\n guest,\n host,\n });\n if (onConnectionError) onConnectionError(frameError);\n }\n });\n return () => {\n mounted = false;\n if (connection) {\n connection.tunnel.destroy();\n }\n };\n }\n }, [guest.id]);\n\n useEffect(() => {\n if (ref.current && onResize) {\n const currentFrame = ref.current;\n return guest.addEventListener(\n \"guestresize\",\n ({ detail: { guestPort, iframe, dimensions } }) => {\n if (guestPort.id === guest.id && iframe === currentFrame) {\n onResize(dimensions);\n }\n }\n );\n }\n }, [ref.current, guest.id, onResize]);\n\n return (\n <iframe\n {...defaultIFrameProps}\n ref={ref}\n src={frameUrl.href}\n name={`uix-guest-${guest.id}`}\n sandbox={\n sandbox\n ? makeSandboxAttrs(defaultSandbox, sandbox).join(\" \")\n : defaultSandbox\n }\n style={\n style\n ? { ...style, ...defaultIFrameProps.style }\n : defaultIFrameProps.style\n }\n {...customIFrameProps}\n {...requiredIframeProps}\n />\n );\n};\nexport default GuestUIFrame;\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { useContext } from \"react\";\nimport { Host } from \"@adobe/uix-host\";\nimport { ExtensionContext, ExtensibilityContext } from \"../extension-context\";\n\n/**\n * @public\n */\nexport class OutsideOfExtensionContextError extends Error {\n outsideOfExtensionContext: boolean;\n constructor(msg: string) {\n super(msg);\n this.outsideOfExtensionContext = true;\n Object.setPrototypeOf(this, OutsideOfExtensionContextError.prototype);\n }\n}\n\n/** @public */\ntype UseHostResponse =\n | { host: undefined; error: Error }\n | { host: Host; error: undefined };\n\n/**\n * Retrieve the {@link @adobe/uix-host#Host} object hosting all extensions inside the current parent provider.\n *\n * @remarks Returns a `{ host, error }` tuple, not the host object directly.\n * @beta\n */\nexport function useHost(): UseHostResponse {\n const extensionsInfo = useContext<ExtensibilityContext>(ExtensionContext);\n\n if (!(extensionsInfo.host instanceof Host)) {\n const error = new OutsideOfExtensionContextError(\n \"Attempt to use extensions outside of ExtensionContext. Wrap extensible part of application with Extensible component.\"\n );\n return {\n host: undefined,\n error,\n };\n }\n return { error: undefined, host: extensionsInfo.host };\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * @hidden\n */\nimport React, { createContext } from \"react\";\nimport type { PropsWithChildren } from \"react\";\nimport { ExtensionRegistryEndpointRegistration } from \"@adobe/uix-host\";\n\n/**\n * @internal\n */\nexport const ExtensibleComponentBoundaryContext = createContext<\n ExtensionRegistryEndpointRegistration[]\n>(null as ExtensionRegistryEndpointRegistration[]);\n\n/** @public */\nexport type ExtensibleComponentProps = PropsWithChildren<{\n extensionPoints: ExtensionRegistryEndpointRegistration[];\n}>;\n\n/**\n * Wrapper that adds an extension point context to subcomponent tree.\n *\n * @public\n */\nexport const ExtensibleComponentBoundary = ({\n extensionPoints,\n children,\n}: ExtensibleComponentProps) => {\n return (\n <ExtensibleComponentBoundaryContext.Provider value={extensionPoints}>\n {children}\n </ExtensibleComponentBoundaryContext.Provider>\n );\n};\n","/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport type { PropsWithChildren, ReactElement } from \"react\";\nimport React, { useMemo } from \"react\";\nimport { Extensible } from \"../Extensible\";\nimport {\n combineExtensionsFromProviders,\n InstalledExtensions,\n mutedProvider,\n type ExtensionsProvider,\n type HostConfig,\n type PortOptions,\n type SharedContextValues,\n} from \"@adobe/uix-host\";\nimport {\n ExtensionPointId,\n ExtensionProviderConfig,\n createExtensionManagerExtensionsProvider,\n} from \"./ExtensionManagerProvider\";\nimport { createUrlExtensionsProvider } from \"./UrlExtensionProvider\";\n\n/** @public */\nexport interface ExtensibleDefaultProps extends Omit<HostConfig, \"hostName\"> {\n /**\n * Unique name for identifying this extensible app. May be used as metadata in\n * extension registry in the future.\n */\n appName?: string;\n /**\n * {@inheritDoc HostConfig.guestOptions}\n */\n guestOptions?: PortOptions;\n /**\n * {@inheritDoc HostConfig.sharedContext}\n */\n sharedContext?: SharedContextValues;\n queryString?: string;\n service: string;\n extensionPoint: string;\n version: string;\n disableExtensionManager?: boolean;\n authConfig: {\n imsToken: string;\n imsOrg: string;\n apiKey: string;\n };\n scope?: Record<string, any>;\n experienceShellEnvironment?: \"prod\" | \"stage\";\n extensionsListCallback?: (\n extensions: InstalledExtensions\n ) => InstalledExtensions;\n}\n\nexport const ExtensibleWrapper = ({\n appName,\n children,\n guestOptions,\n runtimeContainer,\n debug,\n sharedContext,\n experienceShellEnvironment,\n queryString,\n service,\n extensionPoint,\n version,\n disableExtensionManager,\n authConfig,\n scope,\n extensionsListCallback,\n}: PropsWithChildren<ExtensibleDefaultProps>): ReactElement => {\n const defaultExtensionsProvider = useMemo(() => {\n const extensionPointId: ExtensionPointId = {\n service,\n name: extensionPoint,\n version,\n };\n const params: URLSearchParams = new URLSearchParams(queryString ?? \"\");\n const extensionManagerUrlOverride = params.get(\"em\");\n const appRegistryUrlOverride = params.get(\"er\");\n const urlExtensionsProvider: ExtensionsProvider =\n createUrlExtensionsProvider(extensionPointId, queryString);\n const providerConfig: ExtensionProviderConfig = {\n disableExtensionManager,\n };\n\n if (extensionManagerUrlOverride) {\n providerConfig.extensionManagerUrl = extensionManagerUrlOverride;\n }\n\n if (appRegistryUrlOverride) {\n providerConfig.appRegistryUrl = appRegistryUrlOverride;\n }\n\n const extensionManagerExtensionsProvider: ExtensionsProvider =\n createExtensionManagerExtensionsProvider(\n {\n experienceShellEnvironment,\n scope,\n },\n authConfig,\n providerConfig,\n extensionPointId\n );\n\n const extenstions = combineExtensionsFromProviders(\n urlExtensionsProvider,\n mutedProvider(extensionManagerExtensionsProvider)\n );\n\n return extenstions;\n }, [\n experienceShellEnvironment,\n queryString,\n service,\n extensionPoint,\n version,\n disableExtensionManager,\n authConfig,\n scope,\n ]);\n return (\n <Extensible\n extensionsProvider={defaultExtensionsProvider}\n appName={appName}\n runtimeContainer={runtimeContainer}\n debug={debug}\n guestOptions={guestOptions}\n sharedContext={sharedContext}\n extensionsListCallback={extensionsListCallback}\n >\n {children}\n </Extensible>\n );\n};\n\nexport default ExtensibleWrapper;\n","/*************************************************************************\n * ADOBE CONFIDENTIAL\n * ___________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n **************************************************************************/\n\nimport {\n createExtensionRegistryAsObjectsProvider,\n ExtensionsProvider,\n InstalledExtensions,\n} from \"@adobe/uix-host\";\n\nconst EXTENSION_MANAGER_URL_PROD = \"https://aemx-mngr.adobe.io\";\nconst EXTENSION_MANAGER_URL_STAGE = \"https://aemx-mngr-stage.adobe.io\";\n\nconst APP_REGISTRY_URL_PROD = \"https://appregistry.adobe.io\";\nconst APP_REGISTRY_URL_STAGE = \"https://appregistry-stage.adobe.io\";\n\n// Extension Manager stores information about extension points that a particular extension implements\n// in the \"extensionPoints\" array of objects of the following \"ExtensionPoint\" type\n// where \"extensionPoint\" is the name of the extension point, for example, \"aem/assets/details/1\"\n// \"url\" is the extension url for the specified extension point\ntype ExtensionPoint = {\n extensionPoint: string;\n url: string;\n};\nexport type ExtensionManagerExtension = {\n id: string;\n name: string;\n title: string;\n description: string;\n status: string;\n supportEmail: string;\n extId: string;\n disabled: boolean;\n extensionPoints: ExtensionPoint[];\n scope: Record<string, unknown>;\n configuration?: Record<string, unknown>;\n};\n\ntype AuthEMConfig = {\n schema: \"Bearer\" | \"Basic\";\n imsToken: string;\n};\nexport interface ExtensionManagerConfig {\n apiKey: string;\n auth: AuthEMConfig;\n service: string;\n extensionPoint: string;\n version: string;\n imsOrg: string;\n baseUrl: string;\n scope?: Record<string, string>;\n}\n\n/** Authentication configuration, including IMS Org ID, access token, and API key */\nexport interface AuthConfig {\n /** IMS Org ID */\n imsOrg: string;\n /** Access token for the user */\n imsToken: string;\n /** API key */\n apiKey: string;\n}\n\n/** Discovery configuration, including environment and repo Id */\nexport interface DiscoveryConfig {\n /** Environment level for backend Extension resolution services */\n experienceShellEnvironment?: \"prod\" | \"stage\";\n scope?: Record<string, string>;\n}\n\n/** Extension point ID */\nexport interface ExtensionPointId {\n /** Service name */\n service: string;\n /** Extension point name */\n name: string;\n /** Extension point version */\n version: string;\n}\n\n/**\n * Sets up new ExtensionsProvider with authentication and discovery information needed to fetch the list of\n * Extensions from AppRegistry and Extension Manager service, along with the query string portion of URL\n * to extract the information about development Extensions\n */\nexport interface ExtensionsProviderConfig {\n /** Discovery configuration */\n discoveryConfig: DiscoveryConfig;\n /** Authentication configuration */\n authConfig: AuthConfig;\n /** Extension point ID */\n extensionPointId: ExtensionPointId;\n providerConfig: ExtensionProviderConfig;\n}\n\nexport interface ExtensionProviderConfig {\n extensionManagerUrl?: string;\n appRegistryUrl?: string;\n disableExtensionManager?: boolean;\n}\nexport const getExtensionRegistryBaseUrl = (\n environment: \"prod\" | \"stage\" | undefined,\n registry: string | null\n): string =>\n environment === \"prod\"\n ? APP_REGISTRY_URL_PROD\n : registry ?? APP_REGISTRY_URL_STAGE;\n\nexport const getExtensionManagerBaseUrl = (\n environment: \"prod\" | \"stage\" | undefined,\n extensionManager: string | null\n): string =>\n environment === \"prod\"\n ? EXTENSION_MANAGER_URL_PROD\n : extensionManager ?? EXTENSION_MANAGER_URL_STAGE;\n\n/**\n * Extracts programId and envId from the repo value\n * @param repo - the repo value\n * @returns object with programId and envId\n * @ignore\n */\nexport function extractProgramIdEnvId(repo: string): {\n programId: string;\n envId: string;\n} {\n const regex: RegExp = /p(\\d+)-e(\\d+)/;\n const match: RegExpMatchArray | null = regex.exec(repo);\n if (!match) {\n throw new Error(\"Error parsing a repo value\");\n }\n\n return {\n programId: match[1],\n envId: match[2],\n };\n}\n\n/**\n * Builds the URL for fetching extensions from the Extension Manager service\n * @param config - the Extension Manager configuration\n * @returns the URL for fetching extensions\n * @ignore\n */\nexport function buildExtensionManagerUrl(\n config: ExtensionManagerConfig\n): string {\n const scope = config.scope\n ? Object.fromEntries(\n Object.entries(config.scope).map(([k, v]) => [`scope.${k}`, v])\n )\n : {};\n const extensionPoints: string = `${config.service}/${config.extensionPoint}/${config.version}`;\n const queryParams = new URLSearchParams({\n ...scope,\n extensionPoints,\n });\n\n return `${config.baseUrl}/v2/extensions?${queryParams.toString()}`;\n}\n\n/**\n * @ignore\n */\nexport async function fetchExtensionsFromExtensionManager(\n config: ExtensionManagerConfig\n): Promise<ExtensionManagerExtension[]> {\n const resp: Response = await fetch(buildExtensionManagerUrl(config), {\n headers: {\n Authorization: `Bearer ${config.auth.imsToken}`,\n \"x-api-key\": config.apiKey,\n \"x-org-id\": config.imsOrg,\n },\n });\n\n if (resp.status !== 200) {\n throw new Error(\n `Extension Manager returned non-200 response (${\n resp.status\n }): ${await resp.text()}`\n );\n }\n\n return resp.json();\n}\n\n/**\n * Takes an array of extensions from the App Registry, an array of extensions from the Extension Manager, and\n * merges them into a list of Extensions. If an extension is disabled in the Extension Manager, it is removed from\n * the list.\n * Extension list from the App Registry is used as a base.\n * @ignore\n */\nexport function mergeExtensions(\n appRegistryExtensions: InstalledExtensions,\n extensionManagerExtensions: ExtensionManagerExtension[],\n extensionPointId: ExtensionPointId\n): InstalledExtensions {\n const mergedExtensions: InstalledExtensions = Object.assign(\n appRegistryExtensions,\n {}\n );\n extensionManagerExtensions.forEach((extension: ExtensionManagerExtension) => {\n if (extension.disabled) {\n // remove disabled extensions\n delete mergedExtensions[extension.name];\n } else {\n const extPoint: ExtensionPoint | undefined =\n extension.extensionPoints.find(\n (_extensionPoint: ExtensionPoint) =>\n _extensionPoint.extensionPoint ===\n `${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version}`\n );\n if (extPoint) {\n // add a new extension record or replace the existing one by an extension record from Extension Manager\n // extension points are useful for filtering out extensions\n mergedExtensions[extension.name] = {\n id: extension.name,\n url: extPoint.url,\n configuration: extension.configuration,\n extensionPoints: extension.extensionPoints.map(\n (point) => point.extensionPoint\n ),\n };\n } else {\n //this should never happen because we query Extension Manager service for our specific extension point\n console.warn(\n `Extension point ${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version} not found for extension ${extension.name}`\n );\n }\n }\n });\n\n return mergedExtensions;\n}\n\nasync function getExtensionManagerExtensions(\n discoveryConfig: DiscoveryConfig,\n authConfig: AuthConfig,\n providerConfig: ExtensionProviderConfig,\n extensionPointId: ExtensionPointId\n): Promise<InstalledExtensions> {\n const config = {\n apiKey: authConfig.apiKey,\n auth: {\n schema: \"Bearer\",\n imsToken: authConfig.imsToken,\n },\n service: extensionPointId.service,\n extensionPoint: extensionPointId.name,\n version: extensionPointId.version,\n imsOrg: authConfig.imsOrg,\n scope: discoveryConfig.scope,\n };\n\n const appRegistryConfig = {\n ...config,\n baseUrl: getExtensionRegistryBaseUrl(\n discoveryConfig.experienceShellEnvironment,\n providerConfig.appRegistryUrl\n ),\n } as ExtensionManagerConfig;\n const appRegistryExtensionsProvider: ExtensionsProvider =\n createExtensionRegistryAsObjectsProvider(appRegistryConfig);\n\n const extensionManagerConfiguration = {\n ...config,\n baseUrl: getExtensionManagerBaseUrl(\n discoveryConfig.experienceShellEnvironment,\n providerConfig.extensionManagerUrl\n ),\n } as ExtensionManagerConfig;\n const [appRegistryExtensions, extensionManagerExtensions] = await Promise.all(\n [\n appRegistryExtensionsProvider(),\n providerConfig.disableExtensionManager\n ? []\n : fetchExtensionsFromExtensionManager(extensionManagerConfiguration),\n ]\n );\n\n if (providerConfig.disableExtensionManager) {\n return appRegistryExtensions;\n } else {\n return mergeExtensions(\n appRegistryExtensions,\n extensionManagerExtensions,\n extensionPointId\n );\n }\n}\n\n/**\n * Creates an extension manager extension provider\n * @ignore\n */\nexport function createExtensionManagerExtensionsProvider(\n discoveryConfig: DiscoveryConfig,\n authConfig: AuthConfig,\n providerConfig: ExtensionProviderConfig,\n extensionPointId: ExtensionPointId\n): ExtensionsProvider {\n return () => {\n return getExtensionManagerExtensions(\n discoveryConfig,\n authConfig,\n providerConfig,\n extensionPointId\n );\n };\n}\n","/*************************************************************************\n * ADOBE CONFIDENTIAL\n * ___________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n **************************************************************************/\nimport { ExtensionsProvider, InstalledExtensions } from \"@adobe/uix-host\";\nimport { Extension } from \"@adobe/uix-core\";\nimport { ExtensionPointId } from \"./ExtensionManagerProvider\";\nconst EXT_PARAM_PREFIX = \"ext\";\n\nexport interface ExtUrlParams {\n [key: string]: string;\n}\n\n/**\n * Validates if a URL is safe and only allows HTTP/HTTPS protocols\n * @param url - The URL string to validate\n * @returns true if the URL is valid and uses HTTP/HTTPS protocol, false otherwise\n */\nexport function isValidHttpUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n\n return parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts extension URLs from the query string\n * @ignore\n */\nexport function extractExtUrlParams(\n queryString: string | undefined\n): ExtUrlParams {\n if (!queryString) {\n return {};\n }\n const params: URLSearchParams = new URLSearchParams(queryString);\n return Array.from(params.entries()).reduce((extParams, [key, value]) => {\n if (key === EXT_PARAM_PREFIX || key.startsWith(`${EXT_PARAM_PREFIX}.`)) {\n extParams[key] = value;\n }\n return extParams;\n }, {} as ExtUrlParams);\n}\n\n/**\n * Generates an extension ID from the extension URL\n * @ignore\n */\nexport function generateExtensionId(extensionUrl: string): string {\n return extensionUrl.replace(/\\W/g, \"_\");\n}\n\n/**\n * Creates an ExtensionsProvider that provides extensions from the URL\n * @ignore\n */\nexport function createUrlExtensionsProvider(\n extensionPointId: ExtensionPointId,\n queryString: string | undefined\n): ExtensionsProvider {\n const extUrlParams: ExtUrlParams = extractExtUrlParams(queryString);\n\n const extensionUrls: string[] = Object.keys(extUrlParams)\n .filter(\n (extParam) =>\n extParam === EXT_PARAM_PREFIX ||\n extParam ===\n `${EXT_PARAM_PREFIX}.${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version}`\n )\n .flatMap((extParam) => {\n const paramValue = extUrlParams[extParam];\n // If it's a single value, return it in an array. If it's already an array, return it as is.\n if (Array.isArray(paramValue)) {\n return paramValue.filter((param) => isValidHttpUrl(param));\n } else {\n return isValidHttpUrl(paramValue) ? [paramValue] : [];\n }\n });\n\n const installedExtensions: InstalledExtensions = extensionUrls\n .map((extensionUrl: string) => {\n return {\n id: generateExtensionId(extensionUrl),\n url: extensionUrl,\n extensionPoints: [\n `${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version}`,\n ],\n } as Extension;\n })\n .reduce((acc: InstalledExtensions, extension: Extension) => {\n acc[extension.id] = extension;\n return acc;\n }, {} as InstalledExtensions);\n\n return async () => installedExtensions;\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type {\n GuestConnection,\n GuestApis,\n RemoteGuestApis,\n RemoteGuestApiNS,\n VirtualApi,\n} from \"@adobe/uix-core\";\n\nimport { Host, HostEvents } from \"@adobe/uix-host\";\nimport type { CapabilitySpec, Port } from \"@adobe/uix-host\";\nimport { useHost } from \"./useHost\";\nimport { ExtensibleComponentBoundaryContext } from \"../components/ExtensibleComponentBoundary\";\nimport { ExtensionRegistryEndpointRegistration } from \"@adobe/uix-host\";\n\n/**\n * @internal\n */\nexport interface TypedGuestConnection<T extends GuestApis>\n extends GuestConnection {\n id: GuestConnection[\"id\"];\n apis: RemoteGuestApis<T>;\n}\n\n/** @public */\nexport interface UseExtensionsConfig<\n Incoming extends GuestApis,\n Outgoing extends VirtualApi\n> {\n /**\n * A {@link @adobe/uix-host#CapabilitySpec} describing the namespaced methods\n * extensions must implement to be used by this component.\n *\n * @remarks\n * This declaration is used to filter the extensions that will be\n * returned; if they don't implement those methods, they will be filtered out.\n */\n requires?: CapabilitySpec<Required<Incoming>>;\n /**\n * A namespaced object of methods which extensions will be able to call.\n *\n * @remarks This is the counterpart of `requires`; in `requires`, the you\n * describes methods the extension must implement that your host code will\n * call, and in `provides`, you implement host methods that extensions will be\n * able to call.\n *\n * Most cases for host-side methods will use the state of the component. This\n * can cause unexpected bugs in React if the config callback is run on every\n * render. **useExtensions caches the config callback by default!**\n * So remember to pass a deps array, so that the config callback re-runs under\n * the right conditions.\n */\n provides?: Outgoing;\n /**\n * Sets when re-render is triggered on extension load.\n *\n * @remarks\n * Set to `each` to trigger a component re-render every time an individual\n * extension loads, which may result in multiple UI updates. Set to `all` to\n * wait until all extensions have loaded to re-render the component.\n * @defaultValue \"each\"\n */\n updateOn?: \"each\" | \"all\";\n}\n\n/** @public */\nexport interface UseExtensionsResult<T extends GuestApis> {\n /**\n * A list of loaded guests which implement the methods specified in\n * `requires`, represented as {@link @adobe/uix-host#Port} objects which\n * present methods to be called.\n */\n extensions: TypedGuestConnection<T>[];\n /**\n * This is `true` until all extensions are loaded. Use for rendering spinners\n * or other intermediate UI.\n */\n loading: boolean;\n /**\n * Populated with an Error if there were any problems during the load process.\n */\n error?: Error;\n}\n\nconst NO_EXTENSIONS: [] = [];\n\n/**\n * Fetch extensions which implement an API, provide them methods, and use them.\n *\n * @remarks `useExtensions` does three things at once:\n * - Gets all extensions which implement the APIs described in the `require` field\n * - Exposes any functions defined in the `provide` field to those extensions\n * - Returns an object whose `extensions` property is a list of `Port` objects representing those extensions\n *\n * useExtensions will trigger a re-render when extensions load. You can choose whether it triggers that rerender as each extension loads, or only after all extensions have loaded.\n * @public\n */\nexport function useExtensions<\n Incoming extends GuestApis,\n Outgoing extends VirtualApi\n>(\n configFactory: (host: Host) => UseExtensionsConfig<Incoming, Outgoing>,\n deps: unknown[] = []\n): UseExtensionsResult<Incoming> {\n const { host, error } = useHost();\n if (error) {\n return {\n extensions: NO_EXTENSIONS,\n loading: false,\n error,\n };\n }\n const [hostError, setHostError] = useState<Error>();\n const extensionPoints = useContext(ExtensibleComponentBoundaryContext);\n const boundryExtensionPointsAsString = extensionPoints?.map(\n ({\n service,\n extensionPoint,\n version,\n }: ExtensionRegistryEndpointRegistration) =>\n `${service}/${extensionPoint}/${version}`\n );\n const baseDeps = [host, ...deps];\n const {\n requires,\n provides,\n updateOn = \"each\",\n } = useMemo(() => configFactory(host), baseDeps);\n\n const getExtensions = useCallback(() => {\n const newExtensions = [];\n const guests = host.getLoadedGuests(requires);\n\n // Extension filtering: If the boundary is provided, only return extensions which have extensionPoint\n // specified in a provided boundry. Otherwise no filtering is done.\n for (const guest of guests) {\n const allExtensionPoints: string[] =\n getAllExtensionPointsFromGuest(guest);\n\n if (\n !boundryExtensionPointsAsString ||\n !allExtensionPoints.length ||\n isGuestExtensionPointInBoundary(\n boundryExtensionPointsAsString,\n allExtensionPoints\n )\n ) {\n newExtensions.push(guest as unknown as TypedGuestConnection<Incoming>);\n }\n }\n return newExtensions.length === 0 ? NO_EXTENSIONS : newExtensions;\n }, [...baseDeps, requires]);\n\n const subscribe = useCallback(\n (handler: EventListener) => {\n const eventName = updateOn === \"all\" ? \"loadallguests\" : \"guestload\";\n host.addEventListener(eventName, handler);\n\n return () => {\n host.removeEventListener(eventName, handler);\n };\n },\n [...baseDeps, updateOn]\n );\n\n const subscribeToUnload = useCallback((handler: EventListener) => {\n host.addEventListener(\"guestunload\", handler);\n\n return () => {\n host.removeEventListener(\"guestunload\", handler);\n };\n }, baseDeps);\n\n const [extensions, setExtensions] = useState(() => getExtensions());\n\n useEffect(() => {\n return subscribe(() => setExtensions(getExtensions()));\n }, [subscribe]);\n\n const unloadExtentionCallback = (e: CustomEvent) => {\n const eventDetail = e.detail;\n const guest = eventDetail.guest as Port<GuestApis>;\n\n if (guest && guest.id) {\n setExtensions((prevExtensions) => {\n const filtered = prevExtensions.filter(\n (ext) => ext.id !== guest.id || ext.url !== guest.url\n );\n return filtered.length === 0 ? NO_EXTENSIONS : filtered;\n });\n }\n };\n\n useEffect(() => {\n return subscribeToUnload(unloadExtentionCallback);\n }, [subscribeToUnload]);\n\n useEffect(() => {\n for (const guest of extensions) {\n if (provides) {\n guest.provide(provides);\n }\n }\n }, [provides, extensions]);\n\n useEffect(\n () =>\n host.addEventListener(\n \"error\",\n (event: Extract<HostEvents, { detail: { error: Error } }>) =>\n setHostError(event.detail.error)\n ),\n baseDeps\n );\n\n return {\n extensions,\n loading: extensions.length === 0 ? false : host.loading,\n error: hostError,\n };\n}\n\n/**\n * Each extension/guest can have\n * 1. `extensioPoints` field as an array of strings\n * 2. Metadata with array of extensionPoints. If the metadata is present, we need to use it for fitering the extensions.\n * Returns cumulative extension points.\n * @param guest\n * @returns array of extension points as strings\n */\nfunction getAllExtensionPointsFromGuest(guest: Port<GuestApis>): string[] {\n try {\n const guestExtensionPointsFromMetadata = guest.metadata?.extensions?.map(\n (extension: { extensionPoint: string }) => extension?.extensionPoint\n );\n const allExtensionPoints = [\n ...(guest.extensionPoints || []),\n ...(guestExtensionPointsFromMetadata || []),\n ];\n return allExtensionPoints;\n } catch {\n console.error(\n \"Error occurred while getting extension points from guest and metadata. Extension boundaries will not be effective.\"\n );\n return [];\n }\n}\n\nfunction isGuestExtensionPointInBoundary(\n boundryExtensionPointsAsString: string[],\n guestExtensionPoints: string[]\n) {\n return (\n boundryExtensionPointsAsString?.length &&\n guestExtensionPoints?.length &&\n guestExtensionPoints.some((extensionPoint) =>\n boundryExtensionPointsAsString.includes(extensionPoint)\n )\n );\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { useContext } from \"react\";\nimport {\n ExtensionContext,\n ExtensibilityContext,\n} from \"../extension-context.js\";\n\n/**\n * Indicates if external extensions provider was processed. Returns true after passing extension list to the Host.\n *\n * @beta\n */\nexport function useExtensionListFetched(): boolean {\n const extensionsInfo = useContext<ExtensibilityContext>(ExtensionContext);\n\n return extensionsInfo.extensionListFetched;\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/Extensible.tsx","../src/extension-context.ts","../src/components/GuestUIFrame.tsx","../src/hooks/useHost.ts","../src/components/ExtensibleComponentBoundary.tsx","../src/components/ExtensibleWrapper/ExtensibleWrapper.tsx","../src/components/ExtensibleWrapper/ExtensionManagerProvider.ts","../src/components/ExtensibleWrapper/UrlExtensionProvider.ts","../src/hooks/useExtensions.ts","../src/hooks/useExtensionListFetched.ts"],"names":["React","useEffect","useRef","Host","createContext","useMemo","useContext","useState"],"mappings":"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","sourcesContent":["/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nexport * from \"@adobe/uix-host\";\nexport * from \"./components/index.js\";\nexport * from \"./hooks/index.js\";\nexport * from \"./extension-context\";\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport React, { useState, useEffect, useRef, useMemo } from \"react\";\nimport type { PropsWithChildren } from \"react\";\nimport type {\n InstalledExtensions,\n ExtensionsProvider,\n HostConfig,\n PortOptions,\n SharedContextValues,\n} from \"@adobe/uix-host\";\nimport { Host } from \"@adobe/uix-host\";\nimport { ExtensionContext } from \"../extension-context.js\";\n\n/** @public */\nexport interface ExtensibleProps extends Omit<HostConfig, \"hostName\"> {\n /**\n * Unique name for identifying this extensible app. May be used as metadata in\n * extension registry in the future.\n */\n appName?: string;\n /**\n * Function which returns a promise for the full list of extensions.\n */\n extensionsProvider: ExtensionsProvider;\n /**\n * {@inheritDoc HostConfig.guestOptions}\n */\n guestOptions?: PortOptions;\n /**\n * {@inheritDoc HostConfig.sharedContext}\n */\n sharedContext?: SharedContextValues;\n extensionsListCallback?: (\n extensions: InstalledExtensions\n ) => InstalledExtensions;\n}\n\nfunction areExtensionsDifferent(\n set1: InstalledExtensions,\n set2: InstalledExtensions\n) {\n const ids1 = Object.keys(set1).sort();\n const ids2 = Object.keys(set2).sort();\n\n if (ids1.length !== ids2.length) {\n return true;\n }\n\n let isDifferent = false;\n\n ids1.forEach((id) => {\n if (isDifferent) {\n return;\n }\n\n const ext1 = set1[id];\n const ext2 = set2[id];\n\n if (typeof ext1 !== typeof ext2) {\n isDifferent = true;\n return;\n }\n\n if (typeof ext1 === \"string\" && typeof ext2 === \"string\") {\n if (ext1 !== ext2) {\n isDifferent = true;\n return;\n }\n }\n\n if (typeof ext1 === \"object\" && typeof ext2 === \"object\") {\n if (\n ext1.url !== ext2.url ||\n JSON.stringify(ext1.extensionPoints) !==\n JSON.stringify(ext2.extensionPoints) ||\n JSON.stringify(ext1.configuration) !==\n JSON.stringify(ext2.configuration)\n ) {\n isDifferent = true;\n return;\n }\n }\n });\n\n return isDifferent;\n}\n\n/**\n * Declares an extensible area in an app, and provides host and extension\n * objects to all descendents. The {@link useExtensions} hook can only be called\n * in a descendent of this component.\n *\n * @remarks\n * For many apps, there will be only one Extensible provider, fairly high in the\n * component tree. It is a context provider component that may be bundled with\n * other context providers in your app architecture.\n *\n * Each Extensible element creates one {@link @adobe/uix-host#Host} object and\n * one call to an extensions provider. If multiple Extensible elements are used,\n * this may cause redundant calls. Such a design should be carefully considered.\n *\n * @public\n */\nexport function Extensible({\n appName,\n children,\n extensionsProvider,\n guestOptions,\n runtimeContainer,\n debug,\n sharedContext,\n extensionsListCallback,\n}: PropsWithChildren<ExtensibleProps>) {\n const hostName = appName || window.location.host || \"mainframe\";\n\n const [extensions, setExtensions] = useState<InstalledExtensions>({});\n const [extensionListFetched, setExtensionListFetched] =\n useState<boolean>(false);\n const prevSharedContext = useRef(JSON.stringify(sharedContext));\n useEffect(() => {\n let cancelled = false;\n\n extensionsProvider()\n .then((loaded: InstalledExtensions) => {\n if (cancelled) {\n return;\n }\n setExtensions((prev) => {\n let newExtensions = loaded;\n\n if (extensionsListCallback && loaded) {\n newExtensions = extensionsListCallback(newExtensions);\n }\n\n const shouldUpdate = areExtensionsDifferent(prev, newExtensions);\n\n if (shouldUpdate) {\n return newExtensions;\n } else {\n return prev;\n }\n });\n })\n .catch((e: Error | unknown) => {\n if (!cancelled) {\n console.error(\"Fetching list of extensions failed!\", e);\n }\n })\n .finally(() => {\n if (!cancelled) {\n setExtensionListFetched(true);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [extensionsProvider, extensionsListCallback]);\n\n const [host, setHost] = useState<Host>();\n const hostRef = useRef<Host>();\n\n useEffect(() => {\n return () => {\n if (hostRef.current) {\n hostRef.current.unload().catch(() => {});\n hostRef.current = undefined;\n }\n };\n }, []);\n\n useEffect(() => {\n function logError(msg: string) {\n return (e: Error | unknown) => {\n const error = e instanceof Error ? e : new Error(String(e));\n console.error(msg, error, extensions, guestOptions);\n };\n }\n\n if (!extensions || !Object.keys(extensions).length) {\n return;\n }\n\n const loadExtensions = (hostInstance: Host) => {\n hostInstance\n .load(extensions, guestOptions)\n .catch(logError(\"Load of extensions failed!\"));\n };\n\n const sharedContextChanged =\n prevSharedContext.current !== JSON.stringify(sharedContext);\n\n if (sharedContextChanged) {\n prevSharedContext.current = JSON.stringify(sharedContext);\n }\n if (!host || sharedContextChanged) {\n if (hostRef.current) {\n hostRef.current.unload().catch(() => {});\n }\n const newHost = new Host({\n debug,\n hostName,\n runtimeContainer,\n sharedContext,\n });\n hostRef.current = newHost;\n setHost(newHost);\n loadExtensions(newHost);\n } else {\n loadExtensions(host);\n }\n }, [debug, hostName, runtimeContainer, extensions]);\n\n const contextValue = useMemo(\n () => ({ host, extensionListFetched }),\n [host, extensionListFetched]\n );\n\n return (\n <ExtensionContext.Provider value={contextValue}>\n {children}\n </ExtensionContext.Provider>\n );\n}\nexport default Extensible;\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * @hidden\n */\nimport { createContext } from \"react\";\nimport { Host } from \"@adobe/uix-host\";\n\n/**\n * Context container with Host object and extensions load status.\n *\n * @internal\n */\nexport type ExtensibilityContext = {\n host: Host;\n extensionListFetched: boolean;\n};\n\n/**\n * @internal\n */\nexport const ExtensionContext = createContext<ExtensibilityContext>(\n {} as unknown as ExtensibilityContext\n);\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { CrossRealmObject, UIFrameRect, VirtualApi } from \"@adobe/uix-core\";\nimport React, { useEffect, useRef } from \"react\";\nimport type { IframeHTMLAttributes } from \"react\";\nimport { useHost } from \"../hooks/useHost.js\";\nimport type { AttrTokens, SandboxToken } from \"@adobe/uix-host\";\nimport { makeSandboxAttrs, requiredIframeProps } from \"@adobe/uix-host\";\n\n/**\n * @internal\n */\ntype ReactIframeProps = IframeHTMLAttributes<HTMLIFrameElement>;\n\n/**\n * @public\n */\ntype FrameProps = Omit<ReactIframeProps, \"sandbox\">;\n\n/** @public */\nexport interface GuestUIProps extends FrameProps {\n guestId: string;\n /**\n * Receives the Penpal context when the frame is mounted.\n */\n onConnect?: () => void;\n /**\n * Called when the frame disconnects and unmounts.\n */\n onDisconnect?: () => void;\n /**\n * Called when the connection process throws an exception\n */\n onConnectionError?: (error: Error) => void;\n /**\n * Called when the document in the iframe changes size.\n */\n onResize?: (dimensions: UIFrameRect) => void;\n /**\n * Additional sandbox attributes GuestUIFrame might need.\n */\n sandbox?: AttrTokens<SandboxToken>;\n /**\n * Optional custom URL or path.\n */\n src: string;\n /**\n * Host methods to provide only to the guest inside all iframes.\n */\n methods?: VirtualApi;\n /**\n * Host methods to provide only to the guest inside this iframe.\n */\n privateMethods?: VirtualApi;\n}\n\nconst defaultIFrameProps: FrameProps = {\n width: \"100%\",\n height: \"100%\",\n style: {\n display: \"block\",\n border: \"none\",\n },\n};\n\nconst defaultSandbox = \"allow-scripts allow-forms allow-same-origin\";\n\n/**\n * An iframe that attaches to a running GuestServer, to display visible UI pages\n * delivered by the Extension server.\n * @public\n */\nexport const GuestUIFrame = ({\n guestId,\n src = \"\",\n onConnect,\n onDisconnect,\n onConnectionError,\n onResize,\n methods,\n privateMethods,\n sandbox = \"\",\n style,\n ...customIFrameProps\n}: GuestUIProps) => {\n const ref = useRef<HTMLIFrameElement>();\n const { host } = useHost();\n if (!host) {\n return null;\n }\n const guest = host.guests.get(guestId);\n const frameUrl = new URL(src, guest.url.href);\n\n useEffect(() => {\n if (ref.current) {\n let mounted = true;\n let connection: CrossRealmObject<VirtualApi>;\n const connectionFrame = ref.current;\n if (methods) {\n guest.provide(methods);\n }\n const connecting = guest.attachUI(connectionFrame, privateMethods);\n connecting\n .then((c) => {\n connection = c;\n if (!mounted) {\n c.tunnel.destroy();\n } else if (onConnect) {\n onConnect();\n }\n })\n .catch((error: Error) => {\n if (mounted && !connection && connectionFrame === ref.current) {\n const frameError = new Error(\n `GuestUIFrame connection failed: ${\n (error && error.stack) || error\n }`\n );\n Object.assign(frameError, {\n original: error,\n ref,\n guest,\n host,\n });\n if (onConnectionError) onConnectionError(frameError);\n }\n });\n return () => {\n mounted = false;\n if (connection) {\n connection.tunnel.destroy();\n }\n };\n }\n }, [guest.id]);\n\n useEffect(() => {\n if (ref.current && onResize) {\n const currentFrame = ref.current;\n return guest.addEventListener(\n \"guestresize\",\n ({ detail: { guestPort, iframe, dimensions } }) => {\n if (guestPort.id === guest.id && iframe === currentFrame) {\n onResize(dimensions);\n }\n }\n );\n }\n }, [ref.current, guest.id, onResize]);\n\n return (\n <iframe\n {...defaultIFrameProps}\n ref={ref}\n src={frameUrl.href}\n name={`uix-guest-${guest.id}`}\n sandbox={\n sandbox\n ? makeSandboxAttrs(defaultSandbox, sandbox).join(\" \")\n : defaultSandbox\n }\n style={\n style\n ? { ...style, ...defaultIFrameProps.style }\n : defaultIFrameProps.style\n }\n {...customIFrameProps}\n {...requiredIframeProps}\n />\n );\n};\nexport default GuestUIFrame;\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { useContext } from \"react\";\nimport { Host } from \"@adobe/uix-host\";\nimport { ExtensionContext, ExtensibilityContext } from \"../extension-context\";\n\n/**\n * @public\n */\nexport class OutsideOfExtensionContextError extends Error {\n outsideOfExtensionContext: boolean;\n constructor(msg: string) {\n super(msg);\n this.outsideOfExtensionContext = true;\n Object.setPrototypeOf(this, OutsideOfExtensionContextError.prototype);\n }\n}\n\n/** @public */\ntype UseHostResponse =\n | { host: undefined; error: Error }\n | { host: Host; error: undefined };\n\n/**\n * Retrieve the {@link @adobe/uix-host#Host} object hosting all extensions inside the current parent provider.\n *\n * @remarks Returns a `{ host, error }` tuple, not the host object directly.\n * @beta\n */\nexport function useHost(): UseHostResponse {\n const extensionsInfo = useContext<ExtensibilityContext>(ExtensionContext);\n\n if (!(extensionsInfo.host instanceof Host)) {\n const error = new OutsideOfExtensionContextError(\n \"Attempt to use extensions outside of ExtensionContext. Wrap extensible part of application with Extensible component.\"\n );\n return {\n host: undefined,\n error,\n };\n }\n return { error: undefined, host: extensionsInfo.host };\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * @hidden\n */\nimport React, { createContext } from \"react\";\nimport type { PropsWithChildren } from \"react\";\nimport { ExtensionRegistryEndpointRegistration } from \"@adobe/uix-host\";\n\n/**\n * @internal\n */\nexport const ExtensibleComponentBoundaryContext = createContext<\n ExtensionRegistryEndpointRegistration[]\n>(null as ExtensionRegistryEndpointRegistration[]);\n\n/** @public */\nexport type ExtensibleComponentProps = PropsWithChildren<{\n extensionPoints: ExtensionRegistryEndpointRegistration[];\n}>;\n\n/**\n * Wrapper that adds an extension point context to subcomponent tree.\n *\n * @public\n */\nexport const ExtensibleComponentBoundary = ({\n extensionPoints,\n children,\n}: ExtensibleComponentProps) => {\n return (\n <ExtensibleComponentBoundaryContext.Provider value={extensionPoints}>\n {children}\n </ExtensibleComponentBoundaryContext.Provider>\n );\n};\n","/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport type { PropsWithChildren, ReactElement } from \"react\";\nimport React, { useMemo } from \"react\";\nimport { Extensible } from \"../Extensible\";\nimport {\n combineExtensionsFromProviders,\n InstalledExtensions,\n mutedProvider,\n type ExtensionsProvider,\n type HostConfig,\n type PortOptions,\n type SharedContextValues,\n} from \"@adobe/uix-host\";\nimport {\n ExtensionPointId,\n ExtensionProviderConfig,\n createExtensionManagerExtensionsProvider,\n} from \"./ExtensionManagerProvider\";\nimport { createUrlExtensionsProvider } from \"./UrlExtensionProvider\";\n\n/** @public */\nexport interface ExtensibleDefaultProps extends Omit<HostConfig, \"hostName\"> {\n /**\n * Unique name for identifying this extensible app. May be used as metadata in\n * extension registry in the future.\n */\n appName?: string;\n /**\n * {@inheritDoc HostConfig.guestOptions}\n */\n guestOptions?: PortOptions;\n /**\n * {@inheritDoc HostConfig.sharedContext}\n */\n sharedContext?: SharedContextValues;\n queryString?: string;\n service: string;\n extensionPoint: string;\n version: string;\n disableExtensionManager?: boolean;\n authConfig: {\n imsToken: string;\n imsOrg: string;\n apiKey: string;\n };\n scope?: Record<string, any>;\n experienceShellEnvironment?: \"prod\" | \"stage\";\n extensionsListCallback?: (\n extensions: InstalledExtensions\n ) => InstalledExtensions;\n}\n\n/**\n * ExtensibleWrapper component that provides extension support to React applications.\n * @public\n */\nexport const ExtensibleWrapper = ({\n appName,\n children,\n guestOptions,\n runtimeContainer,\n debug,\n sharedContext,\n experienceShellEnvironment,\n queryString,\n service,\n extensionPoint,\n version,\n disableExtensionManager,\n authConfig,\n scope,\n extensionsListCallback,\n}: PropsWithChildren<ExtensibleDefaultProps>): ReactElement => {\n const defaultExtensionsProvider = useMemo(() => {\n const extensionPointId: ExtensionPointId = {\n service,\n name: extensionPoint,\n version,\n };\n const params: URLSearchParams = new URLSearchParams(queryString ?? \"\");\n const extensionManagerUrlOverride = params.get(\"em\");\n const appRegistryUrlOverride = params.get(\"er\");\n const urlExtensionsProvider: ExtensionsProvider =\n createUrlExtensionsProvider(extensionPointId, queryString);\n const providerConfig: ExtensionProviderConfig = {\n disableExtensionManager,\n };\n\n if (extensionManagerUrlOverride) {\n providerConfig.extensionManagerUrl = extensionManagerUrlOverride;\n }\n\n if (appRegistryUrlOverride) {\n providerConfig.appRegistryUrl = appRegistryUrlOverride;\n }\n\n const extensionManagerExtensionsProvider: ExtensionsProvider =\n createExtensionManagerExtensionsProvider(\n {\n experienceShellEnvironment,\n scope,\n },\n authConfig,\n providerConfig,\n extensionPointId\n );\n\n const extenstions = combineExtensionsFromProviders(\n urlExtensionsProvider,\n mutedProvider(extensionManagerExtensionsProvider)\n );\n\n return extenstions;\n }, [\n experienceShellEnvironment,\n queryString,\n service,\n extensionPoint,\n version,\n disableExtensionManager,\n authConfig,\n scope,\n ]);\n return (\n <Extensible\n extensionsProvider={defaultExtensionsProvider}\n appName={appName}\n runtimeContainer={runtimeContainer}\n debug={debug}\n guestOptions={guestOptions}\n sharedContext={sharedContext}\n extensionsListCallback={extensionsListCallback}\n >\n {children}\n </Extensible>\n );\n};\n\nexport default ExtensibleWrapper;\n","/*************************************************************************\n * ADOBE CONFIDENTIAL\n * ___________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n **************************************************************************/\n\nimport {\n createExtensionRegistryAsObjectsProvider,\n ExtensionsProvider,\n InstalledExtensions,\n} from \"@adobe/uix-host\";\n\nconst EXTENSION_MANAGER_URL_PROD = \"https://aemx-mngr.adobe.io\";\nconst EXTENSION_MANAGER_URL_STAGE = \"https://aemx-mngr-stage.adobe.io\";\n\nconst APP_REGISTRY_URL_PROD = \"https://appregistry.adobe.io\";\nconst APP_REGISTRY_URL_STAGE = \"https://appregistry-stage.adobe.io\";\n\n// Extension Manager stores information about extension points that a particular extension implements\n// in the \"extensionPoints\" array of objects of the following \"ExtensionPoint\" type\n// where \"extensionPoint\" is the name of the extension point, for example, \"aem/assets/details/1\"\n// \"url\" is the extension url for the specified extension point\n/** @internal */\ntype ExtensionPoint = {\n extensionPoint: string;\n url: string;\n};\n/** @public */\nexport type ExtensionManagerExtension = {\n id: string;\n name: string;\n title: string;\n description: string;\n status: string;\n supportEmail: string;\n extId: string;\n disabled: boolean;\n extensionPoints: ExtensionPoint[];\n scope: Record<string, unknown>;\n configuration?: Record<string, unknown>;\n};\n\n/** @internal */\ntype AuthEMConfig = {\n schema: \"Bearer\" | \"Basic\";\n imsToken: string;\n};\n/** @public */\nexport interface ExtensionManagerConfig {\n apiKey: string;\n auth: AuthEMConfig;\n service: string;\n extensionPoint: string;\n version: string;\n imsOrg: string;\n baseUrl: string;\n scope?: Record<string, string>;\n}\n\n/**\n * Authentication configuration, including IMS Org ID, access token, and API key\n * @public\n */\nexport interface AuthConfig {\n /** IMS Org ID */\n imsOrg: string;\n /** Access token for the user */\n imsToken: string;\n /** API key */\n apiKey: string;\n}\n\n/**\n * Discovery configuration, including environment and repo Id\n * @public\n */\nexport interface DiscoveryConfig {\n /** Environment level for backend Extension resolution services */\n experienceShellEnvironment?: \"prod\" | \"stage\";\n scope?: Record<string, string>;\n}\n\n/**\n * Extension point ID\n * @public\n */\nexport interface ExtensionPointId {\n /** Service name */\n service: string;\n /** Extension point name */\n name: string;\n /** Extension point version */\n version: string;\n}\n\n/**\n * Sets up new ExtensionsProvider with authentication and discovery information needed to fetch the list of\n * Extensions from AppRegistry and Extension Manager service, along with the query string portion of URL\n * to extract the information about development Extensions\n * @public\n */\nexport interface ExtensionsProviderConfig {\n /** Discovery configuration */\n discoveryConfig: DiscoveryConfig;\n /** Authentication configuration */\n authConfig: AuthConfig;\n /** Extension point ID */\n extensionPointId: ExtensionPointId;\n providerConfig: ExtensionProviderConfig;\n}\n\n/** @public */\nexport interface ExtensionProviderConfig {\n extensionManagerUrl?: string;\n appRegistryUrl?: string;\n disableExtensionManager?: boolean;\n}\n/** @internal */\nexport const getExtensionRegistryBaseUrl = (\n environment: \"prod\" | \"stage\" | undefined,\n registry: string | null\n): string =>\n environment === \"prod\"\n ? APP_REGISTRY_URL_PROD\n : registry ?? APP_REGISTRY_URL_STAGE;\n\n/** @internal */\nexport const getExtensionManagerBaseUrl = (\n environment: \"prod\" | \"stage\" | undefined,\n extensionManager: string | null\n): string =>\n environment === \"prod\"\n ? EXTENSION_MANAGER_URL_PROD\n : extensionManager ?? EXTENSION_MANAGER_URL_STAGE;\n\n/**\n * Extracts programId and envId from the repo value\n * @param repo - the repo value\n * @returns object with programId and envId\n * @internal\n */\nexport function extractProgramIdEnvId(repo: string): {\n programId: string;\n envId: string;\n} {\n const regex: RegExp = /p(\\d+)-e(\\d+)/;\n const match: RegExpMatchArray | null = regex.exec(repo);\n if (!match) {\n throw new Error(\"Error parsing a repo value\");\n }\n\n return {\n programId: match[1],\n envId: match[2],\n };\n}\n\n/**\n * Builds the URL for fetching extensions from the Extension Manager service\n * @param config - the Extension Manager configuration\n * @returns the URL for fetching extensions\n * @internal\n */\nexport function buildExtensionManagerUrl(\n config: ExtensionManagerConfig\n): string {\n const scope = config.scope\n ? Object.fromEntries(\n Object.entries(config.scope).map(([k, v]) => [`scope.${k}`, v])\n )\n : {};\n const extensionPoints: string = `${config.service}/${config.extensionPoint}/${config.version}`;\n const queryParams = new URLSearchParams({\n ...scope,\n extensionPoints,\n });\n\n return `${config.baseUrl}/v2/extensions?${queryParams.toString()}`;\n}\n\n/**\n * @internal\n */\nexport async function fetchExtensionsFromExtensionManager(\n config: ExtensionManagerConfig\n): Promise<ExtensionManagerExtension[]> {\n const resp: Response = await fetch(buildExtensionManagerUrl(config), {\n headers: {\n Authorization: `Bearer ${config.auth.imsToken}`,\n \"x-api-key\": config.apiKey,\n \"x-org-id\": config.imsOrg,\n },\n });\n\n if (resp.status !== 200) {\n throw new Error(\n `Extension Manager returned non-200 response (${\n resp.status\n }): ${await resp.text()}`\n );\n }\n\n return resp.json();\n}\n\n/**\n * Takes an array of extensions from the App Registry, an array of extensions from the Extension Manager, and\n * merges them into a list of Extensions. If an extension is disabled in the Extension Manager, it is removed from\n * the list.\n * Extension list from the App Registry is used as a base.\n * @internal\n */\nexport function mergeExtensions(\n appRegistryExtensions: InstalledExtensions,\n extensionManagerExtensions: ExtensionManagerExtension[],\n extensionPointId: ExtensionPointId\n): InstalledExtensions {\n const mergedExtensions: InstalledExtensions = Object.assign(\n appRegistryExtensions,\n {}\n );\n extensionManagerExtensions.forEach((extension: ExtensionManagerExtension) => {\n if (extension.disabled) {\n // remove disabled extensions\n delete mergedExtensions[extension.name];\n } else {\n const extPoint: ExtensionPoint | undefined =\n extension.extensionPoints.find(\n (_extensionPoint: ExtensionPoint) =>\n _extensionPoint.extensionPoint ===\n `${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version}`\n );\n if (extPoint) {\n // add a new extension record or replace the existing one by an extension record from Extension Manager\n // extension points are useful for filtering out extensions\n mergedExtensions[extension.name] = {\n id: extension.name,\n url: extPoint.url,\n configuration: extension.configuration,\n extensionPoints: extension.extensionPoints.map(\n (point) => point.extensionPoint\n ),\n };\n } else {\n //this should never happen because we query Extension Manager service for our specific extension point\n console.warn(\n `Extension point ${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version} not found for extension ${extension.name}`\n );\n }\n }\n });\n\n return mergedExtensions;\n}\n\nasync function getExtensionManagerExtensions(\n discoveryConfig: DiscoveryConfig,\n authConfig: AuthConfig,\n providerConfig: ExtensionProviderConfig,\n extensionPointId: ExtensionPointId\n): Promise<InstalledExtensions> {\n const config = {\n apiKey: authConfig.apiKey,\n auth: {\n schema: \"Bearer\",\n imsToken: authConfig.imsToken,\n },\n service: extensionPointId.service,\n extensionPoint: extensionPointId.name,\n version: extensionPointId.version,\n imsOrg: authConfig.imsOrg,\n scope: discoveryConfig.scope,\n };\n\n const appRegistryConfig = {\n ...config,\n baseUrl: getExtensionRegistryBaseUrl(\n discoveryConfig.experienceShellEnvironment,\n providerConfig.appRegistryUrl\n ),\n } as ExtensionManagerConfig;\n const appRegistryExtensionsProvider: ExtensionsProvider =\n createExtensionRegistryAsObjectsProvider(appRegistryConfig);\n\n const extensionManagerConfiguration = {\n ...config,\n baseUrl: getExtensionManagerBaseUrl(\n discoveryConfig.experienceShellEnvironment,\n providerConfig.extensionManagerUrl\n ),\n } as ExtensionManagerConfig;\n const [appRegistryExtensions, extensionManagerExtensions] = await Promise.all(\n [\n appRegistryExtensionsProvider(),\n providerConfig.disableExtensionManager\n ? []\n : fetchExtensionsFromExtensionManager(extensionManagerConfiguration),\n ]\n );\n\n if (providerConfig.disableExtensionManager) {\n return appRegistryExtensions;\n } else {\n return mergeExtensions(\n appRegistryExtensions,\n extensionManagerExtensions,\n extensionPointId\n );\n }\n}\n\n/**\n * Creates an extension manager extension provider\n * @internal\n */\nexport function createExtensionManagerExtensionsProvider(\n discoveryConfig: DiscoveryConfig,\n authConfig: AuthConfig,\n providerConfig: ExtensionProviderConfig,\n extensionPointId: ExtensionPointId\n): ExtensionsProvider {\n return () => {\n return getExtensionManagerExtensions(\n discoveryConfig,\n authConfig,\n providerConfig,\n extensionPointId\n );\n };\n}\n","/*************************************************************************\n * ADOBE CONFIDENTIAL\n * ___________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n **************************************************************************/\nimport { ExtensionsProvider, InstalledExtensions } from \"@adobe/uix-host\";\nimport { Extension } from \"@adobe/uix-core\";\nimport { ExtensionPointId } from \"./ExtensionManagerProvider\";\nconst EXT_PARAM_PREFIX = \"ext\";\n\n/** @public */\nexport interface ExtUrlParams {\n [key: string]: string;\n}\n\n/**\n * Validates if a URL is safe and only allows HTTP/HTTPS protocols\n * @param url - The URL string to validate\n * @returns true if the URL is valid and uses HTTP/HTTPS protocol, false otherwise\n * @public\n */\nexport function isValidHttpUrl(url: string): boolean {\n try {\n const parsedUrl = new URL(url);\n\n return parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts extension URLs from the query string\n * @internal\n */\nexport function extractExtUrlParams(\n queryString: string | undefined\n): ExtUrlParams {\n if (!queryString) {\n return {};\n }\n const params: URLSearchParams = new URLSearchParams(queryString);\n return Array.from(params.entries()).reduce((extParams, [key, value]) => {\n if (key === EXT_PARAM_PREFIX || key.startsWith(`${EXT_PARAM_PREFIX}.`)) {\n extParams[key] = value;\n }\n return extParams;\n }, {} as ExtUrlParams);\n}\n\n/**\n * Generates an extension ID from the extension URL\n * @internal\n */\nexport function generateExtensionId(extensionUrl: string): string {\n return extensionUrl.replace(/\\W/g, \"_\");\n}\n\n/**\n * Creates an ExtensionsProvider that provides extensions from the URL\n * @internal\n */\nexport function createUrlExtensionsProvider(\n extensionPointId: ExtensionPointId,\n queryString: string | undefined\n): ExtensionsProvider {\n const extUrlParams: ExtUrlParams = extractExtUrlParams(queryString);\n\n const extensionUrls: string[] = Object.keys(extUrlParams)\n .filter(\n (extParam) =>\n extParam === EXT_PARAM_PREFIX ||\n extParam ===\n `${EXT_PARAM_PREFIX}.${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version}`\n )\n .flatMap((extParam) => {\n const paramValue = extUrlParams[extParam];\n // If it's a single value, return it in an array. If it's already an array, return it as is.\n if (Array.isArray(paramValue)) {\n return paramValue.filter((param) => isValidHttpUrl(param));\n } else {\n return isValidHttpUrl(paramValue) ? [paramValue] : [];\n }\n });\n\n const installedExtensions: InstalledExtensions = extensionUrls\n .map((extensionUrl: string) => {\n return {\n id: generateExtensionId(extensionUrl),\n url: extensionUrl,\n extensionPoints: [\n `${extensionPointId.service}/${extensionPointId.name}/${extensionPointId.version}`,\n ],\n } as Extension;\n })\n .reduce((acc: InstalledExtensions, extension: Extension) => {\n acc[extension.id] = extension;\n return acc;\n }, {} as InstalledExtensions);\n\n return async () => installedExtensions;\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type {\n GuestConnection,\n GuestApis,\n RemoteGuestApis,\n RemoteGuestApiNS,\n VirtualApi,\n} from \"@adobe/uix-core\";\n\nimport { Host, HostEvents } from \"@adobe/uix-host\";\nimport type { CapabilitySpec, Port } from \"@adobe/uix-host\";\nimport { useHost } from \"./useHost\";\nimport { ExtensibleComponentBoundaryContext } from \"../components/ExtensibleComponentBoundary\";\nimport { ExtensionRegistryEndpointRegistration } from \"@adobe/uix-host\";\n\n/**\n * @internal\n */\nexport interface TypedGuestConnection<T extends GuestApis>\n extends GuestConnection {\n id: GuestConnection[\"id\"];\n apis: RemoteGuestApis<T>;\n}\n\n/** @public */\nexport interface UseExtensionsConfig<\n Incoming extends GuestApis,\n Outgoing extends VirtualApi\n> {\n /**\n * A {@link @adobe/uix-host#CapabilitySpec} describing the namespaced methods\n * extensions must implement to be used by this component.\n *\n * @remarks\n * This declaration is used to filter the extensions that will be\n * returned; if they don't implement those methods, they will be filtered out.\n */\n requires?: CapabilitySpec<Required<Incoming>>;\n /**\n * A namespaced object of methods which extensions will be able to call.\n *\n * @remarks This is the counterpart of `requires`; in `requires`, the you\n * describes methods the extension must implement that your host code will\n * call, and in `provides`, you implement host methods that extensions will be\n * able to call.\n *\n * Most cases for host-side methods will use the state of the component. This\n * can cause unexpected bugs in React if the config callback is run on every\n * render. **useExtensions caches the config callback by default!**\n * So remember to pass a deps array, so that the config callback re-runs under\n * the right conditions.\n */\n provides?: Outgoing;\n /**\n * Sets when re-render is triggered on extension load.\n *\n * @remarks\n * Set to `each` to trigger a component re-render every time an individual\n * extension loads, which may result in multiple UI updates. Set to `all` to\n * wait until all extensions have loaded to re-render the component.\n * @defaultValue \"each\"\n */\n updateOn?: \"each\" | \"all\";\n}\n\n/** @public */\nexport interface UseExtensionsResult<T extends GuestApis> {\n /**\n * A list of loaded guests which implement the methods specified in\n * `requires`, represented as {@link @adobe/uix-host#Port} objects which\n * present methods to be called.\n */\n extensions: TypedGuestConnection<T>[];\n /**\n * This is `true` until all extensions are loaded. Use for rendering spinners\n * or other intermediate UI.\n */\n loading: boolean;\n /**\n * Populated with an Error if there were any problems during the load process.\n */\n error?: Error;\n}\n\nconst NO_EXTENSIONS: [] = [];\n\n/**\n * Fetch extensions which implement an API, provide them methods, and use them.\n *\n * @remarks `useExtensions` does three things at once:\n * - Gets all extensions which implement the APIs described in the `require` field\n * - Exposes any functions defined in the `provide` field to those extensions\n * - Returns an object whose `extensions` property is a list of `Port` objects representing those extensions\n *\n * useExtensions will trigger a re-render when extensions load. You can choose whether it triggers that rerender as each extension loads, or only after all extensions have loaded.\n * @public\n */\nexport function useExtensions<\n Incoming extends GuestApis,\n Outgoing extends VirtualApi\n>(\n configFactory: (host: Host) => UseExtensionsConfig<Incoming, Outgoing>,\n deps: unknown[] = []\n): UseExtensionsResult<Incoming> {\n const { host, error: contextError } = useHost();\n\n // All hooks must be called unconditionally before any early return.\n const [hostError, setHostError] = useState<Error>();\n const extensionPoints = useContext(ExtensibleComponentBoundaryContext);\n const boundryExtensionPointsAsString = extensionPoints?.map(\n ({\n service,\n extensionPoint,\n version,\n }: ExtensionRegistryEndpointRegistration) =>\n `${service}/${extensionPoint}/${version}`\n );\n const baseDeps = [host, ...deps];\n const {\n requires,\n provides,\n updateOn = \"each\",\n } = useMemo(\n () =>\n (host ? configFactory(host) : {}) as UseExtensionsConfig<\n Incoming,\n Outgoing\n >,\n baseDeps\n );\n\n const getExtensions = useCallback(() => {\n if (!host) return NO_EXTENSIONS;\n const newExtensions = [];\n const guests = host.getLoadedGuests(requires);\n\n // Extension filtering: If the boundary is provided, only return extensions which have extensionPoint\n // specified in a provided boundry. Otherwise no filtering is done.\n for (const guest of guests) {\n const allExtensionPoints: string[] =\n getAllExtensionPointsFromGuest(guest);\n\n if (\n !boundryExtensionPointsAsString ||\n !allExtensionPoints.length ||\n isGuestExtensionPointInBoundary(\n boundryExtensionPointsAsString,\n allExtensionPoints\n )\n ) {\n newExtensions.push(guest as unknown as TypedGuestConnection<Incoming>);\n }\n }\n return newExtensions.length === 0 ? NO_EXTENSIONS : newExtensions;\n }, [...baseDeps, requires]);\n\n const subscribe = useCallback(\n (handler: EventListener) => {\n if (!host) return () => {};\n const eventName = updateOn === \"all\" ? \"loadallguests\" : \"guestload\";\n host.addEventListener(eventName, handler);\n\n return () => {\n host.removeEventListener(eventName, handler);\n };\n },\n [...baseDeps, updateOn]\n );\n\n const subscribeToUnload = useCallback((handler: EventListener) => {\n if (!host) return () => {};\n host.addEventListener(\"guestunload\", handler);\n\n return () => {\n host.removeEventListener(\"guestunload\", handler);\n };\n }, baseDeps);\n\n const [extensions, setExtensions] =\n useState<TypedGuestConnection<Incoming>[]>(NO_EXTENSIONS);\n\n useEffect(() => {\n // Sync current guests immediately when host becomes available, then subscribe to future loads.\n setExtensions(getExtensions());\n return subscribe(() => setExtensions(getExtensions()));\n }, [subscribe]);\n\n const unloadExtentionCallback = (e: CustomEvent) => {\n const eventDetail = e.detail;\n const guest = eventDetail.guest as Port<GuestApis>;\n\n if (guest && guest.id) {\n setExtensions((prevExtensions) => {\n const filtered = prevExtensions.filter(\n (ext) => ext.id !== guest.id || ext.url !== guest.url\n );\n return filtered.length === 0 ? NO_EXTENSIONS : filtered;\n });\n }\n };\n\n useEffect(() => {\n return subscribeToUnload(unloadExtentionCallback);\n }, [subscribeToUnload]);\n\n useEffect(() => {\n for (const guest of extensions) {\n if (provides) {\n guest.provide(provides);\n }\n }\n }, [provides, extensions]);\n\n useEffect(() => {\n if (!host) return;\n return host.addEventListener(\n \"error\",\n (event: Extract<HostEvents, { detail: { error: Error } }>) =>\n setHostError(event.detail.error)\n );\n }, baseDeps);\n\n if (contextError) {\n return {\n extensions: NO_EXTENSIONS,\n loading: false,\n error: contextError,\n };\n }\n\n return {\n extensions,\n loading: extensions.length === 0 ? false : host.loading,\n error: hostError,\n };\n}\n\n/**\n * Each extension/guest can have\n * 1. `extensioPoints` field as an array of strings\n * 2. Metadata with array of extensionPoints. If the metadata is present, we need to use it for fitering the extensions.\n * Returns cumulative extension points.\n * @param guest\n * @returns array of extension points as strings\n */\nfunction getAllExtensionPointsFromGuest(guest: Port<GuestApis>): string[] {\n try {\n const guestExtensionPointsFromMetadata = guest.metadata?.extensions?.map(\n (extension: { extensionPoint: string }) => extension?.extensionPoint\n );\n const allExtensionPoints = [\n ...(guest.extensionPoints || []),\n ...(guestExtensionPointsFromMetadata || []),\n ];\n return allExtensionPoints;\n } catch {\n console.error(\n \"Error occurred while getting extension points from guest and metadata. Extension boundaries will not be effective.\"\n );\n return [];\n }\n}\n\nfunction isGuestExtensionPointInBoundary(\n boundryExtensionPointsAsString: string[],\n guestExtensionPoints: string[]\n) {\n return (\n boundryExtensionPointsAsString?.length &&\n guestExtensionPoints?.length &&\n guestExtensionPoints.some((extensionPoint) =>\n boundryExtensionPointsAsString.includes(extensionPoint)\n )\n );\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { useContext } from \"react\";\nimport {\n ExtensionContext,\n ExtensibilityContext,\n} from \"../extension-context.js\";\n\n/**\n * Indicates if external extensions provider was processed. Returns true after passing extension list to the Host.\n *\n * @beta\n */\nexport function useExtensionListFetched(): boolean {\n const extensionsInfo = useContext<ExtensibilityContext>(ExtensionContext);\n\n return extensionsInfo.extensionListFetched;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/uix-host-react",
3
- "version": "1.1.8",
3
+ "version": "1.1.9-nightly.20260522",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -20,8 +20,8 @@
20
20
  ],
21
21
  "bugs": "https://github.com/adobe/uix-sdk/issues",
22
22
  "dependencies": {
23
- "@adobe/uix-core": "^1.1.8",
24
- "@adobe/uix-host": "^1.1.8"
23
+ "@adobe/uix-core": "^1.1.9-nightly.20260522",
24
+ "@adobe/uix-host": "^1.1.9-nightly.20260522"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@swc/jest": "^0.2.29",
@@ -442,6 +442,44 @@ describe("Extensible", () => {
442
442
  // The first callback should not be called with cancelled results
443
443
  expect(extensionsListCallback).not.toHaveBeenCalled();
444
444
  });
445
+
446
+ it("should apply extensionsListCallback result when loading extensions", async () => {
447
+ const allExtensions: InstalledExtensions = {
448
+ "ext-1": { id: "ext-1", url: "https://example.com/ext1" },
449
+ "ext-2": { id: "ext-2", url: "https://example.com/ext2" },
450
+ };
451
+ const filteredExtensions: InstalledExtensions = {
452
+ "ext-1": { id: "ext-1", url: "https://example.com/ext1" },
453
+ };
454
+
455
+ const extensionsProvider = jest.fn().mockResolvedValue(allExtensions);
456
+ // Callback filters out ext-2
457
+ const extensionsListCallback = jest
458
+ .fn()
459
+ .mockReturnValue(filteredExtensions);
460
+
461
+ render(
462
+ <Extensible
463
+ appName="test-app"
464
+ extensionsProvider={extensionsProvider}
465
+ extensionsListCallback={extensionsListCallback}
466
+ >
467
+ <div>Test Child</div>
468
+ </Extensible>
469
+ );
470
+
471
+ await waitFor(() => {
472
+ expect(extensionsListCallback).toHaveBeenCalledWith(allExtensions);
473
+ });
474
+
475
+ // host.load must receive the filtered list, not the original
476
+ await waitFor(() => {
477
+ expect(mockLoad).toHaveBeenCalled();
478
+ expect(mockLoad.mock.calls[0][0]).toEqual(filteredExtensions);
479
+ });
480
+
481
+ expect(mockLoad.mock.calls[0][0]).not.toEqual(allExtensions);
482
+ });
445
483
  });
446
484
 
447
485
  describe("Integration scenarios", () => {
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
10
10
  governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import React, { useState, useEffect, useRef } from "react";
13
+ import React, { useState, useEffect, useRef, useMemo } from "react";
14
14
  import type { PropsWithChildren } from "react";
15
15
  import type {
16
16
  InstalledExtensions,
@@ -222,18 +222,13 @@ export function Extensible({
222
222
  }
223
223
  }, [debug, hostName, runtimeContainer, extensions]);
224
224
 
225
- // skip render before host is initialized
226
- if (!host) {
227
- return <>{children}</>;
228
- }
225
+ const contextValue = useMemo(
226
+ () => ({ host, extensionListFetched }),
227
+ [host, extensionListFetched]
228
+ );
229
229
 
230
230
  return (
231
- <ExtensionContext.Provider
232
- value={{
233
- host: host,
234
- extensionListFetched: extensionListFetched,
235
- }}
236
- >
231
+ <ExtensionContext.Provider value={contextValue}>
237
232
  {children}
238
233
  </ExtensionContext.Provider>
239
234
  );
@@ -60,6 +60,10 @@ export interface ExtensibleDefaultProps extends Omit<HostConfig, "hostName"> {
60
60
  ) => InstalledExtensions;
61
61
  }
62
62
 
63
+ /**
64
+ * ExtensibleWrapper component that provides extension support to React applications.
65
+ * @public
66
+ */
63
67
  export const ExtensibleWrapper = ({
64
68
  appName,
65
69
  children,
@@ -31,10 +31,12 @@ const APP_REGISTRY_URL_STAGE = "https://appregistry-stage.adobe.io";
31
31
  // in the "extensionPoints" array of objects of the following "ExtensionPoint" type
32
32
  // where "extensionPoint" is the name of the extension point, for example, "aem/assets/details/1"
33
33
  // "url" is the extension url for the specified extension point
34
+ /** @internal */
34
35
  type ExtensionPoint = {
35
36
  extensionPoint: string;
36
37
  url: string;
37
38
  };
39
+ /** @public */
38
40
  export type ExtensionManagerExtension = {
39
41
  id: string;
40
42
  name: string;
@@ -49,10 +51,12 @@ export type ExtensionManagerExtension = {
49
51
  configuration?: Record<string, unknown>;
50
52
  };
51
53
 
54
+ /** @internal */
52
55
  type AuthEMConfig = {
53
56
  schema: "Bearer" | "Basic";
54
57
  imsToken: string;
55
58
  };
59
+ /** @public */
56
60
  export interface ExtensionManagerConfig {
57
61
  apiKey: string;
58
62
  auth: AuthEMConfig;
@@ -64,7 +68,10 @@ export interface ExtensionManagerConfig {
64
68
  scope?: Record<string, string>;
65
69
  }
66
70
 
67
- /** Authentication configuration, including IMS Org ID, access token, and API key */
71
+ /**
72
+ * Authentication configuration, including IMS Org ID, access token, and API key
73
+ * @public
74
+ */
68
75
  export interface AuthConfig {
69
76
  /** IMS Org ID */
70
77
  imsOrg: string;
@@ -74,14 +81,20 @@ export interface AuthConfig {
74
81
  apiKey: string;
75
82
  }
76
83
 
77
- /** Discovery configuration, including environment and repo Id */
84
+ /**
85
+ * Discovery configuration, including environment and repo Id
86
+ * @public
87
+ */
78
88
  export interface DiscoveryConfig {
79
89
  /** Environment level for backend Extension resolution services */
80
90
  experienceShellEnvironment?: "prod" | "stage";
81
91
  scope?: Record<string, string>;
82
92
  }
83
93
 
84
- /** Extension point ID */
94
+ /**
95
+ * Extension point ID
96
+ * @public
97
+ */
85
98
  export interface ExtensionPointId {
86
99
  /** Service name */
87
100
  service: string;
@@ -95,6 +108,7 @@ export interface ExtensionPointId {
95
108
  * Sets up new ExtensionsProvider with authentication and discovery information needed to fetch the list of
96
109
  * Extensions from AppRegistry and Extension Manager service, along with the query string portion of URL
97
110
  * to extract the information about development Extensions
111
+ * @public
98
112
  */
99
113
  export interface ExtensionsProviderConfig {
100
114
  /** Discovery configuration */
@@ -106,11 +120,13 @@ export interface ExtensionsProviderConfig {
106
120
  providerConfig: ExtensionProviderConfig;
107
121
  }
108
122
 
123
+ /** @public */
109
124
  export interface ExtensionProviderConfig {
110
125
  extensionManagerUrl?: string;
111
126
  appRegistryUrl?: string;
112
127
  disableExtensionManager?: boolean;
113
128
  }
129
+ /** @internal */
114
130
  export const getExtensionRegistryBaseUrl = (
115
131
  environment: "prod" | "stage" | undefined,
116
132
  registry: string | null
@@ -119,6 +135,7 @@ export const getExtensionRegistryBaseUrl = (
119
135
  ? APP_REGISTRY_URL_PROD
120
136
  : registry ?? APP_REGISTRY_URL_STAGE;
121
137
 
138
+ /** @internal */
122
139
  export const getExtensionManagerBaseUrl = (
123
140
  environment: "prod" | "stage" | undefined,
124
141
  extensionManager: string | null
@@ -131,7 +148,7 @@ export const getExtensionManagerBaseUrl = (
131
148
  * Extracts programId and envId from the repo value
132
149
  * @param repo - the repo value
133
150
  * @returns object with programId and envId
134
- * @ignore
151
+ * @internal
135
152
  */
136
153
  export function extractProgramIdEnvId(repo: string): {
137
154
  programId: string;
@@ -153,7 +170,7 @@ export function extractProgramIdEnvId(repo: string): {
153
170
  * Builds the URL for fetching extensions from the Extension Manager service
154
171
  * @param config - the Extension Manager configuration
155
172
  * @returns the URL for fetching extensions
156
- * @ignore
173
+ * @internal
157
174
  */
158
175
  export function buildExtensionManagerUrl(
159
176
  config: ExtensionManagerConfig
@@ -173,7 +190,7 @@ export function buildExtensionManagerUrl(
173
190
  }
174
191
 
175
192
  /**
176
- * @ignore
193
+ * @internal
177
194
  */
178
195
  export async function fetchExtensionsFromExtensionManager(
179
196
  config: ExtensionManagerConfig
@@ -202,7 +219,7 @@ export async function fetchExtensionsFromExtensionManager(
202
219
  * merges them into a list of Extensions. If an extension is disabled in the Extension Manager, it is removed from
203
220
  * the list.
204
221
  * Extension list from the App Registry is used as a base.
205
- * @ignore
222
+ * @internal
206
223
  */
207
224
  export function mergeExtensions(
208
225
  appRegistryExtensions: InstalledExtensions,
@@ -305,7 +322,7 @@ async function getExtensionManagerExtensions(
305
322
 
306
323
  /**
307
324
  * Creates an extension manager extension provider
308
- * @ignore
325
+ * @internal
309
326
  */
310
327
  export function createExtensionManagerExtensionsProvider(
311
328
  discoveryConfig: DiscoveryConfig,
@@ -19,6 +19,7 @@ import { Extension } from "@adobe/uix-core";
19
19
  import { ExtensionPointId } from "./ExtensionManagerProvider";
20
20
  const EXT_PARAM_PREFIX = "ext";
21
21
 
22
+ /** @public */
22
23
  export interface ExtUrlParams {
23
24
  [key: string]: string;
24
25
  }
@@ -27,6 +28,7 @@ export interface ExtUrlParams {
27
28
  * Validates if a URL is safe and only allows HTTP/HTTPS protocols
28
29
  * @param url - The URL string to validate
29
30
  * @returns true if the URL is valid and uses HTTP/HTTPS protocol, false otherwise
31
+ * @public
30
32
  */
31
33
  export function isValidHttpUrl(url: string): boolean {
32
34
  try {
@@ -40,7 +42,7 @@ export function isValidHttpUrl(url: string): boolean {
40
42
 
41
43
  /**
42
44
  * Extracts extension URLs from the query string
43
- * @ignore
45
+ * @internal
44
46
  */
45
47
  export function extractExtUrlParams(
46
48
  queryString: string | undefined
@@ -59,7 +61,7 @@ export function extractExtUrlParams(
59
61
 
60
62
  /**
61
63
  * Generates an extension ID from the extension URL
62
- * @ignore
64
+ * @internal
63
65
  */
64
66
  export function generateExtensionId(extensionUrl: string): string {
65
67
  return extensionUrl.replace(/\W/g, "_");
@@ -67,7 +69,7 @@ export function generateExtensionId(extensionUrl: string): string {
67
69
 
68
70
  /**
69
71
  * Creates an ExtensionsProvider that provides extensions from the URL
70
- * @ignore
72
+ * @internal
71
73
  */
72
74
  export function createUrlExtensionsProvider(
73
75
  extensionPointId: ExtensionPointId,
@@ -114,14 +114,9 @@ export function useExtensions<
114
114
  configFactory: (host: Host) => UseExtensionsConfig<Incoming, Outgoing>,
115
115
  deps: unknown[] = []
116
116
  ): UseExtensionsResult<Incoming> {
117
- const { host, error } = useHost();
118
- if (error) {
119
- return {
120
- extensions: NO_EXTENSIONS,
121
- loading: false,
122
- error,
123
- };
124
- }
117
+ const { host, error: contextError } = useHost();
118
+
119
+ // All hooks must be called unconditionally before any early return.
125
120
  const [hostError, setHostError] = useState<Error>();
126
121
  const extensionPoints = useContext(ExtensibleComponentBoundaryContext);
127
122
  const boundryExtensionPointsAsString = extensionPoints?.map(
@@ -137,9 +132,17 @@ export function useExtensions<
137
132
  requires,
138
133
  provides,
139
134
  updateOn = "each",
140
- } = useMemo(() => configFactory(host), baseDeps);
135
+ } = useMemo(
136
+ () =>
137
+ (host ? configFactory(host) : {}) as UseExtensionsConfig<
138
+ Incoming,
139
+ Outgoing
140
+ >,
141
+ baseDeps
142
+ );
141
143
 
142
144
  const getExtensions = useCallback(() => {
145
+ if (!host) return NO_EXTENSIONS;
143
146
  const newExtensions = [];
144
147
  const guests = host.getLoadedGuests(requires);
145
148
 
@@ -165,6 +168,7 @@ export function useExtensions<
165
168
 
166
169
  const subscribe = useCallback(
167
170
  (handler: EventListener) => {
171
+ if (!host) return () => {};
168
172
  const eventName = updateOn === "all" ? "loadallguests" : "guestload";
169
173
  host.addEventListener(eventName, handler);
170
174
 
@@ -176,6 +180,7 @@ export function useExtensions<
176
180
  );
177
181
 
178
182
  const subscribeToUnload = useCallback((handler: EventListener) => {
183
+ if (!host) return () => {};
179
184
  host.addEventListener("guestunload", handler);
180
185
 
181
186
  return () => {
@@ -183,9 +188,12 @@ export function useExtensions<
183
188
  };
184
189
  }, baseDeps);
185
190
 
186
- const [extensions, setExtensions] = useState(() => getExtensions());
191
+ const [extensions, setExtensions] =
192
+ useState<TypedGuestConnection<Incoming>[]>(NO_EXTENSIONS);
187
193
 
188
194
  useEffect(() => {
195
+ // Sync current guests immediately when host becomes available, then subscribe to future loads.
196
+ setExtensions(getExtensions());
189
197
  return subscribe(() => setExtensions(getExtensions()));
190
198
  }, [subscribe]);
191
199
 
@@ -215,15 +223,22 @@ export function useExtensions<
215
223
  }
216
224
  }, [provides, extensions]);
217
225
 
218
- useEffect(
219
- () =>
220
- host.addEventListener(
221
- "error",
222
- (event: Extract<HostEvents, { detail: { error: Error } }>) =>
223
- setHostError(event.detail.error)
224
- ),
225
- baseDeps
226
- );
226
+ useEffect(() => {
227
+ if (!host) return;
228
+ return host.addEventListener(
229
+ "error",
230
+ (event: Extract<HostEvents, { detail: { error: Error } }>) =>
231
+ setHostError(event.detail.error)
232
+ );
233
+ }, baseDeps);
234
+
235
+ if (contextError) {
236
+ return {
237
+ extensions: NO_EXTENSIONS,
238
+ loading: false,
239
+ error: contextError,
240
+ };
241
+ }
227
242
 
228
243
  return {
229
244
  extensions,