homebridge-config-ui-x 5.0.0-beta.6 → 5.0.0-beta.60
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/CHANGELOG.md +384 -20
- package/CONTRIBUTING.md +5 -4
- package/LICENSE +1 -1
- package/config.schema.json +34 -144
- package/dist/bin/hb-service.d.ts +2 -2
- package/dist/bin/hb-service.js +51 -50
- package/dist/bin/hb-service.js.map +1 -1
- package/dist/bin/platforms/darwin.js +2 -2
- package/dist/bin/platforms/darwin.js.map +1 -1
- package/dist/bin/platforms/win32.js +4 -2
- package/dist/bin/platforms/win32.js.map +1 -1
- package/dist/bin/standalone.js +1 -0
- package/dist/bin/standalone.js.map +1 -1
- package/dist/core/auth/auth.controller.d.ts +2 -2
- package/dist/core/auth/auth.controller.js.map +1 -1
- package/dist/core/auth/auth.module.js +1 -1
- package/dist/core/auth/auth.module.js.map +1 -1
- package/dist/core/auth/auth.service.js +10 -10
- package/dist/core/auth/auth.service.js.map +1 -1
- package/dist/core/auth/jwt.strategy.d.ts +3 -1
- package/dist/core/config/config.service.d.ts +4 -6
- package/dist/core/config/config.service.js +9 -9
- package/dist/core/config/config.service.js.map +1 -1
- package/dist/core/config/config.startup.js +2 -2
- package/dist/core/config/config.startup.js.map +1 -1
- package/dist/core/homebridge-ipc/homebridge-ipc.service.js +3 -3
- package/dist/core/homebridge-ipc/homebridge-ipc.service.js.map +1 -1
- package/dist/index.js +6 -77
- package/dist/index.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modules/accessories/accessories.controller.js +5 -5
- package/dist/modules/accessories/accessories.controller.js.map +1 -1
- package/dist/modules/accessories/accessories.service.js +8 -7
- package/dist/modules/accessories/accessories.service.js.map +1 -1
- package/dist/modules/backup/backup.controller.js +7 -7
- package/dist/modules/backup/backup.controller.js.map +1 -1
- package/dist/modules/backup/backup.service.d.ts +1 -0
- package/dist/modules/backup/backup.service.js +57 -89
- package/dist/modules/backup/backup.service.js.map +1 -1
- package/dist/modules/child-bridges/child-bridges.service.js +0 -7
- package/dist/modules/child-bridges/child-bridges.service.js.map +1 -1
- package/dist/modules/config-editor/config-editor.controller.d.ts +1 -1
- package/dist/modules/config-editor/config-editor.controller.js +8 -8
- package/dist/modules/config-editor/config-editor.controller.js.map +1 -1
- package/dist/modules/config-editor/config-editor.service.d.ts +1 -1
- package/dist/modules/config-editor/config-editor.service.js +62 -64
- package/dist/modules/config-editor/config-editor.service.js.map +1 -1
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.d.ts +1 -1
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.js +13 -11
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.js.map +1 -1
- package/dist/modules/log/log.gateway.d.ts +2 -1
- package/dist/modules/log/log.gateway.js.map +1 -1
- package/dist/modules/log/log.service.js +3 -3
- package/dist/modules/log/log.service.js.map +1 -1
- package/dist/modules/platform-tools/docker/docker.controller.js +3 -3
- package/dist/modules/platform-tools/docker/docker.controller.js.map +1 -1
- package/dist/modules/platform-tools/docker/docker.service.js +1 -1
- package/dist/modules/platform-tools/docker/docker.service.js.map +1 -1
- package/dist/modules/platform-tools/hb-service/hb-service.controller.js +3 -3
- package/dist/modules/platform-tools/hb-service/hb-service.controller.js.map +1 -1
- package/dist/modules/platform-tools/hb-service/hb-service.service.js +6 -6
- package/dist/modules/platform-tools/hb-service/hb-service.service.js.map +1 -1
- package/dist/modules/platform-tools/linux/linux.controller.js +2 -2
- package/dist/modules/platform-tools/linux/linux.controller.js.map +1 -1
- package/dist/modules/platform-tools/linux/linux.service.js +2 -2
- package/dist/modules/platform-tools/linux/linux.service.js.map +1 -1
- package/dist/modules/platform-tools/terminal/terminal.gateway.d.ts +2 -1
- package/dist/modules/platform-tools/terminal/terminal.gateway.js.map +1 -1
- package/dist/modules/platform-tools/terminal/terminal.service.js +2 -2
- package/dist/modules/platform-tools/terminal/terminal.service.js.map +1 -1
- package/dist/modules/plugins/plugins.controller.js +4 -4
- package/dist/modules/plugins/plugins.controller.js.map +1 -1
- package/dist/modules/plugins/plugins.service.d.ts +4 -1
- package/dist/modules/plugins/plugins.service.js +174 -103
- package/dist/modules/plugins/plugins.service.js.map +1 -1
- package/dist/modules/server/server.controller.d.ts +22 -2
- package/dist/modules/server/server.controller.js +86 -18
- package/dist/modules/server/server.controller.js.map +1 -1
- package/dist/modules/server/server.service.d.ts +24 -6
- package/dist/modules/server/server.service.js +186 -67
- package/dist/modules/server/server.service.js.map +1 -1
- package/dist/modules/status/status.controller.d.ts +0 -1
- package/dist/modules/status/status.controller.js +3 -4
- package/dist/modules/status/status.controller.js.map +1 -1
- package/dist/modules/status/status.gateway.d.ts +1 -1
- package/dist/modules/status/status.service.d.ts +1 -1
- package/dist/modules/status/status.service.js +17 -41
- package/dist/modules/status/status.service.js.map +1 -1
- package/dist/modules/users/users.controller.js +7 -7
- package/dist/modules/users/users.controller.js.map +1 -1
- package/dist/self-check.js +6 -6
- package/dist/self-check.js.map +1 -1
- package/package.json +45 -43
- package/public/3rdpartylicenses.txt +119 -62
- package/public/assets/hap-icons/airpurifier.svg +49 -16
- package/public/assets/hap-icons/airquality.svg +24 -13
- package/public/assets/hap-icons/co-sensor.svg +72 -0
- package/public/assets/hap-icons/co2-sensor.svg +72 -0
- package/public/assets/hap-icons/contactsensor-closed.svg +35 -2
- package/public/assets/hap-icons/contactsensor-open.svg +80 -2
- package/public/assets/hap-icons/door-closed.svg +32 -2
- package/public/assets/hap-icons/door-open.svg +48 -2
- package/public/assets/hap-icons/fan-off.svg +24 -13
- package/public/assets/hap-icons/fan-on.svg +24 -13
- package/public/assets/hap-icons/garagedoor.svg +24 -13
- package/public/assets/hap-icons/humidity.svg +24 -13
- package/public/assets/hap-icons/irrigation-system.svg +47 -18
- package/public/assets/hap-icons/leaksensor.svg +52 -2
- package/public/assets/hap-icons/light.svg +47 -28
- package/public/assets/hap-icons/lightbulb.svg +24 -13
- package/public/assets/hap-icons/lock-locked.svg +24 -13
- package/public/assets/hap-icons/lock-unlocked.svg +24 -13
- package/public/assets/hap-icons/motionsensor.svg +100 -2
- package/public/assets/hap-icons/occupancysensor.svg +97 -2
- package/public/assets/hap-icons/outlet.svg +24 -13
- package/public/assets/hap-icons/securitysystem-active.svg +102 -2
- package/public/assets/hap-icons/securitysystem-off.svg +68 -2
- package/public/assets/hap-icons/smokesensor.svg +42 -9
- package/public/assets/hap-icons/speaker.svg +29 -13
- package/public/assets/hap-icons/statelessprogrammableswitch.svg +51 -2
- package/public/assets/hap-icons/switch.svg +24 -13
- package/public/assets/hap-icons/television.svg +15 -4
- package/public/assets/hap-icons/temperature.svg +24 -13
- package/public/assets/hap-icons/unknown.svg +24 -13
- package/public/assets/hap-icons/valve-generic.svg +27 -16
- package/public/assets/hap-icons/valve-irrigation.svg +37 -21
- package/public/assets/hap-icons/valve-showerhead.svg +52 -0
- package/public/assets/hap-icons/valve-waterfaucet.svg +21 -0
- package/public/assets/hap-icons/window-closed.svg +85 -2
- package/public/assets/hap-icons/window-open.svg +136 -2
- package/public/assets/hap-icons/windowcovering-closed.svg +45 -49
- package/public/assets/hap-icons/windowcovering-open.svg +40 -44
- package/public/assets/homebridge-color-round.svg +36 -1
- package/public/assets/homebridge-logo.svg +11 -1
- package/public/assets/mask-icon.svg +5 -1
- package/public/chunk-2HDJYV7P.js +1 -0
- package/public/chunk-2PYGXL3S.js +1 -0
- package/public/chunk-3JURJEIZ.js +1 -0
- package/public/chunk-3MYZ74PN.js +1 -0
- package/public/{chunk-CCUID66K.js → chunk-3NAAMMFZ.js} +1 -1
- package/public/chunk-3R3PVZG7.js +1 -0
- package/public/{chunk-BKUGARB4.js → chunk-44K5XVZH.js} +1 -1
- package/public/chunk-4UVD743J.js +1 -0
- package/public/chunk-5HMI3475.js +1 -0
- package/public/{chunk-NW6AFAD7.js → chunk-6OMIETCH.js} +1 -1
- package/public/chunk-6ZN4TBLM.js +7 -0
- package/public/chunk-7C3VZ3TZ.js +1 -0
- package/public/chunk-7IAYSGNN.js +1 -0
- package/public/{chunk-NWD4LL6Q.js → chunk-7X5P6T37.js} +1 -1
- package/public/chunk-ABI2LUSA.js +1 -0
- package/public/{chunk-QE7DO6J3.js → chunk-AFY7IWPI.js} +2 -2
- package/public/chunk-B75MYCJS.js +1 -0
- package/public/chunk-BC4ZZQWV.js +1 -0
- package/public/chunk-BS6X2RZL.js +1 -0
- package/public/chunk-BTB3JIDJ.js +1 -0
- package/public/chunk-CLRF6AUJ.js +6 -0
- package/public/{chunk-WNWWUCCZ.js → chunk-CUKPSGYS.js} +1 -1
- package/public/chunk-CYW4JA4J.js +1 -0
- package/public/{chunk-WHJSVGC7.js → chunk-D33FRRVF.js} +1 -1
- package/public/chunk-D6DBYUFZ.js +1 -0
- package/public/chunk-DBUCH6BG.js +1 -0
- package/public/chunk-DNQFYNG6.js +1 -0
- package/public/chunk-F5ICJKYI.js +8 -0
- package/public/chunk-FETTFNJ2.js +1 -0
- package/public/{chunk-6TCHCTXZ.js → chunk-G5LGUOIC.js} +1 -1
- package/public/chunk-GDFC3M3E.js +2 -0
- package/public/chunk-GLHOQ5NF.js +1 -0
- package/public/chunk-GSGK2SKG.js +1 -0
- package/public/chunk-H2GFXLCD.js +1 -0
- package/public/chunk-H2OOFTLR.js +1 -0
- package/public/chunk-HEMNUWDO.js +1 -0
- package/public/{chunk-3KDOQQBM.js → chunk-HGUYWCTI.js} +2 -2
- package/public/chunk-I275JECR.js +1 -0
- package/public/{chunk-JZZQRLNW.js → chunk-I6OD3CV4.js} +1 -1
- package/public/chunk-IGYTH5AX.js +14 -0
- package/public/chunk-IPT5RIJX.js +1 -0
- package/public/chunk-J4CB3RFZ.js +1 -0
- package/public/chunk-KFR3ZGJZ.js +1 -0
- package/public/chunk-KKIRFTQL.js +5 -0
- package/public/{chunk-7EUQWCP5.js → chunk-KPW2P5T4.js} +1 -1
- package/public/chunk-L3LMIZ4T.js +1 -0
- package/public/chunk-L4DBDSHB.js +1 -0
- package/public/chunk-LCRNBCRA.js +1 -0
- package/public/chunk-LZSQNNXJ.js +1 -0
- package/public/chunk-MMD3VZMJ.js +20 -0
- package/public/chunk-MOCPJJF3.js +1 -0
- package/public/chunk-NAFR5P6T.js +1 -0
- package/public/chunk-NRSBQVRN.js +1 -0
- package/public/chunk-O5XYQE2Q.js +23 -0
- package/public/chunk-OBOD4WBI.js +1 -0
- package/public/chunk-OI57SN2B.js +1 -0
- package/public/{chunk-4IKE4OKZ.js → chunk-OJE7KDWZ.js} +1 -1
- package/public/chunk-OXOBBTSH.js +1 -0
- package/public/chunk-PCYP2KRX.js +1 -0
- package/public/{chunk-EA5J2VEJ.js → chunk-QCVDY2FW.js} +1 -1
- package/public/chunk-QGLICWXR.js +1 -0
- package/public/chunk-QJ75M7UB.js +1 -0
- package/public/chunk-RFWUHIJ5.js +1 -0
- package/public/chunk-T2YC5S4T.js +1 -0
- package/public/chunk-TCXWRDYD.js +1 -0
- package/public/chunk-TEFE7EK6.js +1 -0
- package/public/chunk-TWDTF4UX.js +1 -0
- package/public/{chunk-QXT6R24L.js → chunk-TYEF6KNJ.js} +1 -1
- package/public/chunk-UCQRW7SR.js +1 -0
- package/public/chunk-VDSVEHQG.js +1 -0
- package/public/chunk-W2INV3O5.js +5 -0
- package/public/chunk-WACROBL3.js +1 -0
- package/public/chunk-WGP32ABK.js +1 -0
- package/public/chunk-XSS6G7LC.js +1 -0
- package/public/chunk-YCBC3C3V.js +1 -0
- package/public/chunk-YET3EKNI.js +1 -0
- package/public/chunk-YTVVSAM2.js +1 -0
- package/public/chunk-YU3C2YTO.js +32 -0
- package/public/chunk-YWMHIHWJ.js +1 -0
- package/public/chunk-Z7QXZUQS.js +1 -0
- package/public/chunk-ZB3BYZDQ.js +1 -0
- package/public/chunk-ZIXTTJ4W.js +1 -0
- package/public/chunk-ZZQJ3DGD.js +1 -0
- package/public/index.html +2 -2
- package/public/main-26CAD2XH.js +1 -0
- package/public/media/fa-brands-400-Q3XCMWHQ.woff2 +0 -0
- package/public/media/{fa-brands-400-KOKGDU7E.ttf → fa-brands-400-R2XQZCET.ttf} +0 -0
- package/public/media/fa-regular-400-QSNYFYRT.woff2 +0 -0
- package/public/media/{fa-regular-400-IPMAEX5Y.ttf → fa-regular-400-XUOPSR7E.ttf} +0 -0
- package/public/media/fa-solid-900-5ZUYHGA7.woff2 +0 -0
- package/public/media/{fa-solid-900-SRFFQLRM.ttf → fa-solid-900-PJNKLK6W.ttf} +0 -0
- package/public/polyfills-JFMQVUE2.js +2 -0
- package/public/styles-6IKEC5B4.css +1 -0
- package/scripts/upgrade-install-plugin.sh +1 -1
- package/public/chunk-2J6XFH3T.js +0 -1
- package/public/chunk-2KNNQ3N3.js +0 -1
- package/public/chunk-3FKHRKWG.js +0 -1
- package/public/chunk-3IX3CLER.js +0 -1
- package/public/chunk-3YHN3VHA.js +0 -1
- package/public/chunk-4AVEC3ZU.js +0 -1
- package/public/chunk-5BHGCTWL.js +0 -5
- package/public/chunk-62ADZGBJ.js +0 -6
- package/public/chunk-6GHV2TKM.js +0 -1
- package/public/chunk-6SC3OCKT.js +0 -8
- package/public/chunk-BCHM64F4.js +0 -1
- package/public/chunk-BPMSJ2VF.js +0 -1
- package/public/chunk-C2ERQ3FX.js +0 -1
- package/public/chunk-C6NH5RUO.js +0 -1
- package/public/chunk-CUPS2NE5.js +0 -1
- package/public/chunk-D6EUS4KM.js +0 -1
- package/public/chunk-DNZYDCPW.js +0 -1
- package/public/chunk-E3OHYYGW.js +0 -23
- package/public/chunk-EMKXES77.js +0 -14
- package/public/chunk-G7AVJCRN.js +0 -1
- package/public/chunk-HSJSWZHD.js +0 -1
- package/public/chunk-HYBTNEG3.js +0 -1
- package/public/chunk-J34SI644.js +0 -1
- package/public/chunk-JD7YSN6P.js +0 -1
- package/public/chunk-JL3HH376.js +0 -1
- package/public/chunk-JN46TW24.js +0 -1
- package/public/chunk-JPWCYJWM.js +0 -1
- package/public/chunk-JQVXXNK7.js +0 -1
- package/public/chunk-JW6PX64L.js +0 -1
- package/public/chunk-JXEJU7V3.js +0 -1
- package/public/chunk-K53Q52AX.js +0 -1
- package/public/chunk-KD3Z24TB.js +0 -1
- package/public/chunk-KPCZLNW7.js +0 -1
- package/public/chunk-KQJ7ONUG.js +0 -1
- package/public/chunk-KUOCPYMN.js +0 -1
- package/public/chunk-KXMGIDLQ.js +0 -1
- package/public/chunk-KZLHFU5K.js +0 -1
- package/public/chunk-LJHUPCL3.js +0 -32
- package/public/chunk-MTMEA6JC.js +0 -1
- package/public/chunk-N5BZ3IQD.js +0 -1
- package/public/chunk-N5UE2QRB.js +0 -1
- package/public/chunk-NGAJQJ5T.js +0 -1
- package/public/chunk-NNATGODS.js +0 -1
- package/public/chunk-NZNNTHFQ.js +0 -1
- package/public/chunk-ORPWYWCL.js +0 -5
- package/public/chunk-OSDZN4BY.js +0 -1
- package/public/chunk-PREJ7FYU.js +0 -1
- package/public/chunk-QHPDGSZ6.js +0 -1
- package/public/chunk-RBHJOIVB.js +0 -1
- package/public/chunk-RRHDXAZE.js +0 -1
- package/public/chunk-T7MCUROV.js +0 -1
- package/public/chunk-TCSXGQNF.js +0 -1
- package/public/chunk-TTENUNEO.js +0 -1
- package/public/chunk-TXOB7R5K.js +0 -7
- package/public/chunk-UEX6RTZJ.js +0 -1
- package/public/chunk-UG5DK2RQ.js +0 -2
- package/public/chunk-UG6ZOHXY.js +0 -1
- package/public/chunk-UN5422JY.js +0 -1
- package/public/chunk-VAJZ7KCO.js +0 -1
- package/public/chunk-VBCYNIMT.js +0 -1
- package/public/chunk-WHJOLAED.js +0 -1
- package/public/chunk-WJFAG3CM.js +0 -20
- package/public/chunk-YN5SJ37A.js +0 -1
- package/public/chunk-YR3ETJZY.js +0 -1
- package/public/chunk-YRD5IXFM.js +0 -1
- package/public/chunk-Z4A7KLCA.js +0 -1
- package/public/chunk-ZT23DWNL.js +0 -1
- package/public/main-LYJIIXIC.js +0 -1
- package/public/media/01-RQ3S2L53.png +0 -0
- package/public/media/02-VNCG2I2A.png +0 -0
- package/public/media/03-HI42L4ZG.png +0 -0
- package/public/media/04-FJLL55LZ.png +0 -0
- package/public/media/05-V3EO6SPT.png +0 -0
- package/public/media/06-EOJZCQZN.png +0 -0
- package/public/media/07-KMKB5PBD.png +0 -0
- package/public/media/08-UQJRF6B2.png +0 -0
- package/public/media/09-2DJQFRHH.png +0 -0
- package/public/media/arrow_left-CQT7FZM7.svg +0 -4
- package/public/media/arrow_right-SBUDRR2G.svg +0 -4
- package/public/media/fa-brands-400-6PJPV6JM.woff2 +0 -0
- package/public/media/fa-regular-400-OHB6J4OK.woff2 +0 -0
- package/public/media/fa-solid-900-ABTK6BNK.woff2 +0 -0
- package/public/polyfills-C6JHVXJJ.js +0 -2
- package/public/scripts-6GVLYD7F.js +0 -62
- package/public/styles-EG5MFQEM.css +0 -1
- /package/public/assets/{bootstrap-4 → bootstrap-5}/cssframework/assets.json +0 -0
|
@@ -40,11 +40,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
40
40
|
this.npm = this.getNpmPath();
|
|
41
41
|
this.paths = this.getBasePaths();
|
|
42
42
|
this.pluginListUrl = 'https://raw.githubusercontent.com/homebridge/plugins/latest/';
|
|
43
|
-
this.pluginListFile = `${this.pluginListUrl}assets/plugins.min.json`;
|
|
43
|
+
this.pluginListFile = `${this.pluginListUrl}assets/plugins-v2.min.json`;
|
|
44
44
|
this.hiddenPlugins = [];
|
|
45
45
|
this.maintainedPlugins = [];
|
|
46
46
|
this.pluginIcons = {};
|
|
47
|
-
this.
|
|
47
|
+
this.pluginAuthors = {};
|
|
48
|
+
this.pluginNames = {};
|
|
48
49
|
this.newScopePlugins = {};
|
|
49
50
|
this.verifiedPlugins = [];
|
|
50
51
|
this.verifiedPlusPlugins = [];
|
|
@@ -67,6 +68,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
67
68
|
this.loadPluginList();
|
|
68
69
|
setInterval(this.loadPluginList.bind(this), 60000 * 60 * 12);
|
|
69
70
|
}
|
|
71
|
+
fixDisplayName(plugin) {
|
|
72
|
+
plugin.displayName = plugin.displayName || (plugin.name.charAt(0) === '@' ? plugin.name.split('/')[1] : plugin.name)
|
|
73
|
+
.replace(/-/g, ' ')
|
|
74
|
+
.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase());
|
|
75
|
+
return plugin;
|
|
76
|
+
}
|
|
70
77
|
async getInstalledPlugins() {
|
|
71
78
|
const plugins = [];
|
|
72
79
|
const modules = await this.getInstalledModules();
|
|
@@ -92,12 +99,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
92
99
|
}
|
|
93
100
|
}
|
|
94
101
|
catch (e) {
|
|
95
|
-
this.logger.error(`Failed to parse plugin
|
|
102
|
+
this.logger.error(`Failed to parse plugin ${pkg.name} as ${e.message}.`);
|
|
96
103
|
}
|
|
97
104
|
});
|
|
98
105
|
}));
|
|
99
|
-
this.installedPlugins = plugins;
|
|
100
|
-
return
|
|
106
|
+
this.installedPlugins = plugins.map(plugin => this.fixDisplayName(plugin));
|
|
107
|
+
return this.installedPlugins;
|
|
101
108
|
}
|
|
102
109
|
async getOutOfDatePlugins() {
|
|
103
110
|
const plugins = await this.getInstalledPlugins();
|
|
@@ -146,14 +153,21 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
146
153
|
if (!this.installedPlugins) {
|
|
147
154
|
await this.getInstalledPlugins();
|
|
148
155
|
}
|
|
149
|
-
|
|
156
|
+
query = query.trim().toLowerCase();
|
|
157
|
+
if ((query.startsWith('homebridge-') || this.isScopedPlugin(query)) && !this.hiddenPlugins.includes(query)) {
|
|
158
|
+
if (!this.installedPlugins.find(x => x.name === query) && Object.keys(this.newScopePlugins).includes(query)) {
|
|
159
|
+
query = `@homebridge-plugins/${query}`;
|
|
160
|
+
}
|
|
161
|
+
return await this.searchNpmRegistrySingle(query);
|
|
162
|
+
}
|
|
163
|
+
const q = `${(!query || !query.length) ? '' : `${query.substring(0, 15)}+`}keywords:homebridge-plugin+not:deprecated&size=99`;
|
|
150
164
|
let searchResults;
|
|
151
165
|
try {
|
|
152
166
|
searchResults = (await (0, rxjs_1.firstValueFrom)(this.httpService.get(`https://registry.npmjs.org/-/v1/search?text=${q}`))).data;
|
|
153
167
|
}
|
|
154
168
|
catch (e) {
|
|
155
|
-
this.logger.error(`Failed to search the npm registry
|
|
156
|
-
throw new common_1.InternalServerErrorException(`Failed to search the npm registry
|
|
169
|
+
this.logger.error(`Failed to search the npm registry (see https://homebridge.io/w/JJSz6 for help) as ${e.message}.`);
|
|
170
|
+
throw new common_1.InternalServerErrorException(`Failed to search the npm registry as ${e.message}, see logs.`);
|
|
157
171
|
}
|
|
158
172
|
const result = searchResults.objects
|
|
159
173
|
.filter(x => x.package.name.indexOf('homebridge-') === 0 || this.isScopedPlugin(x.package.name))
|
|
@@ -161,12 +175,14 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
161
175
|
.map((pkg) => {
|
|
162
176
|
let plugin = {
|
|
163
177
|
name: pkg.package.name,
|
|
178
|
+
displayName: this.pluginNames[pkg.package.name],
|
|
164
179
|
private: false,
|
|
165
180
|
};
|
|
166
181
|
const isInstalled = this.installedPlugins.find(x => x.name === plugin.name);
|
|
167
182
|
if (isInstalled) {
|
|
168
183
|
plugin = isInstalled;
|
|
169
184
|
plugin.lastUpdated = pkg.package.date;
|
|
185
|
+
plugin.keywords = pkg.package.keywords;
|
|
170
186
|
return plugin;
|
|
171
187
|
}
|
|
172
188
|
plugin.publicPackage = true;
|
|
@@ -176,24 +192,45 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
176
192
|
plugin.description = (pkg.package.description)
|
|
177
193
|
? pkg.package.description.replace(/\(?(?:https?|ftp):\/\/[\n\S]+/g, '').trim()
|
|
178
194
|
: pkg.package.name;
|
|
195
|
+
plugin.keywords = pkg.package.keywords;
|
|
179
196
|
plugin.links = pkg.package.links;
|
|
180
|
-
plugin.author = this.
|
|
197
|
+
plugin.author = this.pluginAuthors[pkg.package.name] || ((pkg.package.publisher) ? pkg.package.publisher.username : null);
|
|
181
198
|
plugin.verifiedPlugin = this.verifiedPlugins.includes(pkg.package.name);
|
|
182
199
|
plugin.verifiedPlusPlugin = this.verifiedPlusPlugins.includes(pkg.package.name);
|
|
183
200
|
plugin.icon = this.pluginIcons[pkg.package.name]
|
|
184
201
|
? `${this.pluginListUrl}${this.pluginIcons[pkg.package.name]}`
|
|
185
202
|
: null;
|
|
186
|
-
plugin.isHbScoped =
|
|
203
|
+
plugin.isHbScoped = pkg.package.name.startsWith('@homebridge-plugins/');
|
|
187
204
|
plugin.newHbScope = this.newScopePlugins[pkg.package.name];
|
|
188
205
|
plugin.isHbMaintained = this.maintainedPlugins.includes(pkg.package.name);
|
|
189
206
|
return plugin;
|
|
190
207
|
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
208
|
+
const searchTerm = query
|
|
209
|
+
.replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, '');
|
|
210
|
+
const searchTerms = searchTerm
|
|
211
|
+
.split(/\s+/)
|
|
212
|
+
.filter(term => term.length > 0);
|
|
213
|
+
const exactMatchPlugins = [];
|
|
214
|
+
const partialMatchPlugins = [];
|
|
215
|
+
result.forEach((plugin) => {
|
|
216
|
+
const pluginKeywords = plugin.keywords.map(keyword => keyword.toLowerCase());
|
|
217
|
+
const isExactMatch = pluginKeywords.includes(searchTerm);
|
|
218
|
+
if (isExactMatch) {
|
|
219
|
+
exactMatchPlugins.push(plugin);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const pluginName = plugin.name.toLowerCase();
|
|
223
|
+
const pluginDescription = plugin.description.toLowerCase();
|
|
224
|
+
const isPartialMatch = searchTerms.some(term => pluginName.includes(term))
|
|
225
|
+
|| searchTerms.some(term => pluginKeywords.some(keyword => keyword.includes(term)))
|
|
226
|
+
|| searchTerms.some(term => pluginDescription.includes(term));
|
|
227
|
+
if (isPartialMatch) {
|
|
228
|
+
partialMatchPlugins.push(plugin);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
return (0, lodash_1.orderBy)([...exactMatchPlugins, ...partialMatchPlugins], ['verifiedPlusPlugin', 'verifiedPlugin'], ['desc', 'desc'])
|
|
232
|
+
.slice(0, 30)
|
|
233
|
+
.map(plugin => this.fixDisplayName(plugin));
|
|
197
234
|
}
|
|
198
235
|
async searchNpmRegistrySingle(query) {
|
|
199
236
|
try {
|
|
@@ -224,10 +261,11 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
224
261
|
verifiedPlugin: this.verifiedPlugins.includes(pkg.name),
|
|
225
262
|
verifiedPlusPlugin: this.verifiedPlusPlugins.includes(pkg.name),
|
|
226
263
|
icon: this.pluginIcons[pkg.name],
|
|
227
|
-
isHbScoped:
|
|
264
|
+
isHbScoped: pkg.name.startsWith('@homebridge-plugins/'),
|
|
228
265
|
newHbScope: this.newScopePlugins[pkg.name],
|
|
229
266
|
isHbMaintained: this.maintainedPlugins.includes(pkg.name),
|
|
230
267
|
};
|
|
268
|
+
plugin.displayName = this.pluginNames[pkg.name];
|
|
231
269
|
plugin.publicPackage = true;
|
|
232
270
|
plugin.latestVersion = pkg['dist-tags'] ? pkg['dist-tags'].latest : undefined;
|
|
233
271
|
plugin.lastUpdated = pkg.time.modified;
|
|
@@ -238,38 +276,38 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
238
276
|
homepage: pkg.homepage,
|
|
239
277
|
bugs: typeof pkg.bugs === 'object' && pkg.bugs?.url ? pkg.bugs.url : null,
|
|
240
278
|
};
|
|
241
|
-
plugin.author = this.
|
|
279
|
+
plugin.author = this.pluginAuthors[pkg.name]
|
|
242
280
|
|| ((pkg.maintainers && pkg.maintainers.length) ? pkg.maintainers[0].name : null);
|
|
243
281
|
plugin.verifiedPlugin = this.verifiedPlugins.includes(pkg.name);
|
|
244
282
|
plugin.verifiedPlusPlugin = this.verifiedPlusPlugins.includes(pkg.name);
|
|
245
283
|
plugin.icon = this.pluginIcons[pkg.name]
|
|
246
284
|
? `${this.pluginListUrl}${this.pluginIcons[pkg.name]}`
|
|
247
285
|
: null;
|
|
248
|
-
plugin.isHbScoped =
|
|
286
|
+
plugin.isHbScoped = pkg.name.startsWith('@homebridge-plugins/');
|
|
249
287
|
plugin.newHbScope = this.newScopePlugins[pkg.name];
|
|
250
288
|
plugin.isHbMaintained = this.maintainedPlugins.includes(pkg.name);
|
|
251
|
-
return [plugin];
|
|
289
|
+
return [this.fixDisplayName(plugin)];
|
|
252
290
|
}
|
|
253
291
|
catch (e) {
|
|
254
292
|
if (e.response?.status !== 404) {
|
|
255
|
-
this.logger.error(`Failed to search the npm registry
|
|
293
|
+
this.logger.error(`Failed to search the npm registry (see https://homebridge.io/w/JJSz6 for help) as ${e.message}.`);
|
|
256
294
|
}
|
|
257
295
|
return [];
|
|
258
296
|
}
|
|
259
297
|
}
|
|
260
|
-
async
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
throw new Error(`Cannot uninstall ${pluginAction.name} from ${this.configService.name}.`);
|
|
298
|
+
async manageUi(action, pluginAction, client) {
|
|
299
|
+
if (action === 'uninstall') {
|
|
300
|
+
throw new Error('Cannot uninstall the Homebridge UI.');
|
|
264
301
|
}
|
|
265
|
-
if (
|
|
302
|
+
if (this.configService.dockerOfflineUpdate && pluginAction.version === 'latest') {
|
|
266
303
|
await this.updateSelfOffline(client);
|
|
267
304
|
return true;
|
|
268
305
|
}
|
|
269
306
|
if (action === 'install' && pluginAction.version === 'latest') {
|
|
270
307
|
pluginAction.version = await this.getNpmModuleLatestVersion(pluginAction.name);
|
|
271
308
|
}
|
|
272
|
-
|
|
309
|
+
const userPlatform = (0, node_os_1.platform)();
|
|
310
|
+
let installPath = this.configService.customPluginPath
|
|
273
311
|
? this.configService.customPluginPath
|
|
274
312
|
: this.installedPlugins.find(x => x.name === this.configService.name).installPath;
|
|
275
313
|
await this.getInstalledPlugins();
|
|
@@ -277,24 +315,53 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
277
315
|
if (existingPlugin) {
|
|
278
316
|
installPath = existingPlugin.installPath;
|
|
279
317
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
return true;
|
|
286
|
-
}
|
|
287
|
-
catch (e) {
|
|
288
|
-
client.emit('stdout', (0, bash_color_1.yellow)('\r\nBundled update failed. Trying regular update using npm.\r\n\r\n'));
|
|
289
|
-
}
|
|
318
|
+
const githubReleaseName = await this.isUiUpdateBundleAvailable(pluginAction);
|
|
319
|
+
if (githubReleaseName) {
|
|
320
|
+
try {
|
|
321
|
+
await this.doUiBundleUpdate(pluginAction, client, githubReleaseName);
|
|
322
|
+
return true;
|
|
290
323
|
}
|
|
291
|
-
|
|
292
|
-
client.emit('stdout', (0, bash_color_1.yellow)('
|
|
293
|
-
client.emit('stdout', (0, bash_color_1.yellow)(`Please be patient while ${this.configService.name} updates.\r\n`));
|
|
294
|
-
client.emit('stdout', (0, bash_color_1.yellow)('This process may take 5-15 minutes to complete on your device.\r\n'));
|
|
295
|
-
client.emit('stdout', (0, bash_color_1.yellow)('***************************************************************\r\n\r\n'));
|
|
324
|
+
catch (e) {
|
|
325
|
+
client.emit('stdout', (0, bash_color_1.yellow)('\r\nBundled update failed. Trying regular update using npm.\r\n\r\n'));
|
|
296
326
|
}
|
|
297
327
|
}
|
|
328
|
+
if ((0, node_os_1.cpus)().length === 1 && (0, node_os_1.arch)() === 'arm') {
|
|
329
|
+
client.emit('stdout', (0, bash_color_1.yellow)('***************************************************************\r\n'));
|
|
330
|
+
client.emit('stdout', (0, bash_color_1.yellow)(`Please be patient while ${this.configService.name} updates.\r\n`));
|
|
331
|
+
client.emit('stdout', (0, bash_color_1.yellow)('This process may take 5-15 minutes to complete on your device.\r\n'));
|
|
332
|
+
client.emit('stdout', (0, bash_color_1.yellow)('***************************************************************\r\n\r\n'));
|
|
333
|
+
}
|
|
334
|
+
const installOptions = [];
|
|
335
|
+
if (installPath === this.configService.customPluginPath && await (0, fs_extra_1.pathExists)((0, node_path_1.resolve)(installPath, '../package.json'))) {
|
|
336
|
+
installOptions.push('--save');
|
|
337
|
+
}
|
|
338
|
+
installPath = (0, node_path_1.resolve)(installPath, '../');
|
|
339
|
+
if (!this.configService.customPluginPath || userPlatform === 'win32' || existingPlugin?.globalInstall === true) {
|
|
340
|
+
installOptions.push('-g');
|
|
341
|
+
}
|
|
342
|
+
installOptions.push('--omit=dev');
|
|
343
|
+
const npmPluginLabel = `${pluginAction.name}@${pluginAction.version}`;
|
|
344
|
+
await this.cleanNpmCache();
|
|
345
|
+
await this.runNpmCommand([...this.npm, action, ...installOptions, npmPluginLabel], installPath, client, pluginAction.termCols, pluginAction.termRows);
|
|
346
|
+
await this.ensureCustomPluginDirExists();
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
async managePlugin(action, pluginAction, client) {
|
|
350
|
+
pluginAction.version = pluginAction.version || 'latest';
|
|
351
|
+
if (pluginAction.name === this.configService.name) {
|
|
352
|
+
return await this.manageUi(action, pluginAction, client);
|
|
353
|
+
}
|
|
354
|
+
if (action === 'install' && pluginAction.version === 'latest') {
|
|
355
|
+
pluginAction.version = await this.getNpmModuleLatestVersion(pluginAction.name);
|
|
356
|
+
}
|
|
357
|
+
let installPath = this.configService.customPluginPath
|
|
358
|
+
? this.configService.customPluginPath
|
|
359
|
+
: this.installedPlugins.find(x => x.name === this.configService.name).installPath;
|
|
360
|
+
await this.getInstalledPlugins();
|
|
361
|
+
const existingPlugin = this.installedPlugins.find(x => x.name === pluginAction.name);
|
|
362
|
+
if (existingPlugin) {
|
|
363
|
+
installPath = existingPlugin.installPath;
|
|
364
|
+
}
|
|
298
365
|
if (action === 'install' && await this.isPluginBundleAvailable(pluginAction)) {
|
|
299
366
|
try {
|
|
300
367
|
await this.doPluginBundleUpdate(pluginAction, client);
|
|
@@ -305,6 +372,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
305
372
|
}
|
|
306
373
|
}
|
|
307
374
|
const installOptions = [];
|
|
375
|
+
let npmPluginLabel = pluginAction.name;
|
|
308
376
|
if (installPath === this.configService.customPluginPath && await (0, fs_extra_1.pathExists)((0, node_path_1.resolve)(installPath, '../package.json'))) {
|
|
309
377
|
installOptions.push('--save');
|
|
310
378
|
}
|
|
@@ -312,20 +380,14 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
312
380
|
if (!this.configService.customPluginPath || (0, node_os_1.platform)() === 'win32' || existingPlugin?.globalInstall === true) {
|
|
313
381
|
installOptions.push('-g');
|
|
314
382
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
await this.ensureCustomPluginDirExists();
|
|
319
|
-
return true;
|
|
320
|
-
}
|
|
321
|
-
catch (e) {
|
|
322
|
-
if (pluginAction.name === this.configService.name) {
|
|
323
|
-
client.emit('stdout', (0, bash_color_1.yellow)('\r\nCleaning up npm cache, please wait...\r\n'));
|
|
324
|
-
await this.cleanNpmCache();
|
|
325
|
-
client.emit('stdout', (0, bash_color_1.yellow)(`npm cache cleared, please try updating ${this.configService.name} again.\r\n`));
|
|
326
|
-
}
|
|
327
|
-
throw e;
|
|
383
|
+
if (action === 'install') {
|
|
384
|
+
installOptions.push('--omit=dev');
|
|
385
|
+
npmPluginLabel = `${pluginAction.name}@${pluginAction.version}`;
|
|
328
386
|
}
|
|
387
|
+
await this.cleanNpmCache();
|
|
388
|
+
await this.runNpmCommand([...this.npm, action, ...installOptions, npmPluginLabel], installPath, client, pluginAction.termCols, pluginAction.termRows);
|
|
389
|
+
await this.ensureCustomPluginDirExists();
|
|
390
|
+
return true;
|
|
329
391
|
}
|
|
330
392
|
async getHomebridgePackage() {
|
|
331
393
|
if (this.configService.ui.homebridgePackagePath) {
|
|
@@ -334,21 +396,21 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
334
396
|
return await this.parsePackageJson(await (0, fs_extra_1.readJson)(pkgJsonPath), this.configService.ui.homebridgePackagePath);
|
|
335
397
|
}
|
|
336
398
|
else {
|
|
337
|
-
this.logger.error(`
|
|
399
|
+
this.logger.error(`The Homebridge path ${this.configService.ui.homebridgePackagePath} does not exist.`);
|
|
338
400
|
}
|
|
339
401
|
}
|
|
340
402
|
const modules = await this.getInstalledModules();
|
|
341
403
|
const homebridgeInstalls = modules.filter(x => x.name === 'homebridge');
|
|
342
404
|
if (homebridgeInstalls.length > 1) {
|
|
343
|
-
this.logger.warn('Multiple
|
|
405
|
+
this.logger.warn('Multiple instances of Homebridge were found, see https://homebridge.io/w/JJSgm for help.');
|
|
344
406
|
homebridgeInstalls.forEach((instance) => {
|
|
345
407
|
this.logger.warn(instance.installPath);
|
|
346
408
|
});
|
|
347
409
|
}
|
|
348
410
|
if (!homebridgeInstalls.length) {
|
|
349
411
|
this.configService.hbServiceUiRestartRequired = true;
|
|
350
|
-
this.logger.error('Unable
|
|
351
|
-
throw new Error('Unable To Find Homebridge Installation');
|
|
412
|
+
this.logger.error('Unable to find Homebridge installation, see https://homebridge.io/w/JJSgZ for help.');
|
|
413
|
+
throw new Error('Unable To Find Homebridge Installation.');
|
|
352
414
|
}
|
|
353
415
|
const homebridgeModule = homebridgeInstalls[0];
|
|
354
416
|
const pkgJson = await (0, fs_extra_1.readJson)((0, node_path_1.join)(homebridgeModule.installPath, 'package.json'));
|
|
@@ -378,6 +440,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
378
440
|
}
|
|
379
441
|
let installPath = homebridge.installPath;
|
|
380
442
|
const installOptions = [];
|
|
443
|
+
installOptions.push('--omit=dev');
|
|
381
444
|
if (installPath === this.configService.customPluginPath && await (0, fs_extra_1.pathExists)((0, node_path_1.resolve)(installPath, '../package.json'))) {
|
|
382
445
|
installOptions.push('--save');
|
|
383
446
|
}
|
|
@@ -416,7 +479,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
416
479
|
&& pluginAction.name !== this.configService.name
|
|
417
480
|
&& pluginAction.version !== 'latest') {
|
|
418
481
|
try {
|
|
419
|
-
await (0, rxjs_1.firstValueFrom)(this.httpService.head(`https://github.com/homebridge/
|
|
482
|
+
await (0, rxjs_1.firstValueFrom)(this.httpService.head(`https://github.com/homebridge/plugins/releases/download/v1.0.0/${pluginAction.name.replace('/', '@')}-${pluginAction.version}.sha256`));
|
|
420
483
|
return true;
|
|
421
484
|
}
|
|
422
485
|
catch (e) {
|
|
@@ -440,7 +503,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
440
503
|
'/var/packages/homebridge/target/app/lib/node_modules',
|
|
441
504
|
].includes((0, node_path_1.dirname)(node_process_1.default.env.UIX_BASE_PATH))
|
|
442
505
|
&& pluginAction.name === this.configService.name
|
|
443
|
-
&&
|
|
506
|
+
&& !['latest', 'alpha', 'beta'].includes(pluginAction.version)) {
|
|
444
507
|
try {
|
|
445
508
|
try {
|
|
446
509
|
const withV = `v${pluginAction.version}`;
|
|
@@ -454,7 +517,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
454
517
|
}
|
|
455
518
|
}
|
|
456
519
|
catch (e) {
|
|
457
|
-
this.logger.error(`Failed to check for bundled update: ${e.message}
|
|
520
|
+
this.logger.error(`Failed to check for bundled update: ${e.message}.`);
|
|
458
521
|
return '';
|
|
459
522
|
}
|
|
460
523
|
}
|
|
@@ -491,30 +554,28 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
491
554
|
throw new common_1.NotFoundException();
|
|
492
555
|
}
|
|
493
556
|
const schemaPath = (0, node_path_1.resolve)(plugin.installPath, pluginName, 'config.schema.json');
|
|
557
|
+
if (!schemaPath.startsWith(plugin.installPath)) {
|
|
558
|
+
throw new common_1.BadRequestException('Invalid plugin path');
|
|
559
|
+
}
|
|
494
560
|
let configSchema = await (0, fs_extra_1.readJson)(schemaPath);
|
|
495
561
|
if (configSchema.dynamicSchemaVersion) {
|
|
496
562
|
const dynamicSchemaPath = (0, node_path_1.resolve)(this.configService.storagePath, `.${pluginName}-v${configSchema.dynamicSchemaVersion}.schema.json`);
|
|
497
|
-
this.
|
|
563
|
+
if (!dynamicSchemaPath.startsWith(this.configService.storagePath)) {
|
|
564
|
+
throw new common_1.BadRequestException('Invalid dynamic schema path');
|
|
565
|
+
}
|
|
566
|
+
this.logger.log(`[${pluginName}] dynamic schema path: ${dynamicSchemaPath}.`);
|
|
498
567
|
if ((0, fs_extra_1.existsSync)(dynamicSchemaPath)) {
|
|
499
568
|
try {
|
|
500
569
|
configSchema = await (0, fs_extra_1.readJson)(dynamicSchemaPath);
|
|
501
|
-
this.logger.log(`[${pluginName}] dynamic schema loaded from
|
|
570
|
+
this.logger.log(`[${pluginName}] dynamic schema loaded from ${dynamicSchemaPath}.`);
|
|
502
571
|
}
|
|
503
572
|
catch (e) {
|
|
504
|
-
this.logger.error(`[${pluginName}]
|
|
573
|
+
this.logger.error(`[${pluginName}] failed to load dynamic schema from ${dynamicSchemaPath} as ${e.message}.`);
|
|
505
574
|
}
|
|
506
575
|
}
|
|
507
576
|
}
|
|
508
577
|
if (pluginName === this.configService.name) {
|
|
509
578
|
configSchema.schema.properties.port.default = this.configService.ui.port;
|
|
510
|
-
if (this.configService.serviceMode) {
|
|
511
|
-
configSchema.layout = configSchema.layout.filter((x) => {
|
|
512
|
-
return x.ref !== 'log';
|
|
513
|
-
});
|
|
514
|
-
configSchema.layout = configSchema.layout.filter((x) => {
|
|
515
|
-
return !(x === 'sudo' || x.key === 'restart');
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
579
|
}
|
|
519
580
|
if (pluginName === 'homebridge-alexa') {
|
|
520
581
|
configSchema.schema.properties.pin.default = this.configService.homebridgeConfig.bridge.pin;
|
|
@@ -626,7 +687,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
626
687
|
?.name;
|
|
627
688
|
}
|
|
628
689
|
catch (e) {
|
|
629
|
-
this.logger.error(`Failed to get list of branches from GitHub
|
|
690
|
+
this.logger.error(`Failed to get list of branches from GitHub as ${e.message}.`);
|
|
630
691
|
}
|
|
631
692
|
}
|
|
632
693
|
return {
|
|
@@ -696,7 +757,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
696
757
|
});
|
|
697
758
|
}
|
|
698
759
|
catch (e) {
|
|
699
|
-
this.logger.debug(
|
|
760
|
+
this.logger.debug(`Failed to extract ${pluginName} plugin alias as ${e.message}.`);
|
|
700
761
|
if (this.pluginAliasHints[pluginName]) {
|
|
701
762
|
output.pluginAlias = this.pluginAliasHints[pluginName].pluginAlias;
|
|
702
763
|
output.pluginType = this.pluginAliasHints[pluginName].pluginType;
|
|
@@ -788,7 +849,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
788
849
|
}
|
|
789
850
|
}
|
|
790
851
|
catch (e) {
|
|
791
|
-
this.logger.log(`Failed to parse
|
|
852
|
+
this.logger.log(`Failed to parse ${module} in ${requiredPath} as ${e.message}.`);
|
|
792
853
|
}
|
|
793
854
|
}
|
|
794
855
|
}
|
|
@@ -824,8 +885,8 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
824
885
|
return [windowsNpmPath[0]];
|
|
825
886
|
}
|
|
826
887
|
else {
|
|
827
|
-
this.logger.error('
|
|
828
|
-
this.logger.error('
|
|
888
|
+
this.logger.error('Cannot find npm binary, you will not be able to manage plugins or update Homebridge. You might be able to fix this problem by running:');
|
|
889
|
+
this.logger.error('npm install -g npm');
|
|
829
890
|
}
|
|
830
891
|
}
|
|
831
892
|
return ['npm'];
|
|
@@ -876,8 +937,8 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
876
937
|
async parsePackageJson(pkgJson, installPath) {
|
|
877
938
|
const plugin = {
|
|
878
939
|
name: pkgJson.name,
|
|
940
|
+
displayName: pkgJson.displayName || this.pluginNames[pkgJson.name],
|
|
879
941
|
private: pkgJson.private || false,
|
|
880
|
-
displayName: pkgJson.displayName,
|
|
881
942
|
description: (pkgJson.description)
|
|
882
943
|
? pkgJson.description.replace(/(?:https?|ftp):\/\/[\n\S]+/g, '').trim()
|
|
883
944
|
: pkgJson.name,
|
|
@@ -886,7 +947,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
886
947
|
icon: this.pluginIcons[pkgJson.name]
|
|
887
948
|
? `${this.pluginListUrl}${this.pluginIcons[pkgJson.name]}`
|
|
888
949
|
: null,
|
|
889
|
-
isHbScoped:
|
|
950
|
+
isHbScoped: pkgJson.name.startsWith('@homebridge-plugins/'),
|
|
890
951
|
newHbScope: this.newScopePlugins[pkgJson.name],
|
|
891
952
|
isHbMaintained: this.maintainedPlugins.includes(pkgJson.name),
|
|
892
953
|
installedVersion: installPath ? (pkgJson.version || '0.0.1') : null,
|
|
@@ -938,12 +999,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
938
999
|
homepage: pkg.homepage,
|
|
939
1000
|
bugs: typeof pkg.bugs === 'object' && pkg.bugs?.url ? pkg.bugs.url : null,
|
|
940
1001
|
};
|
|
941
|
-
plugin.author = this.
|
|
1002
|
+
plugin.author = this.pluginAuthors[pkg.name]
|
|
942
1003
|
|| ((pkg.maintainers && pkg.maintainers.length) ? pkg.maintainers[0].name : null);
|
|
943
1004
|
}
|
|
944
1005
|
catch (e) {
|
|
945
1006
|
if (e.response?.status !== 404) {
|
|
946
|
-
this.logger.log(`[${plugin.name}]
|
|
1007
|
+
this.logger.log(`[${plugin.name}] failed to check registry.npmjs.org for updates (see https://homebridge.io/w/JJSz6 for help) as ${e.message}.`);
|
|
947
1008
|
}
|
|
948
1009
|
plugin.publicPackage = false;
|
|
949
1010
|
plugin.latestVersion = null;
|
|
@@ -970,18 +1031,25 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
970
1031
|
command.unshift('sudo', '-E', '-n');
|
|
971
1032
|
}
|
|
972
1033
|
else {
|
|
1034
|
+
let npmInstallPath;
|
|
973
1035
|
try {
|
|
974
|
-
|
|
1036
|
+
npmInstallPath = (0, node_child_process_1.execSync)('npm root -g').toString().trim();
|
|
1037
|
+
}
|
|
1038
|
+
catch (e) {
|
|
1039
|
+
npmInstallPath = (0, node_path_1.resolve)(cwd, 'node_modules');
|
|
1040
|
+
}
|
|
1041
|
+
try {
|
|
1042
|
+
await (0, fs_extra_1.access)(npmInstallPath, fs_extra_1.constants.W_OK);
|
|
975
1043
|
}
|
|
976
1044
|
catch (e) {
|
|
977
1045
|
client.emit('stdout', (0, bash_color_1.yellow)(`The user "${(0, node_os_1.userInfo)().username}" does not have write access to the target directory:\n\r\n\r`));
|
|
978
|
-
client.emit('stdout', `${
|
|
1046
|
+
client.emit('stdout', `${npmInstallPath}\n\r\n\r`);
|
|
979
1047
|
client.emit('stdout', (0, bash_color_1.yellow)('This may cause the operation to fail.\n\r'));
|
|
980
1048
|
client.emit('stdout', (0, bash_color_1.yellow)('See the docs for details on how to enable sudo mode:\n\r'));
|
|
981
1049
|
client.emit('stdout', (0, bash_color_1.yellow)('https://github.com/homebridge/homebridge-config-ui-x/wiki/Manual-Configuration#sudo-mode\n\r\n\r'));
|
|
982
1050
|
}
|
|
983
1051
|
}
|
|
984
|
-
this.logger.log(`Running
|
|
1052
|
+
this.logger.log(`Running command ${command.join(' ')}.`);
|
|
985
1053
|
if (!(0, semver_1.satisfies)(node_process_1.default.version, `>=${this.configService.minimumNodeVersion}`)) {
|
|
986
1054
|
client.emit('stdout', (0, bash_color_1.yellow)(`Node.js v${this.configService.minimumNodeVersion} higher is required for ${this.configService.name}.\n\r`));
|
|
987
1055
|
client.emit('stdout', (0, bash_color_1.yellow)(`You may experience issues while running on Node.js ${node_process_1.default.version}.\n\r\n\r`));
|
|
@@ -1042,13 +1110,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1042
1110
|
return;
|
|
1043
1111
|
}
|
|
1044
1112
|
if (!await (0, fs_extra_1.pathExists)(this.configService.customPluginPath)) {
|
|
1045
|
-
this.logger.warn(`Custom plugin directory was removed
|
|
1113
|
+
this.logger.warn(`Custom plugin directory was removed, re-creating ${this.configService.customPluginPath}.`);
|
|
1046
1114
|
try {
|
|
1047
1115
|
await (0, fs_extra_1.ensureDir)(this.configService.customPluginPath);
|
|
1048
1116
|
}
|
|
1049
1117
|
catch (e) {
|
|
1050
|
-
this.logger.error(
|
|
1051
|
-
this.logger.error(e.message);
|
|
1118
|
+
this.logger.error(`Failed to re-create custom plugin directory as ${e.message}.`);
|
|
1052
1119
|
}
|
|
1053
1120
|
}
|
|
1054
1121
|
}
|
|
@@ -1063,7 +1130,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1063
1130
|
}
|
|
1064
1131
|
}
|
|
1065
1132
|
catch (e) {
|
|
1066
|
-
this.logger.error(`Failed to remove ${offendingPath}
|
|
1133
|
+
this.logger.error(`Failed to remove ${offendingPath} as ${e.message}.`);
|
|
1067
1134
|
}
|
|
1068
1135
|
}
|
|
1069
1136
|
async cleanNpmCache() {
|
|
@@ -1072,9 +1139,9 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1072
1139
|
command.unshift('sudo', '-E', '-n');
|
|
1073
1140
|
}
|
|
1074
1141
|
return new Promise((res) => {
|
|
1075
|
-
const child = (0, node_child_process_1.spawn)(command.shift(), command);
|
|
1142
|
+
const child = (0, node_child_process_1.spawn)(command.shift(), command, { shell: true });
|
|
1076
1143
|
child.on('exit', (code) => {
|
|
1077
|
-
this.logger.log(
|
|
1144
|
+
this.logger.log(`Executed npm cache clear command with exit code ${code}.`);
|
|
1078
1145
|
res(null);
|
|
1079
1146
|
});
|
|
1080
1147
|
child.on('error', () => {
|
|
@@ -1093,36 +1160,40 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1093
1160
|
this.pluginIcons = {};
|
|
1094
1161
|
this.hiddenPlugins = [];
|
|
1095
1162
|
this.maintainedPlugins = [];
|
|
1096
|
-
this.
|
|
1163
|
+
this.pluginAuthors = {};
|
|
1164
|
+
this.pluginNames = {};
|
|
1097
1165
|
this.newScopePlugins = {};
|
|
1098
1166
|
Object.keys(pluginListData).forEach((key) => {
|
|
1099
1167
|
const plugin = pluginListData[key];
|
|
1100
|
-
if (plugin.
|
|
1101
|
-
this.pluginIcons[key] = `icons/${plugin.
|
|
1168
|
+
if (plugin.i) {
|
|
1169
|
+
this.pluginIcons[key] = `icons/${plugin.i}.png`;
|
|
1102
1170
|
}
|
|
1103
|
-
if (plugin.
|
|
1171
|
+
if (plugin.h) {
|
|
1104
1172
|
this.hiddenPlugins.push(key);
|
|
1105
1173
|
}
|
|
1106
|
-
if (plugin.
|
|
1174
|
+
if (plugin.m) {
|
|
1107
1175
|
this.maintainedPlugins.push(key);
|
|
1108
1176
|
}
|
|
1109
|
-
if (plugin.
|
|
1110
|
-
this.
|
|
1177
|
+
if (plugin.a) {
|
|
1178
|
+
this.pluginAuthors[key] = plugin.a;
|
|
1179
|
+
}
|
|
1180
|
+
if (plugin.n) {
|
|
1181
|
+
this.pluginNames[key] = plugin.n;
|
|
1111
1182
|
}
|
|
1112
|
-
if (plugin.
|
|
1113
|
-
this.newScopePlugins[key] = plugin.
|
|
1183
|
+
if (plugin.s) {
|
|
1184
|
+
this.newScopePlugins[key] = plugin.s;
|
|
1114
1185
|
}
|
|
1115
|
-
if (plugin.
|
|
1186
|
+
if (plugin.v) {
|
|
1116
1187
|
this.verifiedPlugins.push(key);
|
|
1117
1188
|
}
|
|
1118
|
-
if (plugin.
|
|
1189
|
+
if (plugin.p) {
|
|
1119
1190
|
this.verifiedPlusPlugins.push(key);
|
|
1120
1191
|
}
|
|
1121
1192
|
});
|
|
1122
1193
|
}
|
|
1123
1194
|
catch (e) {
|
|
1124
1195
|
this.pluginListRetryTimeout = setTimeout(() => this.loadPluginList(), 60000);
|
|
1125
|
-
this.logger.debug(
|
|
1196
|
+
this.logger.debug(`Could not obtain plugin list from plugins repo as ${e.message}.`);
|
|
1126
1197
|
}
|
|
1127
1198
|
}
|
|
1128
1199
|
};
|