@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.
- package/dist/components/Extensible.d.ts.map +1 -1
- package/dist/components/ExtensibleWrapper/ExtensibleWrapper.d.ts +4 -0
- package/dist/components/ExtensibleWrapper/ExtensibleWrapper.d.ts.map +1 -1
- package/dist/components/ExtensibleWrapper/ExtensionManagerProvider.d.ts +25 -8
- package/dist/components/ExtensibleWrapper/ExtensionManagerProvider.d.ts.map +1 -1
- package/dist/components/ExtensibleWrapper/UrlExtensionProvider.d.ts +5 -3
- package/dist/components/ExtensibleWrapper/UrlExtensionProvider.d.ts.map +1 -1
- package/dist/hooks/useExtensions.d.ts.map +1 -1
- package/dist/index.js +32 -27
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/Extensible.test.tsx +38 -0
- package/src/components/Extensible.tsx +6 -11
- package/src/components/ExtensibleWrapper/ExtensibleWrapper.tsx +4 -0
- package/src/components/ExtensibleWrapper/ExtensionManagerProvider.ts +25 -8
- package/src/components/ExtensibleWrapper/UrlExtensionProvider.ts +5 -3
- package/src/hooks/useExtensions.ts +34 -19
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Extensible.d.ts","sourceRoot":"","sources":["../../src/components/Extensible.tsx"],"names":[],"mappings":"AAYA,OAAO,
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
125
|
+
* @internal
|
|
109
126
|
*/
|
|
110
127
|
export declare function buildExtensionManagerUrl(config: ExtensionManagerConfig): string;
|
|
111
128
|
/**
|
|
112
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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":"AAAA;;;;;;;;;;;;;;;4EAe4E;AAE5E,OAAO,EAEL,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAYzB,KAAK,cAAc,GAAG;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AACF,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
|
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,
|
|
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
|
-
|
|
140
|
-
|
|
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(
|
|
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(
|
|
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
|
-
()
|
|
608
|
+
React.useEffect(() => {
|
|
609
|
+
if (!host)
|
|
610
|
+
return;
|
|
611
|
+
return host.addEventListener(
|
|
613
612
|
"error",
|
|
614
613
|
(event) => setHostError(event.detail.error)
|
|
615
|
-
)
|
|
616
|
-
|
|
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.
|
|
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.
|
|
24
|
-
"@adobe/uix-host": "^1.1.
|
|
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
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
|
|
119
|
-
|
|
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(
|
|
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] =
|
|
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
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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,
|