@@ -36,6 +36,7 @@ import Color from "utils/color";
3636import encodings from "utils/encodings" ;
3737import helpers from "utils/helpers" ;
3838import KeyboardEvent from "utils/keyboardEvent" ;
39+ import constants from "./constants" ;
3940
4041import { addMode , removeMode } from "ace/modelist" ;
4142import { addIntentHandler , removeIntentHandler } from "handlers/intent" ;
@@ -157,6 +158,77 @@ export default class Acode {
157158 }
158159 }
159160
161+ /**
162+ * Installs an Acode plugin from registry
163+ * @param {string } pluginId id of the plugin to install
164+ * @param {string } installerPluginName Name of plugin attempting to install
165+ * @returns {Promise<void> }
166+ */
167+ installPlugin ( pluginId , installerPluginName ) {
168+ return new Promise ( async ( resolve , reject ) => {
169+ try {
170+ const confirmation = await confirm (
171+ strings [ "install" ] ,
172+ `Do you want to install plugin '${ pluginId } '${ installerPluginName ? ` requested by ${ installerPluginName } ` : "" } ?` ,
173+ ) ;
174+
175+ if ( ! confirmation ) {
176+ reject ( new Error ( "User cancelled installation" ) ) ;
177+ return ;
178+ }
179+
180+ const isPluginExists = await fsOperation (
181+ Url . join ( PLUGIN_DIR , pluginId ) ,
182+ ) . exists ( ) ;
183+ if ( isPluginExists ) {
184+ reject ( new Error ( "PLugin already installed" ) ) ;
185+ return ;
186+ }
187+
188+ let purchaseToken = null ;
189+
190+ const pluginUrl = Url . join ( constants . API_BASE , `plugin/${ pluginId } ` ) ;
191+ const remotePlugin = await fsOperation ( pluginUrl )
192+ . readFile ( "json" )
193+ . catch ( ( ) => {
194+ reject ( new Error ( "Failed to fetch plugin details" ) ) ;
195+ return null ;
196+ } ) ;
197+
198+ if ( remotePlugin ) {
199+ if ( Number . parseFloat ( remotePlugin . price ) > 0 ) {
200+ try {
201+ const [ product ] = await helpers . promisify ( iap . getProducts , [
202+ remotePlugin . sku ,
203+ ] ) ;
204+ if ( product ) {
205+ async function getPurchase ( sku ) {
206+ const purchases = await helpers . promisify ( iap . getPurchases ) ;
207+ const purchase = purchases . find ( ( p ) =>
208+ p . productIds . includes ( sku ) ,
209+ ) ;
210+ return purchase ;
211+ }
212+ const purchase = await getPurchase ( product . productId ) ;
213+ purchaseToken = purchase ?. purchaseToken ;
214+ }
215+ } catch ( error ) {
216+ helpers . error ( error ) ;
217+ reject ( new Error ( "Failed to validate purchase" ) ) ;
218+ return ;
219+ }
220+ }
221+ }
222+
223+ const { default : installPlugin } = await import ( "lib/installPlugin" ) ;
224+ await installPlugin ( pluginId , remotePlugin . name , purchaseToken ) ;
225+ resolve ( ) ;
226+ } catch ( error ) {
227+ reject ( error ) ;
228+ }
229+ } ) ;
230+ }
231+
160232 get exitAppMessage ( ) {
161233 const numFiles = editorManager . hasUnsavedFiles ( ) ;
162234 if ( numFiles ) {
0 commit comments