homebridge-config-ui-x 5.9.1-beta.0 → 5.9.1-beta.10
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 +23 -2
- package/TODO-MATTER.md +15 -0
- package/dist/app.controller.d.ts +1 -1
- package/dist/app.controller.js +14 -12
- package/dist/app.controller.js.map +1 -1
- package/dist/app.gateway.js +7 -10
- package/dist/app.gateway.js.map +1 -1
- package/dist/app.module.js +42 -43
- package/dist/app.module.js.map +1 -1
- package/dist/app.service.js +4 -7
- package/dist/app.service.js.map +1 -1
- package/dist/bin/base-platform.d.ts +1 -1
- package/dist/bin/base-platform.js +11 -17
- package/dist/bin/base-platform.js.map +1 -1
- package/dist/bin/fork.js +7 -45
- package/dist/bin/fork.js.map +1 -1
- package/dist/bin/hb-service.js +224 -243
- package/dist/bin/hb-service.js.map +1 -1
- package/dist/bin/platforms/darwin.d.ts +1 -1
- package/dist/bin/platforms/darwin.js +61 -65
- package/dist/bin/platforms/darwin.js.map +1 -1
- package/dist/bin/platforms/freebsd.d.ts +1 -1
- package/dist/bin/platforms/freebsd.js +42 -47
- package/dist/bin/platforms/freebsd.js.map +1 -1
- package/dist/bin/platforms/linux.d.ts +1 -1
- package/dist/bin/platforms/linux.js +127 -132
- package/dist/bin/platforms/linux.js.map +1 -1
- package/dist/bin/platforms/win32.d.ts +1 -1
- package/dist/bin/platforms/win32.js +30 -36
- package/dist/bin/platforms/win32.js.map +1 -1
- package/dist/bin/standalone.js +15 -53
- package/dist/bin/standalone.js.map +1 -1
- package/dist/core/auth/auth.controller.d.ts +5 -4
- package/dist/core/auth/auth.controller.js +40 -39
- package/dist/core/auth/auth.controller.js.map +1 -1
- package/dist/core/auth/auth.dto.js +17 -18
- package/dist/core/auth/auth.dto.js.map +1 -1
- package/dist/core/auth/auth.module.js +28 -31
- package/dist/core/auth/auth.module.js.map +1 -1
- package/dist/core/auth/auth.service.d.ts +3 -3
- package/dist/core/auth/auth.service.js +65 -62
- package/dist/core/auth/auth.service.js.map +1 -1
- package/dist/core/auth/guards/admin.guard.js +4 -7
- package/dist/core/auth/guards/admin.guard.js.map +1 -1
- package/dist/core/auth/guards/custom.guard.js +6 -9
- package/dist/core/auth/guards/custom.guard.js.map +1 -1
- package/dist/core/auth/guards/ws-admin-guard.d.ts +2 -2
- package/dist/core/auth/guards/ws-admin-guard.js +13 -11
- package/dist/core/auth/guards/ws-admin-guard.js.map +1 -1
- package/dist/core/auth/guards/ws.guard.d.ts +2 -2
- package/dist/core/auth/guards/ws.guard.js +13 -11
- package/dist/core/auth/guards/ws.guard.js.map +1 -1
- package/dist/core/auth/jwt.strategy.d.ts +3 -2
- package/dist/core/auth/jwt.strategy.js +21 -16
- package/dist/core/auth/jwt.strategy.js.map +1 -1
- package/dist/core/config/config.interfaces.d.ts +8 -1
- package/dist/core/config/config.interfaces.js +1 -2
- package/dist/core/config/config.module.js +8 -10
- package/dist/core/config/config.module.js.map +1 -1
- package/dist/core/config/config.service.d.ts +4 -3
- package/dist/core/config/config.service.js +90 -83
- package/dist/core/config/config.service.js.map +1 -1
- package/dist/core/config/config.startup.d.ts +1 -1
- package/dist/core/config/config.startup.js +23 -28
- package/dist/core/config/config.startup.js.map +1 -1
- package/dist/core/feature-flags/feature-flags.registry.js +2 -5
- package/dist/core/feature-flags/feature-flags.registry.js.map +1 -1
- package/dist/core/homebridge-ipc/homebridge-ipc.module.js +11 -14
- package/dist/core/homebridge-ipc/homebridge-ipc.module.js.map +1 -1
- package/dist/core/homebridge-ipc/homebridge-ipc.service.d.ts +4 -4
- package/dist/core/homebridge-ipc/homebridge-ipc.service.js +25 -19
- package/dist/core/homebridge-ipc/homebridge-ipc.service.js.map +1 -1
- package/dist/core/logger/logger.module.js +8 -10
- package/dist/core/logger/logger.module.js.map +1 -1
- package/dist/core/logger/logger.service.js +13 -23
- package/dist/core/logger/logger.service.js.map +1 -1
- package/dist/core/node-pty/node-pty.module.js +7 -10
- package/dist/core/node-pty/node-pty.module.js.map +1 -1
- package/dist/core/node-pty/node-pty.service.js +6 -11
- package/dist/core/node-pty/node-pty.service.js.map +1 -1
- package/dist/core/node-version.constants.js +4 -11
- package/dist/core/node-version.constants.js.map +1 -1
- package/dist/core/scheduler/scheduler.module.js +15 -10
- package/dist/core/scheduler/scheduler.module.js.map +1 -1
- package/dist/core/scheduler/scheduler.service.d.ts +12 -1
- package/dist/core/scheduler/scheduler.service.js +101 -13
- package/dist/core/scheduler/scheduler.service.js.map +1 -1
- package/dist/core/spa/spa-html.service.js +9 -15
- package/dist/core/spa/spa-html.service.js.map +1 -1
- package/dist/core/spa/spa.filter.d.ts +1 -1
- package/dist/core/spa/spa.filter.js +11 -16
- package/dist/core/spa/spa.filter.js.map +1 -1
- package/dist/core/ssl/ssl-cert-generator.service.d.ts +1 -1
- package/dist/core/ssl/ssl-cert-generator.service.js +34 -36
- package/dist/core/ssl/ssl-cert-generator.service.js.map +1 -1
- package/dist/env-setup.d.ts +1 -0
- package/dist/env-setup.js +7 -0
- package/dist/env-setup.js.map +1 -0
- package/dist/globalDefaults.d.ts +1 -0
- package/dist/globalDefaults.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +16 -19
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +5 -3
- package/dist/main.js +44 -51
- package/dist/main.js.map +1 -1
- package/dist/modules/accessories/accessories.controller.d.ts +3 -3
- package/dist/modules/accessories/accessories.controller.js +28 -29
- package/dist/modules/accessories/accessories.controller.js.map +1 -1
- package/dist/modules/accessories/accessories.dto.js +11 -13
- package/dist/modules/accessories/accessories.dto.js.map +1 -1
- package/dist/modules/accessories/accessories.gateway.d.ts +2 -2
- package/dist/modules/accessories/accessories.gateway.js +18 -16
- package/dist/modules/accessories/accessories.gateway.js.map +1 -1
- package/dist/modules/accessories/accessories.interfaces.d.ts +94 -0
- package/dist/modules/accessories/accessories.interfaces.js +2 -0
- package/dist/modules/accessories/accessories.interfaces.js.map +1 -0
- package/dist/modules/accessories/accessories.module.js +19 -20
- package/dist/modules/accessories/accessories.module.js.map +1 -1
- package/dist/modules/accessories/accessories.service.d.ts +23 -5
- package/dist/modules/accessories/accessories.service.js +316 -51
- package/dist/modules/accessories/accessories.service.js.map +1 -1
- package/dist/modules/backup/backup.controller.d.ts +4 -4
- package/dist/modules/backup/backup.controller.js +68 -67
- package/dist/modules/backup/backup.controller.js.map +1 -1
- package/dist/modules/backup/backup.gateway.d.ts +4 -4
- package/dist/modules/backup/backup.gateway.js +25 -21
- package/dist/modules/backup/backup.gateway.js.map +1 -1
- package/dist/modules/backup/backup.module.js +22 -25
- package/dist/modules/backup/backup.module.js.map +1 -1
- package/dist/modules/backup/backup.service.d.ts +5 -5
- package/dist/modules/backup/backup.service.js +143 -133
- package/dist/modules/backup/backup.service.js.map +1 -1
- package/dist/modules/child-bridges/child-bridges.gateway.d.ts +3 -3
- package/dist/modules/child-bridges/child-bridges.gateway.js +23 -21
- package/dist/modules/child-bridges/child-bridges.gateway.js.map +1 -1
- package/dist/modules/child-bridges/child-bridges.interfaces.js +1 -2
- package/dist/modules/child-bridges/child-bridges.module.js +19 -22
- package/dist/modules/child-bridges/child-bridges.module.js.map +1 -1
- package/dist/modules/child-bridges/child-bridges.service.d.ts +3 -3
- package/dist/modules/child-bridges/child-bridges.service.js +15 -11
- package/dist/modules/child-bridges/child-bridges.service.js.map +1 -1
- package/dist/modules/config-editor/config-editor.controller.d.ts +13 -11
- package/dist/modules/config-editor/config-editor.controller.js +168 -103
- package/dist/modules/config-editor/config-editor.controller.js.map +1 -1
- package/dist/modules/config-editor/config-editor.dto.d.ts +6 -0
- package/dist/modules/config-editor/config-editor.dto.js +40 -0
- package/dist/modules/config-editor/config-editor.dto.js.map +1 -0
- package/dist/modules/config-editor/config-editor.module.js +21 -24
- package/dist/modules/config-editor/config-editor.module.js.map +1 -1
- package/dist/modules/config-editor/config-editor.service.d.ts +11 -8
- package/dist/modules/config-editor/config-editor.service.js +123 -66
- package/dist/modules/config-editor/config-editor.service.js.map +1 -1
- package/dist/modules/custom-plugins/custom-plugins.module.js +10 -13
- package/dist/modules/custom-plugins/custom-plugins.module.js.map +1 -1
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.controller.d.ts +2 -2
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.controller.js +21 -19
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.controller.js.map +1 -1
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.module.js +14 -17
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.module.js.map +1 -1
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.service.d.ts +2 -2
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.service.js +18 -15
- package/dist/modules/custom-plugins/homebridge-deconz/homebridge-deconz.service.js.map +1 -1
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.controller.d.ts +2 -2
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.controller.js +21 -19
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.controller.js.map +1 -1
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.module.js +14 -17
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.module.js.map +1 -1
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.service.d.ts +2 -2
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.service.js +18 -15
- package/dist/modules/custom-plugins/homebridge-hue/homebridge-hue.service.js.map +1 -1
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.controller.d.ts +2 -2
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.controller.js +18 -19
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.controller.js.map +1 -1
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.gateway.d.ts +2 -2
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.gateway.js +15 -13
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.gateway.js.map +1 -1
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.module.js +18 -21
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.module.js.map +1 -1
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.d.ts +8 -8
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.js +47 -41
- package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.js.map +1 -1
- package/dist/modules/log/log.gateway.d.ts +3 -3
- package/dist/modules/log/log.gateway.js +15 -13
- package/dist/modules/log/log.gateway.js.map +1 -1
- package/dist/modules/log/log.interfaces.js +1 -2
- package/dist/modules/log/log.module.js +14 -17
- package/dist/modules/log/log.module.js.map +1 -1
- package/dist/modules/log/log.service.d.ts +5 -5
- package/dist/modules/log/log.service.js +47 -43
- package/dist/modules/log/log.service.js.map +1 -1
- package/dist/modules/platform-tools/docker/docker.controller.d.ts +1 -1
- package/dist/modules/platform-tools/docker/docker.controller.js +24 -25
- package/dist/modules/platform-tools/docker/docker.controller.js.map +1 -1
- package/dist/modules/platform-tools/docker/docker.module.js +14 -17
- package/dist/modules/platform-tools/docker/docker.module.js.map +1 -1
- package/dist/modules/platform-tools/docker/docker.service.d.ts +2 -2
- package/dist/modules/platform-tools/docker/docker.service.js +20 -16
- package/dist/modules/platform-tools/docker/docker.service.js.map +1 -1
- package/dist/modules/platform-tools/hb-service/hb-service.controller.d.ts +2 -2
- package/dist/modules/platform-tools/hb-service/hb-service.controller.js +35 -36
- package/dist/modules/platform-tools/hb-service/hb-service.controller.js.map +1 -1
- package/dist/modules/platform-tools/hb-service/hb-service.dto.js +20 -19
- package/dist/modules/platform-tools/hb-service/hb-service.dto.js.map +1 -1
- package/dist/modules/platform-tools/hb-service/hb-service.module.js +14 -17
- package/dist/modules/platform-tools/hb-service/hb-service.module.js.map +1 -1
- package/dist/modules/platform-tools/hb-service/hb-service.service.d.ts +3 -3
- package/dist/modules/platform-tools/hb-service/hb-service.service.js +37 -30
- package/dist/modules/platform-tools/hb-service/hb-service.service.js.map +1 -1
- package/dist/modules/platform-tools/linux/linux.controller.d.ts +1 -1
- package/dist/modules/platform-tools/linux/linux.controller.js +23 -21
- package/dist/modules/platform-tools/linux/linux.controller.js.map +1 -1
- package/dist/modules/platform-tools/linux/linux.module.js +14 -17
- package/dist/modules/platform-tools/linux/linux.module.js.map +1 -1
- package/dist/modules/platform-tools/linux/linux.service.d.ts +2 -2
- package/dist/modules/platform-tools/linux/linux.service.js +18 -14
- package/dist/modules/platform-tools/linux/linux.service.js.map +1 -1
- package/dist/modules/platform-tools/platform-tools.module.js +12 -15
- package/dist/modules/platform-tools/platform-tools.module.js.map +1 -1
- package/dist/modules/platform-tools/terminal/terminal.controller.d.ts +1 -1
- package/dist/modules/platform-tools/terminal/terminal.controller.js +15 -13
- package/dist/modules/platform-tools/terminal/terminal.controller.js.map +1 -1
- package/dist/modules/platform-tools/terminal/terminal.gateway.d.ts +2 -2
- package/dist/modules/platform-tools/terminal/terminal.gateway.js +17 -15
- package/dist/modules/platform-tools/terminal/terminal.gateway.js.map +1 -1
- package/dist/modules/platform-tools/terminal/terminal.interfaces.js +1 -2
- package/dist/modules/platform-tools/terminal/terminal.module.js +18 -21
- package/dist/modules/platform-tools/terminal/terminal.module.js.map +1 -1
- package/dist/modules/platform-tools/terminal/terminal.service.d.ts +7 -7
- package/dist/modules/platform-tools/terminal/terminal.service.js +33 -28
- package/dist/modules/platform-tools/terminal/terminal.service.js.map +1 -1
- package/dist/modules/plugins/plugins.controller.d.ts +12 -7
- package/dist/modules/plugins/plugins.controller.js +100 -52
- package/dist/modules/plugins/plugins.controller.js.map +1 -1
- package/dist/modules/plugins/plugins.dto.js +26 -24
- package/dist/modules/plugins/plugins.dto.js.map +1 -1
- package/dist/modules/plugins/plugins.gateway.d.ts +5 -5
- package/dist/modules/plugins/plugins.gateway.js +38 -34
- package/dist/modules/plugins/plugins.gateway.js.map +1 -1
- package/dist/modules/plugins/plugins.interfaces.js +1 -2
- package/dist/modules/plugins/plugins.module.js +27 -26
- package/dist/modules/plugins/plugins.module.js.map +1 -1
- package/dist/modules/plugins/plugins.service.d.ts +26 -13
- package/dist/modules/plugins/plugins.service.js +366 -203
- package/dist/modules/plugins/plugins.service.js.map +1 -1
- package/dist/modules/server/server.controller.d.ts +37 -7
- package/dist/modules/server/server.controller.js +294 -177
- package/dist/modules/server/server.controller.js.map +1 -1
- package/dist/modules/server/server.dto.js +13 -16
- package/dist/modules/server/server.dto.js.map +1 -1
- package/dist/modules/server/server.module.js +23 -26
- package/dist/modules/server/server.module.js.map +1 -1
- package/dist/modules/server/server.service.d.ts +36 -6
- package/dist/modules/server/server.service.js +406 -150
- package/dist/modules/server/server.service.js.map +1 -1
- package/dist/modules/setup-wizard/setup-wizard.controller.d.ts +3 -3
- package/dist/modules/setup-wizard/setup-wizard.controller.js +19 -20
- package/dist/modules/setup-wizard/setup-wizard.controller.js.map +1 -1
- package/dist/modules/setup-wizard/setup-wizard.gateway.d.ts +4 -4
- package/dist/modules/setup-wizard/setup-wizard.gateway.js +25 -21
- package/dist/modules/setup-wizard/setup-wizard.gateway.js.map +1 -1
- package/dist/modules/setup-wizard/setup-wizard.guard.d.ts +2 -2
- package/dist/modules/setup-wizard/setup-wizard.guard.js +11 -9
- package/dist/modules/setup-wizard/setup-wizard.guard.js.map +1 -1
- package/dist/modules/setup-wizard/setup-wizard.module.js +12 -15
- package/dist/modules/setup-wizard/setup-wizard.module.js.map +1 -1
- package/dist/modules/status/status.controller.d.ts +5 -5
- package/dist/modules/status/status.controller.js +40 -36
- package/dist/modules/status/status.controller.js.map +1 -1
- package/dist/modules/status/status.gateway.d.ts +11 -11
- package/dist/modules/status/status.gateway.js +51 -47
- package/dist/modules/status/status.gateway.js.map +1 -1
- package/dist/modules/status/status.interfaces.js +2 -5
- package/dist/modules/status/status.interfaces.js.map +1 -1
- package/dist/modules/status/status.module.js +26 -29
- package/dist/modules/status/status.module.js.map +1 -1
- package/dist/modules/status/status.service.d.ts +13 -13
- package/dist/modules/status/status.service.js +100 -88
- package/dist/modules/status/status.service.js.map +1 -1
- package/dist/modules/users/users.controller.d.ts +3 -3
- package/dist/modules/users/users.controller.js +59 -60
- package/dist/modules/users/users.controller.js.map +1 -1
- package/dist/modules/users/users.dto.js +51 -45
- package/dist/modules/users/users.dto.js.map +1 -1
- package/dist/modules/users/users.module.js +14 -17
- package/dist/modules/users/users.module.js.map +1 -1
- package/dist/self-check.js +25 -25
- package/dist/self-check.js.map +1 -1
- package/docs/ssl-upload-pr.md +103 -0
- package/package.json +14 -12
- package/public/3rdpartylicenses.txt +26 -26
- package/public/{chunk-QJLKBB62.js → chunk-2UCXG3TD.js} +1 -1
- package/public/{chunk-W26VKO62.js → chunk-2VYE34OE.js} +1 -1
- package/public/{chunk-FGS4HIPD.js → chunk-4AG5CIDJ.js} +1 -1
- package/public/{chunk-ZF6W5Z5R.js → chunk-4H57TZAE.js} +1 -1
- package/public/{chunk-VFIOPF3O.js → chunk-5CCE4FIL.js} +1 -1
- package/public/{chunk-2UQL2OTF.js → chunk-5RBSMCFS.js} +1 -1
- package/public/{chunk-HVGUNGBB.js → chunk-6O32KEYY.js} +1 -1
- package/public/{chunk-NUCXRR5D.js → chunk-7K67C3PU.js} +1 -1
- package/public/{chunk-HERKNFLL.js → chunk-7PEOCUE2.js} +3 -3
- package/public/{chunk-5WTTTYNS.js → chunk-7RXQUWCY.js} +1 -1
- package/public/{chunk-RLWY3GD4.js → chunk-7SZF43OV.js} +1 -1
- package/public/chunk-AEYQANK4.js +68 -0
- package/public/{chunk-R2PMDKTD.js → chunk-AU2Q4PYM.js} +1 -1
- package/public/chunk-AZIULTML.js +1 -0
- package/public/chunk-B63E4PTS.js +19 -0
- package/public/{chunk-JWY7RFE6.js → chunk-CT6TS63V.js} +1 -1
- package/public/{chunk-TGX55EFG.js → chunk-DGS32J2V.js} +1 -1
- package/public/{chunk-TJEQFEML.js → chunk-DWAKEAKY.js} +1 -1
- package/public/chunk-DZVJNQPQ.js +1 -0
- package/public/chunk-E26RJWMZ.js +4 -0
- package/public/{chunk-E4ZKIFZH.js → chunk-H22EEHWT.js} +1 -1
- package/public/{chunk-PPA66JI2.js → chunk-HZFYCQBZ.js} +1 -1
- package/public/{chunk-SOA3BB36.js → chunk-I24Z7SXB.js} +1 -1
- package/public/{chunk-IEO2AG2N.js → chunk-IA43FDJ7.js} +1 -1
- package/public/{chunk-EYO3XCE2.js → chunk-IHMVNP7Y.js} +1 -1
- package/public/{chunk-FOSFENMV.js → chunk-IJNJ3FHH.js} +1 -1
- package/public/{chunk-5T6O4JCR.js → chunk-IM4LXJ36.js} +1 -1
- package/public/chunk-J4AYRIB4.js +1 -0
- package/public/{chunk-XS5JK2LY.js → chunk-JXJXX7ID.js} +1 -1
- package/public/chunk-K73OEMZP.js +1 -0
- package/public/chunk-KAZYWBPX.js +1 -0
- package/public/chunk-KGXF4YD5.js +1 -0
- package/public/chunk-KN2SQNGB.js +1 -0
- package/public/chunk-LN3BMCV4.js +1 -0
- package/public/{chunk-B5Z4M7ZJ.js → chunk-LOQEG2RD.js} +1 -1
- package/public/chunk-M3HVG4RQ.js +1 -0
- package/public/{chunk-WMGV3KS6.js → chunk-MNT5ZGV3.js} +1 -1
- package/public/{chunk-5W7EKO7F.js → chunk-NTFDKV64.js} +1 -1
- package/public/chunk-PF7M52WR.js +1 -0
- package/public/chunk-PFWD43QS.js +2 -0
- package/public/{chunk-E7S36RMO.js → chunk-PHND6FV5.js} +1 -1
- package/public/chunk-PSYU6RB3.js +1 -0
- package/public/{chunk-4H7ODI34.js → chunk-Q7T3F2Y7.js} +1 -1
- package/public/chunk-QKKTMQUU.js +1 -0
- package/public/chunk-QT6XPFQS.js +1 -0
- package/public/{chunk-5G7T74GR.js → chunk-R2WI5YTX.js} +1 -1
- package/public/chunk-R44T3ZI7.js +50 -0
- package/public/{chunk-Z6VQEXUS.js → chunk-R6KWC4OQ.js} +1 -1
- package/public/{chunk-NIERW5KT.js → chunk-RDOYYGV5.js} +1 -1
- package/public/chunk-RERUZJD4.js +5 -0
- package/public/chunk-S5IG2PNV.js +1 -0
- package/public/{chunk-LI4BZAUI.js → chunk-SVVZYE76.js} +1 -1
- package/public/{chunk-IKY3F7MM.js → chunk-T3SFHTRG.js} +1 -1
- package/public/{chunk-USXMCNIE.js → chunk-TJ6P7UCH.js} +1 -1
- package/public/{chunk-AOALMLGY.js → chunk-U3NNN7U4.js} +1 -1
- package/public/{chunk-7F6JT34E.js → chunk-UBLR5WZR.js} +1 -1
- package/public/{chunk-UKEKNQEJ.js → chunk-UZHUIPNT.js} +1 -1
- package/public/{chunk-EHHNHG6Q.js → chunk-VNXIDOPC.js} +1 -1
- package/public/{chunk-RON3LUMX.js → chunk-W6VJMRO6.js} +1 -1
- package/public/{chunk-BQTGMLQB.js → chunk-WFVVY4KI.js} +1 -1
- package/public/{chunk-Y2N6WV2O.js → chunk-WHSTHY5K.js} +1 -1
- package/public/chunk-XMBCOKOA.js +1 -0
- package/public/{chunk-VB4UAZWJ.js → chunk-XQACD65E.js} +1 -1
- package/public/{chunk-DIWD6B4C.js → chunk-XQCLQKCG.js} +2 -2
- package/public/{chunk-IXIZVUXX.js → chunk-XS55KH6X.js} +1 -1
- package/public/{chunk-AO7VT6PL.js → chunk-YFMEPI62.js} +1 -1
- package/public/chunk-Z4E6BJST.js +1 -0
- package/public/{chunk-OTOQR5Z2.js → chunk-ZSWIXPXA.js} +1 -1
- package/public/index.html +2 -2
- package/public/{main-QP5R7HI3.js → main-WFXBCXTF.js} +1 -1
- package/public/{styles-CSF457UW.css → styles-WNHDEKE4.css} +1 -1
- package/scripts/extract-plugin-alias.js +8 -4
- package/public/chunk-2ADAW5AD.js +0 -1
- package/public/chunk-2MFBHUTD.js +0 -1
- package/public/chunk-2Y63WBU6.js +0 -1
- package/public/chunk-4AWJ2PWG.js +0 -1
- package/public/chunk-4DVF333O.js +0 -1
- package/public/chunk-4E4YMHG4.js +0 -1
- package/public/chunk-BI2TS6NN.js +0 -4
- package/public/chunk-BVTPAZF3.js +0 -1
- package/public/chunk-CWTDHTPI.js +0 -1
- package/public/chunk-D4LRW76J.js +0 -1
- package/public/chunk-DL2QDFLD.js +0 -2
- package/public/chunk-I3QQTGGZ.js +0 -1
- package/public/chunk-IBO6BDNZ.js +0 -1
- package/public/chunk-ISV4M72Q.js +0 -1
- package/public/chunk-JWCVCB6V.js +0 -5
- package/public/chunk-JWHZQ7YI.js +0 -40
- package/public/chunk-LGE6SGDN.js +0 -1
- package/public/chunk-PZD3OMMY.js +0 -1
- package/public/chunk-QOSAHW73.js +0 -50
- package/public/chunk-QU4I4QSX.js +0 -1
- package/public/chunk-SXOLKD36.js +0 -19
- package/public/chunk-ZC3JEQZ5.js +0 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
2
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
3
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -8,66 +7,100 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
9
|
};
|
|
11
|
-
var
|
|
12
|
-
return (
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
12
|
};
|
|
14
13
|
var PluginsService_1;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
14
|
+
import { execSync, fork, spawn } from 'node:child_process';
|
|
15
|
+
import { EventEmitter } from 'node:events';
|
|
16
|
+
import { constants, existsSync } from 'node:fs';
|
|
17
|
+
import { access, readdir, readFile, realpath, stat } from 'node:fs/promises';
|
|
18
|
+
import { createRequire } from 'node:module';
|
|
19
|
+
import { arch, cpus, platform, userInfo } from 'node:os';
|
|
20
|
+
import { basename, delimiter, dirname, join, resolve, sep, } from 'node:path';
|
|
21
|
+
import process from 'node:process';
|
|
22
|
+
import { HttpService } from '@nestjs/axios';
|
|
23
|
+
import { BadRequestException, Inject, Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common';
|
|
24
|
+
import axios from 'axios';
|
|
25
|
+
import { cyan, green, red, yellow } from 'bash-color';
|
|
26
|
+
import { createFile, ensureDir, pathExists, pathExistsSync, readJson, remove } from 'fs-extra/esm';
|
|
27
|
+
import _ from 'lodash';
|
|
28
|
+
import NodeCache from 'node-cache';
|
|
29
|
+
import pLimit from 'p-limit';
|
|
30
|
+
import { firstValueFrom } from 'rxjs';
|
|
31
|
+
import { gt, lt, parse, satisfies } from 'semver';
|
|
32
|
+
import { ConfigService } from '../../core/config/config.service.js';
|
|
33
|
+
import { HomebridgeIpcService } from '../../core/homebridge-ipc/homebridge-ipc.service.js';
|
|
34
|
+
import { Logger } from '../../core/logger/logger.service.js';
|
|
35
|
+
import { NodePtyService } from '../../core/node-pty/node-pty.service.js';
|
|
36
|
+
import { ChildBridgesService } from '../child-bridges/child-bridges.service.js';
|
|
37
|
+
const { orderBy, uniq } = _;
|
|
38
|
+
const require = createRequire(import.meta.url);
|
|
39
|
+
let PluginsService = class PluginsService {
|
|
40
|
+
static { PluginsService_1 = this; }
|
|
41
|
+
httpService;
|
|
42
|
+
nodePtyService;
|
|
43
|
+
logger;
|
|
44
|
+
configService;
|
|
45
|
+
homebridgeIpcService;
|
|
46
|
+
childBridgesService;
|
|
47
|
+
static PLUGIN_IDENTIFIER_PATTERN = /^(@[\w-]+(\.[\w-]+)*\/)?homebridge-[\w-]+$/;
|
|
48
|
+
_npm;
|
|
49
|
+
_paths;
|
|
50
|
+
get npm() {
|
|
51
|
+
if (!this._npm) {
|
|
52
|
+
this._npm = this.getNpmPath();
|
|
53
|
+
}
|
|
54
|
+
return this._npm;
|
|
55
|
+
}
|
|
56
|
+
get paths() {
|
|
57
|
+
if (!this._paths) {
|
|
58
|
+
this._paths = this.getBasePaths();
|
|
59
|
+
}
|
|
60
|
+
return this._paths;
|
|
61
|
+
}
|
|
62
|
+
static UI_RESTART_DELAY_MS = 5000;
|
|
63
|
+
installedPlugins;
|
|
64
|
+
npmPackage;
|
|
65
|
+
pluginListUrl = 'https://raw.githubusercontent.com/homebridge/plugins/latest/';
|
|
66
|
+
pluginListFile = `${this.pluginListUrl}assets/plugins-v2.min.json`;
|
|
67
|
+
pluginListRetryTimeout;
|
|
68
|
+
hiddenPlugins = [];
|
|
69
|
+
maintainedPlugins = [];
|
|
70
|
+
pluginIcons = {};
|
|
71
|
+
pluginAuthors = {};
|
|
72
|
+
pluginNames = {};
|
|
73
|
+
pluginChangelogs = {};
|
|
74
|
+
newScopePlugins = {};
|
|
75
|
+
verifiedPlugins = [];
|
|
76
|
+
verifiedPlusPlugins = [];
|
|
77
|
+
npmPluginCache = new NodeCache({ stdTTL: 300 });
|
|
78
|
+
pluginAliasCache = new NodeCache({ stdTTL: 86400 });
|
|
79
|
+
installedPluginsCache = new NodeCache({ stdTTL: 60 });
|
|
80
|
+
pluginAliasHints = {
|
|
81
|
+
'homebridge-broadlink-rm-pro': {
|
|
82
|
+
pluginAlias: 'BroadlinkRM',
|
|
83
|
+
pluginType: 'platform',
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
constructor(httpService, nodePtyService, logger, configService, homebridgeIpcService, childBridgesService) {
|
|
36
87
|
this.httpService = httpService;
|
|
37
88
|
this.nodePtyService = nodePtyService;
|
|
38
89
|
this.logger = logger;
|
|
39
90
|
this.configService = configService;
|
|
40
|
-
this.
|
|
41
|
-
this.
|
|
42
|
-
this.pluginListUrl = 'https://raw.githubusercontent.com/homebridge/plugins/latest/';
|
|
43
|
-
this.pluginListFile = `${this.pluginListUrl}assets/plugins-v2.min.json`;
|
|
44
|
-
this.hiddenPlugins = [];
|
|
45
|
-
this.maintainedPlugins = [];
|
|
46
|
-
this.pluginIcons = {};
|
|
47
|
-
this.pluginAuthors = {};
|
|
48
|
-
this.pluginNames = {};
|
|
49
|
-
this.pluginChangelogs = {};
|
|
50
|
-
this.newScopePlugins = {};
|
|
51
|
-
this.verifiedPlugins = [];
|
|
52
|
-
this.verifiedPlusPlugins = [];
|
|
53
|
-
this.npmPluginCache = new node_cache_1.default({ stdTTL: 300 });
|
|
54
|
-
this.pluginAliasCache = new node_cache_1.default({ stdTTL: 86400 });
|
|
55
|
-
this.installedPluginsCache = new node_cache_1.default({ stdTTL: 60 });
|
|
56
|
-
this.pluginAliasHints = {
|
|
57
|
-
'homebridge-broadlink-rm-pro': {
|
|
58
|
-
pluginAlias: 'BroadlinkRM',
|
|
59
|
-
pluginType: 'platform',
|
|
60
|
-
},
|
|
61
|
-
};
|
|
91
|
+
this.homebridgeIpcService = homebridgeIpcService;
|
|
92
|
+
this.childBridgesService = childBridgesService;
|
|
62
93
|
this.httpService.axiosRef.interceptors.request.use((config) => {
|
|
63
|
-
const source =
|
|
94
|
+
const source = axios.CancelToken.source();
|
|
64
95
|
config.cancelToken = source.token;
|
|
65
96
|
setTimeout(() => {
|
|
66
97
|
source.cancel('Timeout: request took more than 15 seconds');
|
|
67
98
|
}, 15000);
|
|
68
99
|
return config;
|
|
69
100
|
});
|
|
70
|
-
this.loadPluginList()
|
|
101
|
+
this.loadPluginList().catch((err) => {
|
|
102
|
+
this.logger.error('Failed to load plugin list during initialization:', err);
|
|
103
|
+
});
|
|
71
104
|
setInterval(this.loadPluginList.bind(this), 60000 * 60 * 12);
|
|
72
105
|
}
|
|
73
106
|
fixDisplayName(plugin) {
|
|
@@ -86,12 +119,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
86
119
|
const modules = await this.getInstalledModules();
|
|
87
120
|
const disabledPlugins = await this.getDisabledPlugins();
|
|
88
121
|
const homebridgePlugins = modules.filter(module => ((module.name.indexOf('homebridge-') === 0) || this.isScopedPlugin(module.name))
|
|
89
|
-
&&
|
|
90
|
-
const limit = (
|
|
122
|
+
&& pathExistsSync(join(module.installPath, 'package.json')));
|
|
123
|
+
const limit = pLimit(cpus().length);
|
|
91
124
|
await Promise.all(homebridgePlugins.map(async (pkg) => {
|
|
92
125
|
return limit(async () => {
|
|
93
126
|
try {
|
|
94
|
-
const pkgJson = await
|
|
127
|
+
const pkgJson = await readJson(join(pkg.installPath, 'package.json'));
|
|
95
128
|
if (pkgJson.keywords && pkgJson.keywords.includes('homebridge-plugin')) {
|
|
96
129
|
const plugin = await this.parsePackageJson(pkgJson, pkg.path);
|
|
97
130
|
plugin.disabled = disabledPlugins.includes(plugin.name);
|
|
@@ -120,21 +153,21 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
120
153
|
}
|
|
121
154
|
async lookupPlugin(pluginName) {
|
|
122
155
|
if (!PluginsService_1.PLUGIN_IDENTIFIER_PATTERN.test(pluginName)) {
|
|
123
|
-
throw new
|
|
156
|
+
throw new BadRequestException('Invalid plugin name.');
|
|
124
157
|
}
|
|
125
158
|
const lookup = await this.searchNpmRegistrySingle(pluginName);
|
|
126
159
|
if (!lookup.length) {
|
|
127
|
-
throw new
|
|
160
|
+
throw new NotFoundException();
|
|
128
161
|
}
|
|
129
162
|
return lookup[0];
|
|
130
163
|
}
|
|
131
164
|
async getAvailablePluginVersions(pluginName) {
|
|
132
165
|
if (!PluginsService_1.PLUGIN_IDENTIFIER_PATTERN.test(pluginName) && pluginName !== 'homebridge') {
|
|
133
|
-
throw new
|
|
166
|
+
throw new BadRequestException('Invalid plugin name.');
|
|
134
167
|
}
|
|
135
168
|
try {
|
|
136
169
|
const fromCache = this.npmPluginCache.get(`lookup-${pluginName}`);
|
|
137
|
-
const pkg = fromCache || (await
|
|
170
|
+
const pkg = fromCache || (await firstValueFrom((this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(pluginName).replace(/%40/g, '@')}`, {
|
|
138
171
|
headers: {
|
|
139
172
|
accept: 'application/vnd.npm.install-v1+json',
|
|
140
173
|
},
|
|
@@ -156,7 +189,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
156
189
|
};
|
|
157
190
|
}
|
|
158
191
|
catch (e) {
|
|
159
|
-
throw new
|
|
192
|
+
throw new NotFoundException();
|
|
160
193
|
}
|
|
161
194
|
}
|
|
162
195
|
extractTerms(query, separator) {
|
|
@@ -210,11 +243,11 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
210
243
|
const q = `${normalizedQuery.substring(0, 15)}+keywords:homebridge-plugin+not:deprecated&size=99`;
|
|
211
244
|
let searchResults;
|
|
212
245
|
try {
|
|
213
|
-
searchResults = (await
|
|
246
|
+
searchResults = (await firstValueFrom(this.httpService.get(`https://registry.npmjs.org/-/v1/search?text=${q}`))).data;
|
|
214
247
|
}
|
|
215
248
|
catch (e) {
|
|
216
249
|
this.logger.error(`Failed to search the npm registry (see https://homebridge.io/w/JJSz6 for help) as ${e.message}.`);
|
|
217
|
-
throw new
|
|
250
|
+
throw new InternalServerErrorException(`Failed to search the npm registry as ${e.message}, see logs.`);
|
|
218
251
|
}
|
|
219
252
|
const hiddenPluginsSet = new Set(this.hiddenPlugins);
|
|
220
253
|
const plugins = searchResults.objects
|
|
@@ -260,7 +293,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
260
293
|
matchGroups[matchType].push(plugin);
|
|
261
294
|
}
|
|
262
295
|
}
|
|
263
|
-
const orderPlugins = (arr) =>
|
|
296
|
+
const orderPlugins = (arr) => orderBy(arr, ['isHbScoped', 'verifiedPlusPlugin', 'verifiedPlugin', 'lastUpdated'], ['desc', 'desc', 'desc']);
|
|
264
297
|
return [
|
|
265
298
|
...orderPlugins(matchGroups.exactName),
|
|
266
299
|
...orderPlugins(matchGroups.exactKeyword),
|
|
@@ -272,7 +305,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
272
305
|
async searchNpmRegistrySingle(query) {
|
|
273
306
|
try {
|
|
274
307
|
const fromCache = this.npmPluginCache.get(`lookup-${query}`);
|
|
275
|
-
const pkg = fromCache || (await
|
|
308
|
+
const pkg = fromCache || (await firstValueFrom((this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(query).replace(/%40/g, '@')}`)))).data;
|
|
276
309
|
if (!fromCache) {
|
|
277
310
|
this.npmPluginCache.set(`lookup-${query}`, pkg, 60);
|
|
278
311
|
}
|
|
@@ -343,8 +376,8 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
343
376
|
if (action === 'install' && pluginAction.version === 'latest') {
|
|
344
377
|
pluginAction.version = await this.getNpmModuleLatestVersion(pluginAction.name);
|
|
345
378
|
}
|
|
346
|
-
const userPlatform =
|
|
347
|
-
if (this.configService.ui.webroot &&
|
|
379
|
+
const userPlatform = platform();
|
|
380
|
+
if (this.configService.ui.webroot && lt(pluginAction.version, '5.9.1-alpha.0')) {
|
|
348
381
|
throw new Error(`Cannot install HB UI v${pluginAction.version} when a webroot is configured.\n\r`
|
|
349
382
|
+ 'Please either:\n\r'
|
|
350
383
|
+ ' - Remove the configured webroot, restart Homebridge, then try the install again, or\n\r'
|
|
@@ -365,20 +398,20 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
365
398
|
return true;
|
|
366
399
|
}
|
|
367
400
|
catch (e) {
|
|
368
|
-
client.emit('stdout',
|
|
401
|
+
client.emit('stdout', yellow('\r\nBundled update failed. Trying regular update using npm.\r\n\r\n'));
|
|
369
402
|
}
|
|
370
403
|
}
|
|
371
|
-
if (
|
|
372
|
-
client.emit('stdout',
|
|
373
|
-
client.emit('stdout',
|
|
374
|
-
client.emit('stdout',
|
|
375
|
-
client.emit('stdout',
|
|
404
|
+
if (cpus().length === 1 && arch() === 'arm') {
|
|
405
|
+
client.emit('stdout', yellow('***************************************************************\r\n'));
|
|
406
|
+
client.emit('stdout', yellow(`Please be patient while ${this.configService.name} updates.\r\n`));
|
|
407
|
+
client.emit('stdout', yellow('This process may take 5-15 minutes to complete on your device.\r\n'));
|
|
408
|
+
client.emit('stdout', yellow('***************************************************************\r\n\r\n'));
|
|
376
409
|
}
|
|
377
410
|
const installOptions = [];
|
|
378
|
-
if (installPath === this.configService.customPluginPath && await
|
|
411
|
+
if (installPath === this.configService.customPluginPath && await pathExists(resolve(installPath, '../package.json'))) {
|
|
379
412
|
installOptions.push('--save');
|
|
380
413
|
}
|
|
381
|
-
installPath =
|
|
414
|
+
installPath = resolve(installPath, '../');
|
|
382
415
|
if (!this.configService.customPluginPath || userPlatform === 'win32' || existingPlugin?.globalInstall === true) {
|
|
383
416
|
installOptions.push('-g');
|
|
384
417
|
}
|
|
@@ -411,16 +444,16 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
411
444
|
return true;
|
|
412
445
|
}
|
|
413
446
|
catch (e) {
|
|
414
|
-
client.emit('stdout',
|
|
447
|
+
client.emit('stdout', yellow('\r\nBundled install / update could not complete. Trying regular install / update using npm.\r\n\r\n'));
|
|
415
448
|
}
|
|
416
449
|
}
|
|
417
450
|
const installOptions = [];
|
|
418
451
|
let npmPluginLabel = pluginAction.name;
|
|
419
|
-
if (installPath === this.configService.customPluginPath && await
|
|
452
|
+
if (installPath === this.configService.customPluginPath && await pathExists(resolve(installPath, '../package.json'))) {
|
|
420
453
|
installOptions.push('--save');
|
|
421
454
|
}
|
|
422
|
-
installPath =
|
|
423
|
-
if (!this.configService.customPluginPath ||
|
|
455
|
+
installPath = resolve(installPath, '../');
|
|
456
|
+
if (!this.configService.customPluginPath || platform() === 'win32' || existingPlugin?.globalInstall === true) {
|
|
424
457
|
installOptions.push('-g');
|
|
425
458
|
}
|
|
426
459
|
if (action === 'install') {
|
|
@@ -434,9 +467,9 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
434
467
|
}
|
|
435
468
|
async getHomebridgePackage() {
|
|
436
469
|
if (this.configService.ui.homebridgePackagePath) {
|
|
437
|
-
const pkgJsonPath =
|
|
438
|
-
if (await
|
|
439
|
-
return await this.parsePackageJson(await
|
|
470
|
+
const pkgJsonPath = join(this.configService.ui.homebridgePackagePath, 'package.json');
|
|
471
|
+
if (await pathExists(pkgJsonPath)) {
|
|
472
|
+
return await this.parsePackageJson(await readJson(pkgJsonPath), this.configService.ui.homebridgePackagePath);
|
|
440
473
|
}
|
|
441
474
|
else {
|
|
442
475
|
this.logger.error(`The Homebridge path ${this.configService.ui.homebridgePackagePath} does not exist.`);
|
|
@@ -456,20 +489,20 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
456
489
|
throw new Error('Unable To Find Homebridge Installation.');
|
|
457
490
|
}
|
|
458
491
|
const homebridgeModule = homebridgeInstalls[0];
|
|
459
|
-
const pkgJson = await
|
|
492
|
+
const pkgJson = await readJson(join(homebridgeModule.installPath, 'package.json'));
|
|
460
493
|
const homebridge = await this.parsePackageJson(pkgJson, homebridgeModule.path);
|
|
461
494
|
if (!homebridge.latestVersion) {
|
|
462
495
|
return homebridge;
|
|
463
496
|
}
|
|
464
|
-
const homebridgeVersion =
|
|
497
|
+
const homebridgeVersion = parse(homebridge.installedVersion);
|
|
465
498
|
const installedTag = homebridgeVersion.prerelease[0]?.toString();
|
|
466
499
|
if (!homebridge.updateAvailable) {
|
|
467
|
-
const shouldCheckBetas = (installedTag && ['alpha', 'beta', 'test'].includes(installedTag) &&
|
|
500
|
+
const shouldCheckBetas = (installedTag && ['alpha', 'beta', 'test'].includes(installedTag) && gt(homebridge.installedVersion, homebridge.latestVersion))
|
|
468
501
|
|| this.configService.ui.plugins?.alwaysShowBetas;
|
|
469
502
|
if (shouldCheckBetas) {
|
|
470
503
|
const versions = await this.getAvailablePluginVersions('homebridge');
|
|
471
504
|
const targetTag = this.configService.ui.plugins?.alwaysShowBetas && !installedTag ? 'beta' : installedTag;
|
|
472
|
-
if (versions.tags[targetTag] &&
|
|
505
|
+
if (versions.tags[targetTag] && gt(versions.tags[targetTag], homebridge.installedVersion)) {
|
|
473
506
|
homebridge.latestVersion = versions.tags[targetTag];
|
|
474
507
|
homebridge.updateAvailable = true;
|
|
475
508
|
homebridge.updateEngines = versions.versions?.[homebridge.latestVersion]?.engines || null;
|
|
@@ -489,16 +522,112 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
489
522
|
let installPath = homebridge.installPath;
|
|
490
523
|
const installOptions = [];
|
|
491
524
|
installOptions.push('--omit=dev');
|
|
492
|
-
if (installPath === this.configService.customPluginPath && await
|
|
525
|
+
if (installPath === this.configService.customPluginPath && await pathExists(resolve(installPath, '../package.json'))) {
|
|
493
526
|
installOptions.push('--save');
|
|
494
527
|
}
|
|
495
|
-
installPath =
|
|
496
|
-
if (homebridge.globalInstall ||
|
|
528
|
+
installPath = resolve(installPath, '../');
|
|
529
|
+
if (homebridge.globalInstall || platform() === 'win32') {
|
|
497
530
|
installOptions.push('-g');
|
|
498
531
|
}
|
|
499
532
|
await this.runNpmCommand([...this.npm, 'install', ...installOptions, `${homebridge.name}@${homebridgeUpdateAction.version}`], installPath, client, homebridgeUpdateAction.termCols, homebridgeUpdateAction.termRows);
|
|
500
533
|
return true;
|
|
501
534
|
}
|
|
535
|
+
async triggerUpdate(name, version) {
|
|
536
|
+
let targetVersion = version || 'latest';
|
|
537
|
+
try {
|
|
538
|
+
switch (name) {
|
|
539
|
+
case 'homebridge': {
|
|
540
|
+
const homebridge = await this.getHomebridgePackage();
|
|
541
|
+
if (targetVersion === 'latest' && homebridge.latestVersion) {
|
|
542
|
+
targetVersion = homebridge.latestVersion;
|
|
543
|
+
}
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
case 'homebridge-config-ui-x': {
|
|
547
|
+
const uiPackage = await this.getHomebridgeUiPackage();
|
|
548
|
+
if (!uiPackage) {
|
|
549
|
+
throw new NotFoundException(`Package ${name} is not installed.`);
|
|
550
|
+
}
|
|
551
|
+
if (targetVersion === 'latest' && uiPackage.latestVersion) {
|
|
552
|
+
targetVersion = uiPackage.latestVersion;
|
|
553
|
+
}
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
default: {
|
|
557
|
+
if (!PluginsService_1.PLUGIN_IDENTIFIER_PATTERN.test(name)) {
|
|
558
|
+
throw new BadRequestException('Invalid package name. Must be "homebridge", "homebridge-config-ui-x", or a valid Homebridge plugin name.');
|
|
559
|
+
}
|
|
560
|
+
const plugins = await this.getInstalledPlugins();
|
|
561
|
+
const plugin = plugins.find(p => p.name === name);
|
|
562
|
+
if (!plugin) {
|
|
563
|
+
throw new NotFoundException(`Plugin ${name} is not installed.`);
|
|
564
|
+
}
|
|
565
|
+
if (targetVersion === 'latest' && plugin.latestVersion) {
|
|
566
|
+
targetVersion = plugin.latestVersion;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
catch (e) {
|
|
572
|
+
if (e instanceof NotFoundException) {
|
|
573
|
+
throw e;
|
|
574
|
+
}
|
|
575
|
+
this.logger.error(`Failed to validate package ${name} for update: ${e.message}`);
|
|
576
|
+
throw new BadRequestException(`Failed to validate package ${name} for update.`);
|
|
577
|
+
}
|
|
578
|
+
setImmediate(async () => {
|
|
579
|
+
try {
|
|
580
|
+
this.logger.log(`Starting scheduled update for ${name} to version ${targetVersion}`);
|
|
581
|
+
const mockClient = new EventEmitter();
|
|
582
|
+
mockClient.on('stdout', (data) => {
|
|
583
|
+
this.logger.log(`[${name} update] ${data.toString().trim()}`);
|
|
584
|
+
});
|
|
585
|
+
if (name === 'homebridge') {
|
|
586
|
+
await this.updateHomebridgePackage({ version: targetVersion }, mockClient);
|
|
587
|
+
this.logger.log(`Successfully updated Homebridge to version ${targetVersion}. Performing quick restart of Homebridge process...`);
|
|
588
|
+
this.homebridgeIpcService.restartHomebridge();
|
|
589
|
+
}
|
|
590
|
+
else if (name === this.configService.name) {
|
|
591
|
+
await this.managePlugin('install', { name, version: targetVersion }, mockClient);
|
|
592
|
+
this.logger.warn(`homebridge-config-ui-x has been updated, server will restart in ${PluginsService_1.UI_RESTART_DELAY_MS / 1000} seconds...`);
|
|
593
|
+
setTimeout(() => {
|
|
594
|
+
process.exit(0);
|
|
595
|
+
}, PluginsService_1.UI_RESTART_DELAY_MS);
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
await this.managePlugin('install', { name, version: targetVersion }, mockClient);
|
|
599
|
+
this.logger.log(`Successfully updated ${name} to version ${targetVersion}.`);
|
|
600
|
+
const childBridgeUsernames = await this.getPluginChildBridgeUsernames(name);
|
|
601
|
+
if (childBridgeUsernames.length > 0) {
|
|
602
|
+
this.logger.log(`${name} is running in ${childBridgeUsernames.length} child bridge(s). Restarting child bridges: ${childBridgeUsernames.join(', ')}`);
|
|
603
|
+
for (const username of childBridgeUsernames) {
|
|
604
|
+
this.logger.log(`Restarting child bridge ${username}...`);
|
|
605
|
+
this.childBridgesService.restartChildBridge(username);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
this.logger.log(`${name} is not running in a child bridge. Performing quick restart of Homebridge process...`);
|
|
610
|
+
this.homebridgeIpcService.restartHomebridge();
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
catch (error) {
|
|
615
|
+
this.logger.error(`Failed to update ${name}: ${error.message}`);
|
|
616
|
+
try {
|
|
617
|
+
this.logger.warn('Attempting fallback restart of Homebridge process...');
|
|
618
|
+
this.homebridgeIpcService.restartHomebridge();
|
|
619
|
+
}
|
|
620
|
+
catch (restartError) {
|
|
621
|
+
this.logger.error(`Failed to restart Homebridge: ${restartError.message}`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
return {
|
|
626
|
+
ok: true,
|
|
627
|
+
name,
|
|
628
|
+
version: targetVersion,
|
|
629
|
+
};
|
|
630
|
+
}
|
|
502
631
|
async getHomebridgeUiPackage() {
|
|
503
632
|
const plugins = await this.getInstalledPlugins();
|
|
504
633
|
return plugins.find((x) => x.name === this.configService.name);
|
|
@@ -513,9 +642,9 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
513
642
|
if (!npmPkg) {
|
|
514
643
|
throw new Error('Could not find npm package');
|
|
515
644
|
}
|
|
516
|
-
const pkgJson = await
|
|
645
|
+
const pkgJson = await readJson(join(npmPkg.installPath, 'package.json'));
|
|
517
646
|
const npm = await this.parsePackageJson(pkgJson, npmPkg.path);
|
|
518
|
-
npm.showUpdateWarning =
|
|
647
|
+
npm.showUpdateWarning = lt(npm.installedVersion, '9.5.0');
|
|
519
648
|
this.npmPackage = npm;
|
|
520
649
|
return npm;
|
|
521
650
|
}
|
|
@@ -528,7 +657,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
528
657
|
&& pluginAction.version !== 'latest') {
|
|
529
658
|
try {
|
|
530
659
|
const repoVersion = pluginAction.name.startsWith('@') ? 'v1.0.0-1' : 'v1.0.0';
|
|
531
|
-
await
|
|
660
|
+
await firstValueFrom(this.httpService.head(`https://github.com/homebridge/plugins/releases/download/${repoVersion}/${pluginAction.name.replace('/', '@')}-${pluginAction.version}.sha256`));
|
|
532
661
|
return true;
|
|
533
662
|
}
|
|
534
663
|
catch (e) {
|
|
@@ -540,7 +669,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
540
669
|
}
|
|
541
670
|
}
|
|
542
671
|
async doPluginBundleUpdate(pluginAction, client) {
|
|
543
|
-
const pluginUpgradeInstallScriptPath =
|
|
672
|
+
const pluginUpgradeInstallScriptPath = join(process.env.UIX_BASE_PATH, 'scripts/upgrade-install-plugin.sh');
|
|
544
673
|
await this.runNpmCommand([pluginUpgradeInstallScriptPath, pluginAction.name, pluginAction.version, this.configService.customPluginPath], this.configService.storagePath, client, pluginAction.termCols, pluginAction.termRows);
|
|
545
674
|
return true;
|
|
546
675
|
}
|
|
@@ -550,18 +679,18 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
550
679
|
'/usr/lib/node_modules',
|
|
551
680
|
'/opt/homebridge/lib/node_modules',
|
|
552
681
|
'/var/packages/homebridge/target/app/lib/node_modules',
|
|
553
|
-
].includes(
|
|
682
|
+
].includes(dirname(process.env.UIX_BASE_PATH))
|
|
554
683
|
&& pluginAction.name === this.configService.name
|
|
555
684
|
&& !['latest', 'alpha', 'beta'].includes(pluginAction.version)) {
|
|
556
685
|
try {
|
|
557
686
|
try {
|
|
558
687
|
const withV = `v${pluginAction.version}`;
|
|
559
|
-
await
|
|
688
|
+
await firstValueFrom(this.httpService.head(`https://github.com/homebridge/homebridge-config-ui-x/releases/download/${withV}/homebridge-config-ui-x-${pluginAction.version}.tar.gz`));
|
|
560
689
|
return withV;
|
|
561
690
|
}
|
|
562
691
|
catch (e2) {
|
|
563
692
|
const withoutV = pluginAction.version;
|
|
564
|
-
await
|
|
693
|
+
await firstValueFrom(this.httpService.head(`https://github.com/homebridge/homebridge-config-ui-x/releases/download/${withoutV}/homebridge-config-ui-x-${pluginAction.version}.tar.gz`));
|
|
565
694
|
return withoutV;
|
|
566
695
|
}
|
|
567
696
|
}
|
|
@@ -575,21 +704,21 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
575
704
|
}
|
|
576
705
|
}
|
|
577
706
|
async doUiBundleUpdate(pluginAction, client, githubReleaseName) {
|
|
578
|
-
const prefix =
|
|
579
|
-
const upgradeInstallScriptPath =
|
|
580
|
-
await this.runNpmCommand(this.configService.ui.sudo ? ['npm', 'run', 'upgrade-install', '--', pluginAction.version, prefix, githubReleaseName] : [upgradeInstallScriptPath, pluginAction.version, prefix, githubReleaseName],
|
|
707
|
+
const prefix = dirname(dirname(dirname(process.env.UIX_BASE_PATH)));
|
|
708
|
+
const upgradeInstallScriptPath = join(process.env.UIX_BASE_PATH, 'scripts/upgrade-install.sh');
|
|
709
|
+
await this.runNpmCommand(this.configService.ui.sudo ? ['npm', 'run', 'upgrade-install', '--', pluginAction.version, prefix, githubReleaseName] : [upgradeInstallScriptPath, pluginAction.version, prefix, githubReleaseName], process.env.UIX_BASE_PATH, client, pluginAction.termCols, pluginAction.termRows);
|
|
581
710
|
}
|
|
582
711
|
async updateSelfOffline(client) {
|
|
583
|
-
client.emit('stdout',
|
|
712
|
+
client.emit('stdout', yellow(`${this.configService.name} has been scheduled to update on the next container restart.\n\r\n\r`));
|
|
584
713
|
await new Promise(res => setTimeout(res, 800));
|
|
585
|
-
client.emit('stdout',
|
|
714
|
+
client.emit('stdout', yellow('The Docker container will now try and restart.\n\r\n\r'));
|
|
586
715
|
await new Promise(res => setTimeout(res, 800));
|
|
587
|
-
client.emit('stdout',
|
|
588
|
-
+
|
|
716
|
+
client.emit('stdout', yellow('If you have not started the Docker container with ')
|
|
717
|
+
+ red('--restart=always') + yellow(' you may\n\rneed to manually start the container again.\n\r\n\r'));
|
|
589
718
|
await new Promise(res => setTimeout(res, 800));
|
|
590
|
-
client.emit('stdout',
|
|
719
|
+
client.emit('stdout', yellow('This process may take several minutes. Please be patient.\n\r'));
|
|
591
720
|
await new Promise(res => setTimeout(res, 10000));
|
|
592
|
-
await
|
|
721
|
+
await createFile('/homebridge/.uix-upgrade-on-restart');
|
|
593
722
|
}
|
|
594
723
|
async getPluginConfigSchema(pluginName) {
|
|
595
724
|
if (!this.installedPlugins) {
|
|
@@ -597,19 +726,19 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
597
726
|
}
|
|
598
727
|
const plugin = this.installedPlugins.find(x => x.name === pluginName);
|
|
599
728
|
if (!plugin) {
|
|
600
|
-
throw new
|
|
729
|
+
throw new NotFoundException();
|
|
601
730
|
}
|
|
602
731
|
if (!plugin.settingsSchema) {
|
|
603
|
-
throw new
|
|
732
|
+
throw new NotFoundException();
|
|
604
733
|
}
|
|
605
|
-
const schemaPath =
|
|
606
|
-
let configSchema = await
|
|
734
|
+
const schemaPath = resolve(plugin.installPath, pluginName, 'config.schema.json');
|
|
735
|
+
let configSchema = await readJson(schemaPath);
|
|
607
736
|
if (configSchema.dynamicSchemaVersion) {
|
|
608
|
-
const dynamicSchemaPath =
|
|
737
|
+
const dynamicSchemaPath = resolve(this.configService.storagePath, `.${pluginName}-v${configSchema.dynamicSchemaVersion}.schema.json`);
|
|
609
738
|
this.logger.log(`[${pluginName}] dynamic schema path: ${dynamicSchemaPath}.`);
|
|
610
|
-
if (
|
|
739
|
+
if (existsSync(dynamicSchemaPath)) {
|
|
611
740
|
try {
|
|
612
|
-
configSchema = await
|
|
741
|
+
configSchema = await readJson(dynamicSchemaPath);
|
|
613
742
|
this.logger.log(`[${pluginName}] dynamic schema loaded from ${dynamicSchemaPath}.`);
|
|
614
743
|
}
|
|
615
744
|
catch (e) {
|
|
@@ -695,34 +824,34 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
695
824
|
await this.getInstalledPlugins();
|
|
696
825
|
const plugin = this.installedPlugins.find(x => x.name === pluginName);
|
|
697
826
|
if (!plugin) {
|
|
698
|
-
throw new
|
|
827
|
+
throw new NotFoundException();
|
|
699
828
|
}
|
|
700
|
-
const changeLog =
|
|
701
|
-
if (await
|
|
829
|
+
const changeLog = resolve(plugin.installPath, plugin.name, 'CHANGELOG.md');
|
|
830
|
+
if (await pathExists(changeLog)) {
|
|
702
831
|
return {
|
|
703
|
-
changelog: await
|
|
832
|
+
changelog: await readFile(changeLog, 'utf8'),
|
|
704
833
|
};
|
|
705
834
|
}
|
|
706
835
|
else {
|
|
707
|
-
throw new
|
|
836
|
+
throw new NotFoundException();
|
|
708
837
|
}
|
|
709
838
|
}
|
|
710
839
|
async getPluginRelease(pluginName) {
|
|
711
840
|
let latestVersion = null;
|
|
712
841
|
try {
|
|
713
|
-
const pkg = (await
|
|
842
|
+
const pkg = (await firstValueFrom((this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(pluginName).replace(/%40/g, '@')}`)))).data;
|
|
714
843
|
latestVersion = pkg['dist-tags'] ? pkg['dist-tags'].latest : null;
|
|
715
844
|
}
|
|
716
845
|
catch (e) {
|
|
717
|
-
throw new
|
|
846
|
+
throw new NotFoundException();
|
|
718
847
|
}
|
|
719
848
|
switch (pluginName) {
|
|
720
849
|
case 'homebridge':
|
|
721
850
|
case 'homebridge-config-ui-x': {
|
|
722
851
|
try {
|
|
723
|
-
const release = await
|
|
724
|
-
const tags = await
|
|
725
|
-
const changelog = await
|
|
852
|
+
const release = await firstValueFrom(this.httpService.get(`https://api.github.com/repos/homebridge/${pluginName}/releases/latest`));
|
|
853
|
+
const tags = await firstValueFrom(this.httpService.get(`https://api.github.com/repos/homebridge/${pluginName}/tags`));
|
|
854
|
+
const changelog = await firstValueFrom(this.httpService.get(`https://raw.githubusercontent.com/homebridge/${pluginName}/refs/tags/${tags.data[0].name}/CHANGELOG.md`));
|
|
726
855
|
return {
|
|
727
856
|
name: release.data.name,
|
|
728
857
|
notes: release.data.body,
|
|
@@ -743,33 +872,33 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
743
872
|
await this.getInstalledPlugins();
|
|
744
873
|
const plugin = this.installedPlugins.find(x => x.name === pluginName);
|
|
745
874
|
if (!plugin) {
|
|
746
|
-
throw new
|
|
875
|
+
throw new NotFoundException();
|
|
747
876
|
}
|
|
748
877
|
if (!plugin.links.homepage && !plugin.links.bugs) {
|
|
749
|
-
throw new
|
|
878
|
+
throw new NotFoundException();
|
|
750
879
|
}
|
|
751
880
|
const repoMatch = plugin.links.homepage?.match(/https:\/\/github.com\/([^/]+)\/([^/#]+)/);
|
|
752
881
|
const bugsMatch = plugin.links.bugs?.match(/https:\/\/github.com\/([^/]+)\/([^/#]+)/);
|
|
753
882
|
let match = repoMatch;
|
|
754
883
|
if (!repoMatch) {
|
|
755
884
|
if (!bugsMatch) {
|
|
756
|
-
throw new
|
|
885
|
+
throw new NotFoundException();
|
|
757
886
|
}
|
|
758
887
|
match = bugsMatch;
|
|
759
888
|
}
|
|
760
889
|
try {
|
|
761
|
-
const release = await
|
|
890
|
+
const release = await firstValueFrom(this.httpService.get(`https://api.github.com/repos/${match[1]}/${match[2]}/releases/latest`));
|
|
762
891
|
const latestTag = release.data.tag_name;
|
|
763
892
|
const isReleaseMatch = latestVersion?.replace(/[^0-9.]/g, '').includes(release.data.tag_name?.replace(/[^0-9.]/g, ''));
|
|
764
893
|
const changelogPath = this.pluginChangelogs[pluginName] || '';
|
|
765
894
|
let changelogData = null;
|
|
766
895
|
try {
|
|
767
|
-
const changelog = await
|
|
896
|
+
const changelog = await firstValueFrom(this.httpService.get(`https://raw.githubusercontent.com/${match[1]}/${match[2]}/refs/tags/${latestTag}/${changelogPath}CHANGELOG.md`));
|
|
768
897
|
changelogData = changelog.data;
|
|
769
898
|
}
|
|
770
899
|
catch {
|
|
771
900
|
try {
|
|
772
|
-
const changelog = (await
|
|
901
|
+
const changelog = (await firstValueFrom(this.httpService.get(`https://raw.githubusercontent.com/${match[1]}/${match[2]}/refs/tags/${latestTag}/${changelogPath}changelog.md`))).data;
|
|
773
902
|
changelogData = changelog.data;
|
|
774
903
|
}
|
|
775
904
|
catch { }
|
|
@@ -782,7 +911,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
782
911
|
};
|
|
783
912
|
}
|
|
784
913
|
catch (e) {
|
|
785
|
-
throw new
|
|
914
|
+
throw new NotFoundException();
|
|
786
915
|
}
|
|
787
916
|
}
|
|
788
917
|
}
|
|
@@ -793,7 +922,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
793
922
|
}
|
|
794
923
|
const plugin = this.installedPlugins.find(x => x.name === pluginName);
|
|
795
924
|
if (!plugin) {
|
|
796
|
-
throw new
|
|
925
|
+
throw new NotFoundException();
|
|
797
926
|
}
|
|
798
927
|
const fromCache = this.pluginAliasCache.get(pluginName);
|
|
799
928
|
if (fromCache) {
|
|
@@ -811,9 +940,9 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
811
940
|
else {
|
|
812
941
|
try {
|
|
813
942
|
await new Promise((res, rej) => {
|
|
814
|
-
const child =
|
|
943
|
+
const child = fork(resolve(process.env.UIX_BASE_PATH, 'scripts/extract-plugin-alias.js'), {
|
|
815
944
|
env: {
|
|
816
|
-
UIX_EXTRACT_PLUGIN_PATH:
|
|
945
|
+
UIX_EXTRACT_PLUGIN_PATH: resolve(plugin.installPath, plugin.name),
|
|
817
946
|
},
|
|
818
947
|
stdio: 'ignore',
|
|
819
948
|
});
|
|
@@ -845,24 +974,50 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
845
974
|
this.pluginAliasCache.set(pluginName, output);
|
|
846
975
|
return output;
|
|
847
976
|
}
|
|
977
|
+
async getPluginChildBridgeUsernames(pluginName) {
|
|
978
|
+
try {
|
|
979
|
+
const plugin = await this.getPluginAlias(pluginName);
|
|
980
|
+
if (!plugin.pluginAlias) {
|
|
981
|
+
return [];
|
|
982
|
+
}
|
|
983
|
+
const config = await readJson(this.configService.configPath);
|
|
984
|
+
const arrayKey = plugin.pluginType === 'accessory' ? 'accessories' : 'platforms';
|
|
985
|
+
const usernamesSet = new Set();
|
|
986
|
+
const pluginBlocks = config[arrayKey]?.filter((block) => {
|
|
987
|
+
const matchesPlugin = block[plugin.pluginType] === plugin.pluginAlias
|
|
988
|
+
|| block[plugin.pluginType] === `${pluginName}.${plugin.pluginAlias}`;
|
|
989
|
+
return matchesPlugin && block._bridge?.username;
|
|
990
|
+
}) || [];
|
|
991
|
+
for (const block of pluginBlocks) {
|
|
992
|
+
if (block._bridge?.username) {
|
|
993
|
+
usernamesSet.add(block._bridge.username);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
return Array.from(usernamesSet);
|
|
997
|
+
}
|
|
998
|
+
catch (e) {
|
|
999
|
+
this.logger.error(`Failed to get child bridge usernames for ${pluginName}: ${e.message}`);
|
|
1000
|
+
return [];
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
848
1003
|
async getPluginUiMetadata(pluginName) {
|
|
849
1004
|
if (!this.installedPlugins) {
|
|
850
1005
|
await this.getInstalledPlugins();
|
|
851
1006
|
}
|
|
852
1007
|
const plugin = this.installedPlugins.find(x => x.name === pluginName);
|
|
853
|
-
const fullPath =
|
|
854
|
-
const schema = await
|
|
855
|
-
const customUiPath =
|
|
856
|
-
const publicPath =
|
|
857
|
-
const serverPath =
|
|
1008
|
+
const fullPath = resolve(plugin.installPath, plugin.name);
|
|
1009
|
+
const schema = await readJson(resolve(fullPath, 'config.schema.json'));
|
|
1010
|
+
const customUiPath = resolve(fullPath, schema.customUiPath || 'homebridge-ui');
|
|
1011
|
+
const publicPath = resolve(customUiPath, 'public');
|
|
1012
|
+
const serverPath = resolve(customUiPath, 'server.js');
|
|
858
1013
|
const devServer = plugin.private ? schema.customUiDevServer : null;
|
|
859
|
-
if (!devServer && !await
|
|
1014
|
+
if (!devServer && !await pathExists(customUiPath)) {
|
|
860
1015
|
throw new Error(`Plugin does not provide a custom UI at expected location: ${customUiPath}`);
|
|
861
1016
|
}
|
|
862
|
-
if (!devServer && !(await
|
|
863
|
-
throw new Error(`Custom UI path is outside the plugin root: ${await
|
|
1017
|
+
if (!devServer && !(await realpath(customUiPath)).startsWith(await realpath(fullPath))) {
|
|
1018
|
+
throw new Error(`Custom UI path is outside the plugin root: ${await realpath(customUiPath)}`);
|
|
864
1019
|
}
|
|
865
|
-
if (await
|
|
1020
|
+
if (await pathExists(resolve(publicPath, 'index.html')) || devServer) {
|
|
866
1021
|
return {
|
|
867
1022
|
devServer,
|
|
868
1023
|
serverPath,
|
|
@@ -874,7 +1029,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
874
1029
|
}
|
|
875
1030
|
async getDisabledPlugins() {
|
|
876
1031
|
try {
|
|
877
|
-
const config = await
|
|
1032
|
+
const config = await readJson(this.configService.configPath);
|
|
878
1033
|
if (Array.isArray(config.disabledPlugins)) {
|
|
879
1034
|
return config.disabledPlugins;
|
|
880
1035
|
}
|
|
@@ -888,14 +1043,14 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
888
1043
|
}
|
|
889
1044
|
async getInstalledScopedModules(requiredPath, scope) {
|
|
890
1045
|
try {
|
|
891
|
-
if ((await
|
|
892
|
-
const scopedModules = await
|
|
1046
|
+
if ((await stat(join(requiredPath, scope))).isDirectory()) {
|
|
1047
|
+
const scopedModules = await readdir(join(requiredPath, scope));
|
|
893
1048
|
return scopedModules
|
|
894
1049
|
.filter(x => x.startsWith('homebridge-'))
|
|
895
1050
|
.map((x) => {
|
|
896
1051
|
return {
|
|
897
|
-
name:
|
|
898
|
-
installPath:
|
|
1052
|
+
name: join(scope, x).split(sep).join('/'),
|
|
1053
|
+
installPath: join(requiredPath, scope, x),
|
|
899
1054
|
path: requiredPath,
|
|
900
1055
|
};
|
|
901
1056
|
});
|
|
@@ -912,7 +1067,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
912
1067
|
async getInstalledModules() {
|
|
913
1068
|
const allModules = [];
|
|
914
1069
|
for (const requiredPath of this.paths) {
|
|
915
|
-
const modules = await
|
|
1070
|
+
const modules = await readdir(requiredPath);
|
|
916
1071
|
for (const module of modules) {
|
|
917
1072
|
try {
|
|
918
1073
|
if (module.charAt(0) === '@') {
|
|
@@ -921,7 +1076,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
921
1076
|
else {
|
|
922
1077
|
allModules.push({
|
|
923
1078
|
name: module,
|
|
924
|
-
installPath:
|
|
1079
|
+
installPath: join(requiredPath, module),
|
|
925
1080
|
path: requiredPath,
|
|
926
1081
|
});
|
|
927
1082
|
}
|
|
@@ -934,16 +1089,16 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
934
1089
|
if (allModules.findIndex(x => x.name === 'homebridge-config-ui-x') === -1) {
|
|
935
1090
|
allModules.push({
|
|
936
1091
|
name: 'homebridge-config-ui-x',
|
|
937
|
-
installPath:
|
|
938
|
-
path:
|
|
1092
|
+
installPath: process.env.UIX_BASE_PATH,
|
|
1093
|
+
path: dirname(process.env.UIX_BASE_PATH),
|
|
939
1094
|
});
|
|
940
1095
|
}
|
|
941
1096
|
if (allModules.findIndex(x => x.name === 'homebridge') === -1) {
|
|
942
|
-
if (
|
|
1097
|
+
if (existsSync(join(process.env.UIX_BASE_PATH, '..', 'homebridge'))) {
|
|
943
1098
|
allModules.push({
|
|
944
1099
|
name: 'homebridge',
|
|
945
|
-
installPath:
|
|
946
|
-
path:
|
|
1100
|
+
installPath: join(process.env.UIX_BASE_PATH, '..', 'homebridge'),
|
|
1101
|
+
path: dirname(join(process.env.UIX_BASE_PATH, '..', 'homebridge')),
|
|
947
1102
|
});
|
|
948
1103
|
}
|
|
949
1104
|
}
|
|
@@ -953,12 +1108,12 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
953
1108
|
return (name.charAt(0) === '@' && name.split('/').length > 0 && name.split('/')[1].indexOf('homebridge-') === 0);
|
|
954
1109
|
}
|
|
955
1110
|
getNpmPath() {
|
|
956
|
-
if (
|
|
1111
|
+
if (platform() === 'win32') {
|
|
957
1112
|
const windowsNpmPath = [
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
].filter(
|
|
1113
|
+
join(process.env.APPDATA, 'npm/npm.cmd'),
|
|
1114
|
+
join(process.env.ProgramFiles, 'nodejs/npm.cmd'),
|
|
1115
|
+
join(process.env.NVM_SYMLINK || `${process.env.ProgramFiles}/nodejs`, 'npm.cmd'),
|
|
1116
|
+
].filter(existsSync);
|
|
962
1117
|
if (windowsNpmPath.length) {
|
|
963
1118
|
return [windowsNpmPath[0]];
|
|
964
1119
|
}
|
|
@@ -981,33 +1136,33 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
981
1136
|
}
|
|
982
1137
|
else {
|
|
983
1138
|
paths = paths.concat(require.main?.paths || []);
|
|
984
|
-
if (
|
|
985
|
-
paths =
|
|
1139
|
+
if (process.env.NODE_PATH) {
|
|
1140
|
+
paths = process.env.NODE_PATH.split(delimiter).filter(p => !!p).concat(paths);
|
|
986
1141
|
}
|
|
987
1142
|
else {
|
|
988
|
-
if ((
|
|
1143
|
+
if ((platform() !== 'win32')) {
|
|
989
1144
|
paths.push('/usr/local/lib/node_modules');
|
|
990
1145
|
paths.push('/usr/lib/node_modules');
|
|
991
1146
|
}
|
|
992
1147
|
paths.push(...this.getNpmPrefixToSearchPaths());
|
|
993
1148
|
}
|
|
994
|
-
paths = paths.filter(x => x !==
|
|
1149
|
+
paths = paths.filter(x => x !== join(process.env.UIX_BASE_PATH, 'node_modules'));
|
|
995
1150
|
}
|
|
996
|
-
return
|
|
997
|
-
return
|
|
1151
|
+
return uniq(paths).filter((requiredPath) => {
|
|
1152
|
+
return existsSync(requiredPath);
|
|
998
1153
|
});
|
|
999
1154
|
}
|
|
1000
1155
|
getNpmPrefixToSearchPaths() {
|
|
1001
1156
|
const paths = [];
|
|
1002
|
-
if ((
|
|
1003
|
-
paths.push(
|
|
1157
|
+
if ((platform() === 'win32')) {
|
|
1158
|
+
paths.push(join(process.env.APPDATA, 'npm/node_modules'));
|
|
1004
1159
|
}
|
|
1005
1160
|
else {
|
|
1006
|
-
paths.push(
|
|
1161
|
+
paths.push(execSync('/bin/echo -n "$(npm -g prefix)/lib/node_modules"', {
|
|
1007
1162
|
env: Object.assign({
|
|
1008
1163
|
npm_config_loglevel: 'silent',
|
|
1009
1164
|
npm_update_notifier: 'false',
|
|
1010
|
-
},
|
|
1165
|
+
}, process.env),
|
|
1011
1166
|
}).toString('utf8'));
|
|
1012
1167
|
}
|
|
1013
1168
|
return paths;
|
|
@@ -1030,7 +1185,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1030
1185
|
isHbMaintained: this.maintainedPlugins.includes(pkgJson.name),
|
|
1031
1186
|
installedVersion: installPath ? (pkgJson.version || '0.0.1') : null,
|
|
1032
1187
|
globalInstall: (installPath !== this.configService.customPluginPath),
|
|
1033
|
-
settingsSchema: await
|
|
1188
|
+
settingsSchema: await pathExists(resolve(installPath, pkgJson.name, 'config.schema.json')),
|
|
1034
1189
|
engines: pkgJson.engines,
|
|
1035
1190
|
installPath,
|
|
1036
1191
|
};
|
|
@@ -1049,20 +1204,20 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1049
1204
|
const fromCache = this.npmPluginCache.get(plugin.name);
|
|
1050
1205
|
plugin.updateAvailable = false;
|
|
1051
1206
|
plugin.updateTag = null;
|
|
1052
|
-
const pkg = fromCache || (await
|
|
1207
|
+
const pkg = fromCache || (await firstValueFrom(this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(plugin.name).replace(/%40/g, '@')}/latest`))).data;
|
|
1053
1208
|
plugin.latestVersion = pkg.version;
|
|
1054
|
-
plugin.updateAvailable =
|
|
1209
|
+
plugin.updateAvailable = gt(pkg.version, plugin.installedVersion);
|
|
1055
1210
|
plugin.updateEngines = plugin.updateAvailable ? pkg.engines : null;
|
|
1056
1211
|
if (!plugin.updateAvailable) {
|
|
1057
|
-
const pluginVersion =
|
|
1212
|
+
const pluginVersion = parse(plugin.installedVersion);
|
|
1058
1213
|
const installedTag = pluginVersion.prerelease[0]?.toString();
|
|
1059
1214
|
const shouldCheckBetas = (installedTag
|
|
1060
1215
|
&& ['alpha', 'beta', 'test'].includes(installedTag)
|
|
1061
|
-
&&
|
|
1216
|
+
&& gt(plugin.installedVersion, plugin.latestVersion)) || this.configService.ui.plugins?.alwaysShowBetas;
|
|
1062
1217
|
if (shouldCheckBetas) {
|
|
1063
1218
|
const versions = await this.getAvailablePluginVersions(plugin.name);
|
|
1064
1219
|
const targetTag = this.configService.ui.plugins?.alwaysShowBetas && !installedTag ? 'beta' : installedTag;
|
|
1065
|
-
if (versions.tags[targetTag] &&
|
|
1220
|
+
if (versions.tags[targetTag] && gt(versions.tags[targetTag], plugin.installedVersion)) {
|
|
1066
1221
|
plugin.latestVersion = versions.tags[targetTag];
|
|
1067
1222
|
plugin.updateAvailable = true;
|
|
1068
1223
|
plugin.updateEngines = versions.versions?.[plugin.latestVersion]?.engines || null;
|
|
@@ -1096,7 +1251,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1096
1251
|
}
|
|
1097
1252
|
async getNpmModuleLatestVersion(npmModuleName) {
|
|
1098
1253
|
try {
|
|
1099
|
-
const response = await
|
|
1254
|
+
const response = await firstValueFrom(this.httpService.get(`https://registry.npmjs.org/${npmModuleName}/latest`));
|
|
1100
1255
|
return response.data.version;
|
|
1101
1256
|
}
|
|
1102
1257
|
catch (e) {
|
|
@@ -1113,29 +1268,29 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1113
1268
|
else {
|
|
1114
1269
|
let npmInstallPath;
|
|
1115
1270
|
try {
|
|
1116
|
-
npmInstallPath =
|
|
1271
|
+
npmInstallPath = execSync('npm root -g').toString().trim();
|
|
1117
1272
|
}
|
|
1118
1273
|
catch (e) {
|
|
1119
|
-
npmInstallPath =
|
|
1274
|
+
npmInstallPath = resolve(cwd, 'node_modules');
|
|
1120
1275
|
}
|
|
1121
1276
|
try {
|
|
1122
|
-
await
|
|
1277
|
+
await access(npmInstallPath, constants.W_OK);
|
|
1123
1278
|
}
|
|
1124
1279
|
catch (e) {
|
|
1125
|
-
client.emit('stdout',
|
|
1280
|
+
client.emit('stdout', yellow(`The user "${userInfo().username}" does not have write access to the target directory:\n\r\n\r`));
|
|
1126
1281
|
client.emit('stdout', `${npmInstallPath}\n\r\n\r`);
|
|
1127
|
-
client.emit('stdout',
|
|
1128
|
-
client.emit('stdout',
|
|
1129
|
-
client.emit('stdout',
|
|
1282
|
+
client.emit('stdout', yellow('This may cause the operation to fail.\n\r'));
|
|
1283
|
+
client.emit('stdout', yellow('See the docs for details on how to enable sudo mode:\n\r'));
|
|
1284
|
+
client.emit('stdout', yellow('https://github.com/homebridge/homebridge-config-ui-x/wiki/Manual-Configuration#sudo-mode\n\r\n\r'));
|
|
1130
1285
|
}
|
|
1131
1286
|
}
|
|
1132
1287
|
this.logger.log(`Running command ${command.join(' ')}.`);
|
|
1133
|
-
if (!
|
|
1134
|
-
client.emit('stdout',
|
|
1135
|
-
client.emit('stdout',
|
|
1288
|
+
if (!satisfies(process.version, `>=${this.configService.minimumNodeVersion}`)) {
|
|
1289
|
+
client.emit('stdout', yellow(`Node.js v${this.configService.minimumNodeVersion} higher is required for ${this.configService.name}.\n\r`));
|
|
1290
|
+
client.emit('stdout', yellow(`You may experience issues while running on Node.js ${process.version}.\n\r\n\r`));
|
|
1136
1291
|
}
|
|
1137
1292
|
const env = {};
|
|
1138
|
-
Object.assign(env,
|
|
1293
|
+
Object.assign(env, process.env);
|
|
1139
1294
|
Object.assign(env, {
|
|
1140
1295
|
npm_config_global_style: 'true',
|
|
1141
1296
|
npm_config_unsafe_perm: 'true',
|
|
@@ -1144,20 +1299,20 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1144
1299
|
npm_config_foreground_scripts: 'true',
|
|
1145
1300
|
npm_config_loglevel: 'error',
|
|
1146
1301
|
});
|
|
1147
|
-
if (command.includes('-g') &&
|
|
1148
|
-
cwd =
|
|
1302
|
+
if (command.includes('-g') && basename(cwd) === 'lib') {
|
|
1303
|
+
cwd = dirname(cwd);
|
|
1149
1304
|
Object.assign(env, {
|
|
1150
1305
|
npm_config_prefix: cwd,
|
|
1151
1306
|
});
|
|
1152
1307
|
}
|
|
1153
|
-
if (
|
|
1308
|
+
if (platform() === 'win32') {
|
|
1154
1309
|
Object.assign(env, {
|
|
1155
1310
|
npm_config_prefix: cwd,
|
|
1156
1311
|
});
|
|
1157
1312
|
}
|
|
1158
|
-
client.emit('stdout',
|
|
1159
|
-
client.emit('stdout',
|
|
1160
|
-
client.emit('stdout',
|
|
1313
|
+
client.emit('stdout', cyan(`USER: ${userInfo().username}\n\r`));
|
|
1314
|
+
client.emit('stdout', cyan(`DIR: ${cwd}\n\r`));
|
|
1315
|
+
client.emit('stdout', cyan(`CMD: ${command.join(' ')}\n\r\n\r`));
|
|
1161
1316
|
this.installedPluginsCache.del('installed-plugins');
|
|
1162
1317
|
await new Promise((res, rej) => {
|
|
1163
1318
|
const term = this.nodePtyService.spawn(command.shift(), command, {
|
|
@@ -1173,7 +1328,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1173
1328
|
term.onExit(({ exitCode }) => {
|
|
1174
1329
|
if (exitCode === 0) {
|
|
1175
1330
|
clearTimeout(timeoutTimer);
|
|
1176
|
-
client.emit('stdout',
|
|
1331
|
+
client.emit('stdout', green('\n\rOperation succeeded!.\n\r'));
|
|
1177
1332
|
res(null);
|
|
1178
1333
|
}
|
|
1179
1334
|
else {
|
|
@@ -1190,10 +1345,10 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1190
1345
|
if (!this.configService.customPluginPath) {
|
|
1191
1346
|
return;
|
|
1192
1347
|
}
|
|
1193
|
-
if (!await
|
|
1348
|
+
if (!await pathExists(this.configService.customPluginPath)) {
|
|
1194
1349
|
this.logger.warn(`Custom plugin directory was removed, re-creating ${this.configService.customPluginPath}.`);
|
|
1195
1350
|
try {
|
|
1196
|
-
await
|
|
1351
|
+
await ensureDir(this.configService.customPluginPath);
|
|
1197
1352
|
}
|
|
1198
1353
|
catch (e) {
|
|
1199
1354
|
this.logger.error(`Failed to re-create custom plugin directory as ${e.message}.`);
|
|
@@ -1204,10 +1359,10 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1204
1359
|
if (!this.configService.customPluginPath) {
|
|
1205
1360
|
return;
|
|
1206
1361
|
}
|
|
1207
|
-
const offendingPath =
|
|
1362
|
+
const offendingPath = resolve(this.configService.customPluginPath, '@eaDir');
|
|
1208
1363
|
try {
|
|
1209
|
-
if (!await
|
|
1210
|
-
await
|
|
1364
|
+
if (!await pathExists(offendingPath)) {
|
|
1365
|
+
await remove(offendingPath);
|
|
1211
1366
|
}
|
|
1212
1367
|
}
|
|
1213
1368
|
catch (e) {
|
|
@@ -1220,7 +1375,8 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1220
1375
|
command.unshift('sudo', '-E', '-n');
|
|
1221
1376
|
}
|
|
1222
1377
|
return new Promise((res) => {
|
|
1223
|
-
const
|
|
1378
|
+
const fullCommand = command.join(' ');
|
|
1379
|
+
const child = spawn(fullCommand, { shell: true });
|
|
1224
1380
|
child.on('exit', (code) => {
|
|
1225
1381
|
this.logger.log(`Executed npm cache clear command with exit code ${code}.`);
|
|
1226
1382
|
res(null);
|
|
@@ -1232,7 +1388,7 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1232
1388
|
async loadPluginList() {
|
|
1233
1389
|
clearTimeout(this.pluginListRetryTimeout);
|
|
1234
1390
|
try {
|
|
1235
|
-
const pluginList = (await
|
|
1391
|
+
const pluginList = (await firstValueFrom(this.httpService.get(this.pluginListFile, {
|
|
1236
1392
|
httpsAgent: null,
|
|
1237
1393
|
})));
|
|
1238
1394
|
const pluginListData = pluginList.data;
|
|
@@ -1282,13 +1438,20 @@ let PluginsService = PluginsService_1 = class PluginsService {
|
|
|
1282
1438
|
}
|
|
1283
1439
|
}
|
|
1284
1440
|
};
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
(
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1441
|
+
PluginsService = PluginsService_1 = __decorate([
|
|
1442
|
+
Injectable(),
|
|
1443
|
+
__param(0, Inject(HttpService)),
|
|
1444
|
+
__param(1, Inject(NodePtyService)),
|
|
1445
|
+
__param(2, Inject(Logger)),
|
|
1446
|
+
__param(3, Inject(ConfigService)),
|
|
1447
|
+
__param(4, Inject(HomebridgeIpcService)),
|
|
1448
|
+
__param(5, Inject(ChildBridgesService)),
|
|
1449
|
+
__metadata("design:paramtypes", [HttpService,
|
|
1450
|
+
NodePtyService,
|
|
1451
|
+
Logger,
|
|
1452
|
+
ConfigService,
|
|
1453
|
+
HomebridgeIpcService,
|
|
1454
|
+
ChildBridgesService])
|
|
1293
1455
|
], PluginsService);
|
|
1456
|
+
export { PluginsService };
|
|
1294
1457
|
//# sourceMappingURL=plugins.service.js.map
|