@adobe/uix-host 0.6.3
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/LICENSE +201 -0
- package/README.md +1 -0
- package/dist/debug-host.d.ts +8 -0
- package/dist/debug-host.d.ts.map +1 -0
- package/dist/esm/index.js +408 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/extensions-provider/composition.d.ts +9 -0
- package/dist/extensions-provider/composition.d.ts.map +1 -0
- package/dist/extensions-provider/extension-registry.d.ts +29 -0
- package/dist/extensions-provider/extension-registry.d.ts.map +1 -0
- package/dist/extensions-provider/index.d.ts +3 -0
- package/dist/extensions-provider/index.d.ts.map +1 -0
- package/dist/host.d.ts +247 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +413 -0
- package/dist/index.js.map +1 -0
- package/dist/port.d.ts +173 -0
- package/dist/port.d.ts.map +1 -0
- package/package.json +39 -0
- package/src/debug-host.ts +79 -0
- package/src/extensions-provider/composition.ts +30 -0
- package/src/extensions-provider/extension-registry.ts +152 -0
- package/src/extensions-provider/index.ts +14 -0
- package/src/host.ts +429 -0
- package/src/index.ts +76 -0
- package/src/port.ts +430 -0
- package/tsconfig.json +19 -0
package/dist/port.d.ts
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
import type { Emits, GuestConnection, HostMethodAddress, NamedEvent, RemoteHostApis, GuestApis } from "@adobe/uix-core";
|
2
|
+
import { Emitter } from "@adobe/uix-core";
|
3
|
+
import { Connection } from "penpal";
|
4
|
+
/**
|
5
|
+
* A specifier for methods to be expected on a remote interface.
|
6
|
+
*
|
7
|
+
* @remarks
|
8
|
+
* A CapabilitySpec is a description of an interface, like a very simplified
|
9
|
+
* type definition. It specifies an object structure and the paths in that
|
10
|
+
* structure that must be functions. (It doesn't specify anything about the
|
11
|
+
* signatures or return values of those functions.)
|
12
|
+
*
|
13
|
+
* Use CapabilitySpec objects as queries, or filters, to get a subset of
|
14
|
+
* installed extensions which have registered methods which match the spec.
|
15
|
+
*
|
16
|
+
* @example
|
17
|
+
* As an extensible app developer, you are making an extension point for spell
|
18
|
+
* check. Your code expects extensions to register an API `spellCheck` with
|
19
|
+
* methods called `spellCheck.correct(text)` and `spellCheck.suggest(text)`.
|
20
|
+
*
|
21
|
+
* ```javascript
|
22
|
+
* async function correctText(text) {
|
23
|
+
* const spellCheckers = host.getLoadedGuests({
|
24
|
+
* spellCheck: [
|
25
|
+
* 'correct',
|
26
|
+
* 'suggest'
|
27
|
+
* ]
|
28
|
+
* });
|
29
|
+
* let correcting = text;
|
30
|
+
* for (const checker of spellCheckers) {
|
31
|
+
* correcting = await checker.apis.spellCheck.correct(correcting);
|
32
|
+
* }
|
33
|
+
* return Promise.all(checkers.map(checker =>
|
34
|
+
* checker.apis.spellCheck.suggest(correcting)
|
35
|
+
* ));
|
36
|
+
* }
|
37
|
+
* ```
|
38
|
+
*
|
39
|
+
* @public
|
40
|
+
*/
|
41
|
+
export declare type CapabilitySpec<T extends GuestApis> = {
|
42
|
+
[Name in keyof T]: (keyof T[Name])[];
|
43
|
+
};
|
44
|
+
/** @public */
|
45
|
+
declare type PortEvent<GuestApi, Type extends string = string, Detail = Record<string, unknown>> = NamedEvent<Type, Detail & Record<string, unknown> & {
|
46
|
+
guestPort: Port<GuestApi>;
|
47
|
+
}>;
|
48
|
+
/** @public */
|
49
|
+
export declare type PortEvents<GuestApi, HostApi extends Record<string, unknown> = Record<string, unknown>> = PortEvent<GuestApi, "hostprovide"> | PortEvent<GuestApi, "unload"> | PortEvent<GuestApi, "beforecallhostmethod", HostMethodAddress<HostApi>>;
|
50
|
+
/** @public */
|
51
|
+
export declare type PortOptions = {
|
52
|
+
/**
|
53
|
+
* Time in milliseconds to wait for the guest to connect before throwing.
|
54
|
+
*/
|
55
|
+
timeout?: number;
|
56
|
+
/**
|
57
|
+
* Set true to log copiously in the console.
|
58
|
+
*/
|
59
|
+
debug?: boolean;
|
60
|
+
};
|
61
|
+
/**
|
62
|
+
* A Port is the Host-maintained object representing an extension running as a
|
63
|
+
* guest. It exposes methods registered by the Guest, and can provide Host
|
64
|
+
* methods back to the guest.
|
65
|
+
*
|
66
|
+
* @remarks
|
67
|
+
* When the Host object loads extensions via {@link Host.load}, it creates a
|
68
|
+
* Port object for each extension. When retrieving and filtering extensions
|
69
|
+
* via {@link Host.(getLoadedGuests:2)}, a list of Port objects is returned. From
|
70
|
+
* the point of view of the extensible app using the Host object, extensions
|
71
|
+
* are always Port objects, which expose the methods registered by the
|
72
|
+
* extension at the {@link Port.apis} property.
|
73
|
+
*
|
74
|
+
* @privateRemarks
|
75
|
+
* We've gone through several possible names for this object. GuestProxy,
|
76
|
+
* GuestInterface, GuestConnection, etc. "Port" is not ideal, but it conflicted
|
77
|
+
* the least with other types we defined in early drafts. It's definitely
|
78
|
+
* something we should review.
|
79
|
+
* @public
|
80
|
+
*/
|
81
|
+
export declare class Port<GuestApi> extends Emitter<PortEvents<GuestApi>> implements GuestConnection {
|
82
|
+
private connection;
|
83
|
+
private debug;
|
84
|
+
private debugLogger?;
|
85
|
+
private frame;
|
86
|
+
private guest;
|
87
|
+
private hostApis;
|
88
|
+
private isLoaded;
|
89
|
+
private runtimeContainer;
|
90
|
+
private sharedContext;
|
91
|
+
private subscriptions;
|
92
|
+
private timeout;
|
93
|
+
/**
|
94
|
+
* Dictionary of namespaced methods that were registered by this guest at the
|
95
|
+
* time of connection, using {@link @adobe/uix-guest#register}.
|
96
|
+
*
|
97
|
+
* @remarks
|
98
|
+
* These methods are proxy methods; you can only pass serializable objects to
|
99
|
+
* them, not class instances, methods or callbacks.
|
100
|
+
* @public
|
101
|
+
*/
|
102
|
+
apis: RemoteHostApis;
|
103
|
+
/**
|
104
|
+
* If any errors occurred during the loading of guests, this property will
|
105
|
+
* contain the error that was raised.
|
106
|
+
* @public
|
107
|
+
*/
|
108
|
+
error?: Error;
|
109
|
+
private uiConnections;
|
110
|
+
/**
|
111
|
+
* The URL of the guest provided by the extension registry. The Host will
|
112
|
+
* load this URL in the background, in the invisible the bootstrap frame, so
|
113
|
+
* this URL must point to a page that calls {@link @adobe/uix-guest#register}
|
114
|
+
* when it loads.
|
115
|
+
*/
|
116
|
+
url: URL;
|
117
|
+
constructor(config: {
|
118
|
+
owner: string;
|
119
|
+
id: string;
|
120
|
+
url: URL;
|
121
|
+
/**
|
122
|
+
* An alternate DOM element to use for invisible iframes. Will create its
|
123
|
+
* own if this option is not populated with a DOM element.
|
124
|
+
*/
|
125
|
+
runtimeContainer: HTMLElement;
|
126
|
+
options: PortOptions;
|
127
|
+
debugLogger?: Console;
|
128
|
+
/**
|
129
|
+
* Initial object to populate the shared context with. Once the guest
|
130
|
+
* connects, it will be able to access these properties.
|
131
|
+
*/
|
132
|
+
sharedContext: Record<string, unknown>;
|
133
|
+
events: Emits;
|
134
|
+
});
|
135
|
+
/**
|
136
|
+
* Connect an iframe element which is displaying another page in the extension
|
137
|
+
* with the extension's bootstrap frame, so they can share context and events.
|
138
|
+
*/
|
139
|
+
attachUI(iframe: HTMLIFrameElement): Connection<RemoteHostApis<GuestApi>>;
|
140
|
+
/**
|
141
|
+
* Returns true if the guest has registered methods matching the provided
|
142
|
+
* capability spec. A capability spec is simply an object whose properties are
|
143
|
+
* declared in an array of keys, description the names of the functions and
|
144
|
+
* methods that the Port will expose.
|
145
|
+
*/
|
146
|
+
hasCapabilities(requiredMethods: CapabilitySpec<GuestApis>): boolean;
|
147
|
+
/**
|
148
|
+
* True when al extensions have loaded.
|
149
|
+
*/
|
150
|
+
isReady(): boolean;
|
151
|
+
/**
|
152
|
+
* Loads the extension. Returns a promise which resolves when the extension
|
153
|
+
* has loaded. The Host calls this method after retrieving extensions.
|
154
|
+
*/
|
155
|
+
load(): Promise<RemoteHostApis<import("@adobe/uix-core").VirtualApi>>;
|
156
|
+
/**
|
157
|
+
* The host-side equivalent of {@link @adobe/uix-guest#register}. Pass a set
|
158
|
+
* of methods down to the guest as proxies.
|
159
|
+
*/
|
160
|
+
provide(apis: RemoteHostApis): void;
|
161
|
+
/**
|
162
|
+
* Disconnect from the extension.
|
163
|
+
*/
|
164
|
+
unload(): Promise<void>;
|
165
|
+
private assert;
|
166
|
+
private assertReady;
|
167
|
+
private attachFrame;
|
168
|
+
private connect;
|
169
|
+
private getHostMethodCallee;
|
170
|
+
private invokeHostMethod;
|
171
|
+
}
|
172
|
+
export {};
|
173
|
+
//# sourceMappingURL=port.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../src/port.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
{
|
2
|
+
"name": "@adobe/uix-host",
|
3
|
+
"version": "0.6.3",
|
4
|
+
"description": "Tools for embedding UIX Extensions into Adobe apps",
|
5
|
+
"author": "Adobe, Inc,",
|
6
|
+
"type": "module",
|
7
|
+
"module": "dist/esm/index.js",
|
8
|
+
"main": "dist/index.js",
|
9
|
+
"exports": {
|
10
|
+
"import": "./dist/esm/index.js",
|
11
|
+
"require": "./dist/index.js"
|
12
|
+
},
|
13
|
+
"types": "dist/index.d.ts",
|
14
|
+
"scripts": {
|
15
|
+
"build": "tsup",
|
16
|
+
"watch": "tsup --watch --silent"
|
17
|
+
},
|
18
|
+
"browserslist": [
|
19
|
+
"> 0.2%, last 2 versions, not dead"
|
20
|
+
],
|
21
|
+
"bugs": "https://git.corp.adobe.com/dx-devex-acceleration/uix-sdk/issues",
|
22
|
+
"dependencies": {
|
23
|
+
"@adobe/uix-core": "^0.6.3",
|
24
|
+
"penpal": "~6.2.2"
|
25
|
+
},
|
26
|
+
"files": [
|
27
|
+
"README.md",
|
28
|
+
"dist",
|
29
|
+
"src",
|
30
|
+
"tsconfig.json"
|
31
|
+
],
|
32
|
+
"homepage": "https://git.corp.adobe.com/dx-devex-acceleration/uix-sdk",
|
33
|
+
"license": "Apache-2.0",
|
34
|
+
"repository": {
|
35
|
+
"type": "git",
|
36
|
+
"url": "https://git.corp.adobe.com/dx-devex-acceleration/uix-sdk.git"
|
37
|
+
},
|
38
|
+
"sideEffects": false
|
39
|
+
}
|
@@ -0,0 +1,79 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2022 Adobe. All rights reserved.
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
10
|
+
governing permissions and limitations under the License.
|
11
|
+
*/
|
12
|
+
|
13
|
+
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
14
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
15
|
+
/**
|
16
|
+
* Adapter to attach console logging listeners to a Host running in an app
|
17
|
+
* @hidden
|
18
|
+
*/
|
19
|
+
import {
|
20
|
+
debugEmitter,
|
21
|
+
EmitterDebugLogger,
|
22
|
+
Emits,
|
23
|
+
GuestConnection,
|
24
|
+
} from "@adobe/uix-core";
|
25
|
+
import type { PortEvents } from "./port.js";
|
26
|
+
import type { HostEventLoadAllGuests, HostEvents } from "./host.js";
|
27
|
+
|
28
|
+
type GenericPortEvents = PortEvents<Record<string, unknown>>;
|
29
|
+
|
30
|
+
type Portlike = GuestConnection & Emits<GenericPortEvents>;
|
31
|
+
|
32
|
+
export function debugHost(host: Emits<HostEvents>): EmitterDebugLogger {
|
33
|
+
const hostLogger = debugEmitter(host, {
|
34
|
+
theme: "blue medium",
|
35
|
+
type: "Host",
|
36
|
+
});
|
37
|
+
hostLogger
|
38
|
+
.listen("guestbeforeload", (log, event) => {
|
39
|
+
const { detail } = event;
|
40
|
+
const guest = detail.guest as Portlike;
|
41
|
+
log.info(event, `Guest ID ${guest.id}`);
|
42
|
+
const portLogger = debugEmitter(guest, {
|
43
|
+
theme: "green medium",
|
44
|
+
type: "Port",
|
45
|
+
id: `${host.id} ➔ ${guest.id}`,
|
46
|
+
});
|
47
|
+
portLogger
|
48
|
+
.listen("hostprovide", (log, event) => {
|
49
|
+
log.info("received APIs", event.detail.apis);
|
50
|
+
})
|
51
|
+
.listen("beforecallhostmethod", (log, event) => {
|
52
|
+
log.info(event.detail);
|
53
|
+
})
|
54
|
+
.listen("unload", (log, event) => {
|
55
|
+
log.info(event.detail);
|
56
|
+
log.detach();
|
57
|
+
});
|
58
|
+
})
|
59
|
+
.listen("guestload", (log, e) => {
|
60
|
+
log.info(e.detail.guest.id, e.detail.guest);
|
61
|
+
})
|
62
|
+
.listen("error", (log, e) => {
|
63
|
+
log.error(`Error: ${e.detail.error.message}`, e);
|
64
|
+
})
|
65
|
+
.listen(
|
66
|
+
"loadallguests",
|
67
|
+
(log, { detail: { failed, loaded, host } }: HostEventLoadAllGuests) => {
|
68
|
+
if (failed.length > 0) {
|
69
|
+
log.error("%d guests failed to load!", failed.length);
|
70
|
+
}
|
71
|
+
log.info("%d guests loaded", loaded.length, host);
|
72
|
+
}
|
73
|
+
)
|
74
|
+
.listen("unload", (log) => {
|
75
|
+
log.info("Unloaded guest and container.");
|
76
|
+
log.detach();
|
77
|
+
});
|
78
|
+
return hostLogger;
|
79
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2022 Adobe. All rights reserved.
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
10
|
+
governing permissions and limitations under the License.
|
11
|
+
*/
|
12
|
+
|
13
|
+
import { InstalledExtensions, ExtensionsProvider } from "../host.js";
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Combine multiple {@link @adobe/uix-host#ExtensionsProvider} callbacks into a
|
17
|
+
* single callback, which aggregates and dedupes all extensions from all
|
18
|
+
* providers into one namespaced object.
|
19
|
+
* @public
|
20
|
+
*/
|
21
|
+
export function combineExtensionsFromProviders(
|
22
|
+
...providers: Array<ExtensionsProvider>
|
23
|
+
): ExtensionsProvider {
|
24
|
+
return () =>
|
25
|
+
Promise.all(providers.map((ep: ExtensionsProvider) => ep())).then(
|
26
|
+
(extensionsBatches: Array<InstalledExtensions>) => {
|
27
|
+
return Object.assign({}, ...extensionsBatches);
|
28
|
+
}
|
29
|
+
);
|
30
|
+
}
|
@@ -0,0 +1,152 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2022 Adobe. All rights reserved.
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
10
|
+
governing permissions and limitations under the License.
|
11
|
+
*/
|
12
|
+
|
13
|
+
import { InstalledExtensions, ExtensionsProvider } from "../host.js";
|
14
|
+
|
15
|
+
interface ExtensionDefinition {
|
16
|
+
name: string;
|
17
|
+
title: string;
|
18
|
+
description: string;
|
19
|
+
icon: string;
|
20
|
+
publisher: string;
|
21
|
+
endpoints: Record<string, EndpointDefinition>;
|
22
|
+
xrInfo: ExtensionInfo;
|
23
|
+
status: string;
|
24
|
+
}
|
25
|
+
|
26
|
+
type EndpointDefinition = Record<string, Array<OperationDefinition>>;
|
27
|
+
|
28
|
+
interface ExtensionInfo {
|
29
|
+
supportEmail: string;
|
30
|
+
appId: string;
|
31
|
+
}
|
32
|
+
|
33
|
+
interface OperationDefinition {
|
34
|
+
href: string;
|
35
|
+
metadata: OperationMetadata;
|
36
|
+
}
|
37
|
+
|
38
|
+
interface OperationMetadata {
|
39
|
+
services: Array<object>;
|
40
|
+
profile: OperationProfile;
|
41
|
+
}
|
42
|
+
|
43
|
+
interface OperationProfile {
|
44
|
+
client_id: string;
|
45
|
+
scope: string;
|
46
|
+
}
|
47
|
+
|
48
|
+
/** @public */
|
49
|
+
export interface ExtensionRegistryEndpointRegistration {
|
50
|
+
service: string;
|
51
|
+
extensionPoint: string;
|
52
|
+
version: string;
|
53
|
+
}
|
54
|
+
|
55
|
+
/** @public */
|
56
|
+
export interface ExtensionRegistryExtensionRegistration
|
57
|
+
extends ExtensionRegistryEndpointRegistration {
|
58
|
+
imsOrg: string;
|
59
|
+
}
|
60
|
+
|
61
|
+
/** @public */
|
62
|
+
export interface ExtensionRegistryConnection {
|
63
|
+
baseUrl?: string;
|
64
|
+
apiKey: string;
|
65
|
+
auth: {
|
66
|
+
schema: "Basic" | "Bearer";
|
67
|
+
imsToken: string;
|
68
|
+
};
|
69
|
+
}
|
70
|
+
|
71
|
+
/** @public */
|
72
|
+
export interface ExtensionRegistryConfig
|
73
|
+
extends ExtensionRegistryExtensionRegistration,
|
74
|
+
ExtensionRegistryConnection {}
|
75
|
+
|
76
|
+
function buildEndpointPath(
|
77
|
+
config: ExtensionRegistryEndpointRegistration
|
78
|
+
): string {
|
79
|
+
return `${config.service}/${config.extensionPoint}/${config.version}`;
|
80
|
+
}
|
81
|
+
|
82
|
+
function ensureProtocolSpecified(url: string) {
|
83
|
+
if (url.startsWith("https://")) {
|
84
|
+
return url;
|
85
|
+
}
|
86
|
+
if (url.startsWith("http://")) {
|
87
|
+
return url;
|
88
|
+
}
|
89
|
+
return `https://${url}`;
|
90
|
+
}
|
91
|
+
|
92
|
+
async function fetchExtensionsFromRegistry(
|
93
|
+
config: ExtensionRegistryConfig
|
94
|
+
): Promise<Array<ExtensionDefinition>> {
|
95
|
+
const resp = await fetch(
|
96
|
+
`${ensureProtocolSpecified(
|
97
|
+
config.baseUrl || "appregistry.adobe.io"
|
98
|
+
)}/myxchng/v1/org/${encodeURIComponent(
|
99
|
+
config.imsOrg
|
100
|
+
)}/xtn/${buildEndpointPath(config)}?auth=true`,
|
101
|
+
{
|
102
|
+
headers: {
|
103
|
+
Accept: "application/json",
|
104
|
+
Authorization: `${config.auth.schema} ${config.auth.imsToken}`, // todo: check if auth schema needed (initial implementation was without it)
|
105
|
+
"X-Api-Key": config.apiKey,
|
106
|
+
},
|
107
|
+
}
|
108
|
+
);
|
109
|
+
|
110
|
+
if (resp.status != 200) {
|
111
|
+
throw new Error(
|
112
|
+
`extension registry returned non-200 response (${
|
113
|
+
resp.status
|
114
|
+
}): ${await resp.text()}`
|
115
|
+
);
|
116
|
+
}
|
117
|
+
|
118
|
+
return await resp.json();
|
119
|
+
}
|
120
|
+
|
121
|
+
function extensionRegistryExtensionsProvider(
|
122
|
+
config: ExtensionRegistryConfig
|
123
|
+
): Promise<InstalledExtensions> {
|
124
|
+
const erEndpoint = buildEndpointPath(config);
|
125
|
+
return fetchExtensionsFromRegistry(config).then((out) =>
|
126
|
+
out.reduce((a, e: ExtensionDefinition) => {
|
127
|
+
if (e.status !== "PUBLISHED") {
|
128
|
+
return a;
|
129
|
+
}
|
130
|
+
|
131
|
+
return {
|
132
|
+
...a,
|
133
|
+
// todo: make safer way to extract href
|
134
|
+
[e.name]: e.endpoints[erEndpoint].view[0].href,
|
135
|
+
};
|
136
|
+
}, {})
|
137
|
+
);
|
138
|
+
|
139
|
+
return Promise.resolve({});
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Create a callback that fetches extensions from the registry.
|
144
|
+
* @public
|
145
|
+
*/
|
146
|
+
export function createExtensionRegistryProvider(
|
147
|
+
config: ExtensionRegistryConfig
|
148
|
+
): ExtensionsProvider {
|
149
|
+
return function () {
|
150
|
+
return extensionRegistryExtensionsProvider(config);
|
151
|
+
};
|
152
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2022 Adobe. All rights reserved.
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
10
|
+
governing permissions and limitations under the License.
|
11
|
+
*/
|
12
|
+
|
13
|
+
export * from "./extension-registry.js";
|
14
|
+
export * from "./composition.js";
|