Browse Source

enhance(plugin): WIP install plugin from web

charlie 10 months ago
parent
commit
1af1c14edc

+ 41 - 19
libs/src/LSPlugin.core.ts

@@ -153,6 +153,7 @@ interface PluginLocalOptions {
   name: string
   version: string
   mode: 'shadow' | 'iframe'
+  webPkg?: any // web plugin package.json data
   settingsSchema?: SettingSchemaDesc[]
   settings?: PluginSettings
   effect?: boolean
@@ -506,6 +507,12 @@ class PluginLocal extends EventEmitter<
   _resolveResourceFullUrl(filePath: string, localRoot?: string) {
     if (!filePath?.trim()) return
     localRoot = localRoot || this._localRoot
+
+    if (this.isWebPlugin) {
+      // TODO: strategy for Logseq plugins center
+      return `https://pub-80f42b85b62c40219354a834fcf2bbfa.r2.dev/${path.join(localRoot, filePath)}`
+    }
+
     const reg = /^(http|file)/
     if (!reg.test(filePath)) {
       const url = path.join(localRoot, filePath)
@@ -517,29 +524,28 @@ class PluginLocal extends EventEmitter<
   }
 
   async _preparePackageConfigs() {
-    const { url } = this._options
-    let pkg: any
+    const { url, webPkg } = this._options
+    let pkg: any = webPkg
 
-    try {
-      if (!url) {
-        throw new Error('Can not resolve package config location')
-      }
+    if (!pkg) {
+      try {
+        if (!url) {
+          throw new Error('Can not resolve package config location')
+        }
 
-      debug('prepare package root', url)
+        debug('prepare package root', url)
 
-      pkg = await invokeHostExportedApi('load_plugin_config', url)
+        pkg = await invokeHostExportedApi('load_plugin_config', url)
 
-      if (!pkg || ((pkg = JSON.parse(pkg)), !pkg)) {
-        throw new Error(`Parse package config error #${url}/package.json`)
+        if (!pkg || ((pkg = JSON.parse(pkg)), !pkg)) {
+          throw new Error(`Parse package config error #${url}/package.json`)
+        }
+      } catch (e) {
+        throw new IllegalPluginPackageError(e.message)
       }
-    } catch (e) {
-      throw new IllegalPluginPackageError(e.message)
     }
 
-    const localRoot = (this._localRoot = safetyPathNormalize(url))
-    const logseq: Partial<LSPluginPkgConfig> = pkg.logseq || {}
-
-      // Pick legal attrs
+    // Pick legal attrs
     ;[
       'name',
       'author',
@@ -556,13 +562,19 @@ class PluginLocal extends EventEmitter<
         this._options[k] = pkg[k]
       })
 
+    const { repo, version } = this._options
+    const localRoot = (this._localRoot = this.isWebPlugin ? `${repo}/${version}` : safetyPathNormalize(url))
+    const logseq: Partial<LSPluginPkgConfig> = pkg.logseq || {}
     const validateEntry = (main) => main && /\.(js|html)$/.test(main)
 
     // Entry from main
     const entry = logseq.entry || logseq.main || pkg.main
+
     if (validateEntry(entry)) {
       // Theme has no main
       this._options.entry = this._resolveResourceFullUrl(entry, localRoot)
+
+      // development mode entry
       this._options.devEntry = logseq.devEntry
 
       if (logseq.mode) {
@@ -674,9 +686,10 @@ class PluginLocal extends EventEmitter<
       if (!options.url) return
 
       if (!options.url.startsWith('http') && this._localRoot) {
-        options.url = path.join(this._localRoot, options.url)
+        options.url = this._resolveResourceFullUrl(options.url, this._localRoot)
+
         // file:// for native
-        if (!options.url.startsWith('file:')) {
+        if (!this.isWebPlugin && !options.url.startsWith('file:')) {
           options.url = 'assets://' + options.url
         }
       }
@@ -971,12 +984,17 @@ class PluginLocal extends EventEmitter<
     }
   }
 
+  get isWebPlugin() {
+    return !!this.options.webPkg
+  }
+
   get layoutCore(): any {
     // @ts-expect-error
     return window.frontend.modules.layout.core
   }
 
   get isInstalledInDotRoot() {
+    if (this.isWebPlugin) return false
     const dotRoot = this.dotConfigRoot
     const plgRoot = this.localRoot
     return dotRoot && plgRoot && plgRoot.startsWith(dotRoot)
@@ -1235,7 +1253,7 @@ class LSPluginCore
     try {
       this._isRegistering = true
 
-      const userConfigRoot = this._options.dotConfigRoot
+      const _userConfigRoot = this._options.dotConfigRoot
       const readyIndicator = (this._readyIndicator = deferred())
 
       await this.loadUserPreferences()
@@ -1488,6 +1506,10 @@ class LSPluginCore
     return cleanInjectedUI(id)
   }
 
+  get isWebPlatform() {
+    return this.options.dotConfigRoot?.startsWith('LSPUserDotRoot')
+  }
+
   get registeredPlugins(): Map<PluginLocalIdentity, PluginLocal> {
     return this._registeredPlugins
   }

+ 2 - 2
src/main/frontend/handler/common/plugin.cljs

@@ -40,13 +40,13 @@
   [{:keys [version repo only-check _plugin-action] :as mft}]
   (js/console.log "debug:install-or-update" mft)
   (-> (fetch-web-plugin-entry-info repo version)
-    (p/then (fn [{:keys [version]}]
+    (p/then (fn [{:keys [_version] :as web-pkg}]
               (emit-lsp-updates!
                 {:status :completed
                  :only-check only-check
                  :payload (if only-check
                             (assoc mft :latest-version version :latest-notes "TODO: update notes")
-                            (assoc mft :dst repo :installed-version version :web true))})))
+                            (assoc mft :dst repo :installed-version version :web-pkg (merge web-pkg mft)))})))
     (p/catch (fn [^js e]
                (emit-lsp-updates!
                  {:status :error

+ 2 - 2
src/main/frontend/handler/plugin.cljs

@@ -203,7 +203,7 @@
                        (case (keyword status)
 
                          :completed
-                         (let [{:keys [id dst name title theme]} payload
+                         (let [{:keys [id dst name title theme web-pkg]} payload
                                name (or title name "Untitled")]
                            (if only-check
                              (state/consume-updates-from-coming-plugin! payload false)
@@ -218,7 +218,7 @@
                                         (t :plugin/update-plugin name (.-version (.-options pl))) :success)
                                       (state/consume-updates-from-coming-plugin! payload true))))
                                ;; register plugin
-                               (-> (js/LSPluginCore.register (bean/->js {:key id :url dst}))
+                               (-> (js/LSPluginCore.register (bean/->js {:key id :url dst :webPkg web-pkg}))
                                  (p/then (fn []
                                            (when theme (js/setTimeout #(select-a-plugin-theme id) 300))
                                            (notification/show!

+ 4 - 1
src/main/logseq/api.cljs

@@ -206,7 +206,10 @@
 
 (def ^:export load_plugin_config
   (fn [path]
-    (fs/read-file nil (util/node-path.join path "package.json"))))
+    (if (util/electron?)
+      (fs/read-file nil (util/node-path.join path "package.json"))
+      (do (js/console.log "==>>> TODO: load plugin package.json from local???")
+        ""))))
 
 (def ^:export load_plugin_readme
   (fn [path]