diff --git a/acct-group/node-red/metadata.xml b/acct-group/node-red/metadata.xml
new file mode 100644
index 000000000..b49da09df
--- /dev/null
+++ b/acct-group/node-red/metadata.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ web@inode64.com
+ Fco. Javier Félix
+
+
+ proxy-maint@gentoo.org
+ Proxy Maintainers
+
+
diff --git a/acct-group/node-red/node-red-0.ebuild b/acct-group/node-red/node-red-0.ebuild
new file mode 100644
index 000000000..13b09bf8b
--- /dev/null
+++ b/acct-group/node-red/node-red-0.ebuild
@@ -0,0 +1,8 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+inherit acct-group
+
+ACCT_GROUP_ID=565
diff --git a/acct-group/zigbee2mqtt/metadata.xml b/acct-group/zigbee2mqtt/metadata.xml
new file mode 100644
index 000000000..b49da09df
--- /dev/null
+++ b/acct-group/zigbee2mqtt/metadata.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ web@inode64.com
+ Fco. Javier Félix
+
+
+ proxy-maint@gentoo.org
+ Proxy Maintainers
+
+
diff --git a/acct-group/zigbee2mqtt/zigbee2mqtt-0.ebuild b/acct-group/zigbee2mqtt/zigbee2mqtt-0.ebuild
new file mode 100644
index 000000000..6078f4c61
--- /dev/null
+++ b/acct-group/zigbee2mqtt/zigbee2mqtt-0.ebuild
@@ -0,0 +1,8 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+inherit acct-group
+
+ACCT_GROUP_ID=313
diff --git a/acct-user/node-red/metadata.xml b/acct-user/node-red/metadata.xml
new file mode 100644
index 000000000..b49da09df
--- /dev/null
+++ b/acct-user/node-red/metadata.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ web@inode64.com
+ Fco. Javier Félix
+
+
+ proxy-maint@gentoo.org
+ Proxy Maintainers
+
+
diff --git a/acct-user/node-red/node-red-0.ebuild b/acct-user/node-red/node-red-0.ebuild
new file mode 100644
index 000000000..10637f166
--- /dev/null
+++ b/acct-user/node-red/node-red-0.ebuild
@@ -0,0 +1,13 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+inherit acct-user
+
+DESCRIPTION="A user for node-red"
+ACCT_USER_ID=313
+ACCT_USER_HOME=/var/lib/node-red
+ACCT_USER_GROUPS=( node-red )
+
+acct-user_add_deps
diff --git a/acct-user/zigbee2mqtt/metadata.xml b/acct-user/zigbee2mqtt/metadata.xml
new file mode 100644
index 000000000..b49da09df
--- /dev/null
+++ b/acct-user/zigbee2mqtt/metadata.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ web@inode64.com
+ Fco. Javier Félix
+
+
+ proxy-maint@gentoo.org
+ Proxy Maintainers
+
+
diff --git a/acct-user/zigbee2mqtt/zigbee2mqtt-0-r2.ebuild b/acct-user/zigbee2mqtt/zigbee2mqtt-0-r2.ebuild
new file mode 100644
index 000000000..9764943d1
--- /dev/null
+++ b/acct-user/zigbee2mqtt/zigbee2mqtt-0-r2.ebuild
@@ -0,0 +1,13 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+inherit acct-user
+
+DESCRIPTION="A user for zigbee2mqtt"
+ACCT_USER_ID=313
+ACCT_USER_HOME=/var/lib/zigbee2mqtt
+ACCT_USER_GROUPS=( zigbee2mqtt dialout )
+
+acct-user_add_deps
diff --git a/app-misc/node-red/Manifest b/app-misc/node-red/Manifest
new file mode 100644
index 000000000..c95679350
--- /dev/null
+++ b/app-misc/node-red/Manifest
@@ -0,0 +1,2 @@
+DIST node-red-3.0.2-node_modules.tar.xz 11665624 BLAKE2B 828fe99506d7c0393beac747ca3f1047582fe006a53c1dd8b864ae73709bb9dc767a5fefe40205d6bfd6551fe1cf3b9cf2f565fa5abf01ef4182d5e43864e1f0 SHA512 823d14d07319d1d8cb361dd0dd014444d8e5d8116021981378b33ee9c19d79f9b3ab106c23cd0731d52b23d3ff862e7bb37910858621a84560015794275b12c1
+DIST node-red-3.0.2.tar.gz 6515723 BLAKE2B a205de81e26913baf772e588f38b8eaae6dca8b1c67f2f7ee2717833dc94666ab5d8d6e8433e87e81a7caa1b659d57144a46cda86626787cdeb3f5ec010d7309 SHA512 5828ce643a9b119ac95e22947f5fd7db84c6a5e288d1bc4c49504cd7ca478ff950eadce310b87ccabecb54b43c016ba11c2ee31c1a2b411f70ff0f514915a325
diff --git a/app-misc/node-red/files/node-red b/app-misc/node-red/files/node-red
new file mode 100644
index 000000000..ad04aed41
--- /dev/null
+++ b/app-misc/node-red/files/node-red
@@ -0,0 +1,17 @@
+#!/sbin/openrc-run
+
+depend() {
+ after mosquitto
+}
+
+start() {
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --user node-red:node-red --chdir /usr/lib64/node_modules/node-red/packages/node_modules/node-red/ --exec /usr/bin/npm --background --make-pidfile --pidfile /run/${SVCNAME}.pid -- start
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --quiet --retry 10 --pidfile /run/${SVCNAME}.pid
+ eend $?
+}
diff --git a/app-misc/node-red/files/node-red.conf b/app-misc/node-red/files/node-red.conf
new file mode 100644
index 000000000..7b27bbbb9
--- /dev/null
+++ b/app-misc/node-red/files/node-red.conf
@@ -0,0 +1 @@
+d /var/lib/node-red 0750 node-red node-red
diff --git a/app-misc/node-red/files/node-red.service b/app-misc/node-red/files/node-red.service
new file mode 100644
index 000000000..7ea89ca98
--- /dev/null
+++ b/app-misc/node-red/files/node-red.service
@@ -0,0 +1,42 @@
+[Unit]
+Description=node-red
+After=network.target
+After=mosquitto.service
+
+[Service]
+ExecStart=npm start
+WorkingDirectory=/usr/lib64/node_modules/node-red/packages/node_modules/node-red/
+StandardOutput=inherit
+StandardError=inherit
+Restart=always
+User=node-red
+
+CapabilityBoundingSet=
+NoNewPrivileges=true
+RemoveIPC=true
+LockPersonality=true
+
+ProtectControlGroups=true
+ProtectKernelTunables=true
+ProtectKernelModules=true
+ProtectKernelLogs=true
+ProtectHostname=true
+ProtectProc=noaccess
+ProtectClock=yes
+DeviceAllow=char-* rw
+
+RestrictRealtime=true
+RestrictSUIDSGID=true
+RestrictNamespaces=true
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+
+ProtectSystem=strict
+ProtectHome=true
+PrivateTmp=true
+ReadWritePaths=/var/lib/node-red
+
+SystemCallArchitectures=native
+SystemCallFilter=@system-service @pkey
+
+[Install]
+WantedBy=multi-user.target
diff --git a/app-misc/node-red/metadata.xml b/app-misc/node-red/metadata.xml
new file mode 100644
index 000000000..8e3206452
--- /dev/null
+++ b/app-misc/node-red/metadata.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ web@inode64.com
+ Fco. Javier Félix
+
+
+ proxy-maint@gentoo.org
+ Proxy Maintainers
+
+
+ node-red/node-red
+
+
diff --git a/app-misc/node-red/node-red-3.0.2.ebuild b/app-misc/node-red/node-red-3.0.2.ebuild
new file mode 100644
index 000000000..194644842
--- /dev/null
+++ b/app-misc/node-red/node-red-3.0.2.ebuild
@@ -0,0 +1,49 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+inherit nodejs nodejs-pack systemd tmpfiles
+
+DESCRIPTION="A visual tool for wiring the Internet of Things."
+HOMEPAGE="https://nodered.org"
+SRC_URI="https://github.com/${PN}/${PN}/archive/refs/tags/${PV}.tar.gz -> ${P}.tar.gz
+ https://raw.githubusercontent.com/inode64/inode64-overlay/main/dist/${P}-node_modules.tar.xz"
+
+LICENSE="Apache-2.0"
+SLOT="0"
+KEYWORDS="~amd64"
+
+RDEPEND="
+ acct-group/node-red
+ acct-user/node-red
+"
+
+NODEJS_EXTRA_FILES="packages"
+
+src_prepare() {
+ default
+
+ # TODO: remove bcrypt fail to compile
+ rm -rf node_modules/bcrypt || die
+}
+
+src_install() {
+ # Remove jsdoc-nr-template, prune use git to get the version
+ rm -rf node_modules/jsdoc-nr-template/ || die
+ sed -i -e '/jsdoc-nr-template/d' package.json || die
+
+ nodejs_docs
+
+ enpm_clean
+ enpm_install
+
+ dotmpfiles "${FILESDIR}"/node-red.conf
+
+ doinitd "${FILESDIR}"/${PN}
+ systemd_dounit "${FILESDIR}/${PN}.service"
+}
+
+pkg_postinst() {
+ tmpfiles_process node-red.conf
+}
diff --git a/app-misc/zigbee2mqtt/Manifest b/app-misc/zigbee2mqtt/Manifest
new file mode 100644
index 000000000..6a3d0e94a
--- /dev/null
+++ b/app-misc/zigbee2mqtt/Manifest
@@ -0,0 +1,2 @@
+DIST zigbee2mqtt-1.30.1-node_modules.tar.xz 18782028 BLAKE2B ee85f5de70a6913b164c73420a5ff01761d5ed3e417951e57f391234e66cd5de76dc459fda84452e1615c544f064d89d156bb580137503a45237b4aae4e23a0b SHA512 d4454ef828c66974d1210b7cc1df7526e3e324addc4e420de13314a13070132e3b7958bf2e8fdac50648ed21f06340f5335fc5b947ee1815dea3035f38954876
+DIST zigbee2mqtt-1.30.1.tar.gz 483028 BLAKE2B 9c297c85a08ef911ad13b2722adecda6e01f0c5689a5225e3e4b0998c6a6626fe0ded2d64df0479c72971fc5f92f79cb65bdc3f8ecd1583b78d94168de1fcdba SHA512 b38accbaea044c0e5b28a4cef0652d90d7691ca936e82bdd82b39d8f77719ac750c067dcb58b9a9d2251dd821e81ed62eed8bbab3c232f516a7a6247fa575d58
diff --git a/app-misc/zigbee2mqtt/files/zigbee2mqtt b/app-misc/zigbee2mqtt/files/zigbee2mqtt
new file mode 100644
index 000000000..a4d8f7565
--- /dev/null
+++ b/app-misc/zigbee2mqtt/files/zigbee2mqtt
@@ -0,0 +1,24 @@
+#!/sbin/openrc-run
+
+depend() {
+ need mosquitto
+}
+
+checkconfig() {
+ if [ ! -f /var/lib/${SVCNAME}/configuration.yaml ] ; then
+ eerror "No /var/lib/${SVCNAME}/configuration.yaml file exists!"
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --user zigbee2mqtt:zigbee2mqtt --env ZIGBEE2MQTT_DATA=/var/lib/${SVCNAME} --chdir /usr/lib64/node_modules/zigbee2mqtt --exec /usr/bin/npm --background --make-pidfile --pidfile /run/${SVCNAME}.pid -- start
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --quiet --retry 10 --pidfile /run/${SVCNAME}.pid
+ eend $?
+}
diff --git a/app-misc/zigbee2mqtt/files/zigbee2mqtt.conf b/app-misc/zigbee2mqtt/files/zigbee2mqtt.conf
new file mode 100644
index 000000000..35e843658
--- /dev/null
+++ b/app-misc/zigbee2mqtt/files/zigbee2mqtt.conf
@@ -0,0 +1,3 @@
+d /var/lib/zigbee2mqtt 0750 zigbee2mqtt zigbee2mqtt
+f /var/lib/zigbee2mqtt//configuration.yaml 0640 zigbee2mqtt zigbee2mqtt
+d /var/log/zigbee2mqtt 0750 zigbee2mqtt zigbee2mqtt
diff --git a/app-misc/zigbee2mqtt/files/zigbee2mqtt.service b/app-misc/zigbee2mqtt/files/zigbee2mqtt.service
new file mode 100644
index 000000000..8b96b9035
--- /dev/null
+++ b/app-misc/zigbee2mqtt/files/zigbee2mqtt.service
@@ -0,0 +1,43 @@
+[Unit]
+Description=zigbee2mqtt
+After=network.target
+Wants=mosquitto.service
+
+[Service]
+ExecStart=npm start
+WorkingDirectory=/usr/lib64/node_modules/zigbee2mqtt
+Environment=ZIGBEE2MQTT_DATA=/var/lib/zigbee2mqtt
+StandardOutput=inherit
+StandardError=inherit
+Restart=always
+User=zigbee2mqtt
+
+CapabilityBoundingSet=
+NoNewPrivileges=true
+RemoveIPC=true
+LockPersonality=true
+
+ProtectControlGroups=true
+ProtectKernelTunables=true
+ProtectKernelModules=true
+ProtectKernelLogs=true
+ProtectHostname=true
+ProtectProc=noaccess
+ProtectClock=yes
+DeviceAllow=char-* rw
+
+RestrictRealtime=true
+RestrictSUIDSGID=true
+RestrictNamespaces=true
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+
+ProtectSystem=strict
+ProtectHome=true
+PrivateTmp=true
+ReadWritePaths=/var/lib/zigbee2mqtt
+
+SystemCallArchitectures=native
+SystemCallFilter=@system-service @pkey
+
+[Install]
+WantedBy=multi-user.target
diff --git a/app-misc/zigbee2mqtt/metadata.xml b/app-misc/zigbee2mqtt/metadata.xml
new file mode 100644
index 000000000..189f80caa
--- /dev/null
+++ b/app-misc/zigbee2mqtt/metadata.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ web@inode64.com
+ Fco. Javier Félix
+
+
+ proxy-maint@gentoo.org
+ Proxy Maintainers
+
+
+ Koenkk/zigbee2mqtt
+
+
diff --git a/app-misc/zigbee2mqtt/zigbee2mqtt-1.30.1.ebuild b/app-misc/zigbee2mqtt/zigbee2mqtt-1.30.1.ebuild
new file mode 100644
index 000000000..c502b383b
--- /dev/null
+++ b/app-misc/zigbee2mqtt/zigbee2mqtt-1.30.1.ebuild
@@ -0,0 +1,60 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+if [[ ${PV} == *9999* ]]; then
+ EGIT_REPO_URI="https://github.com/Koenkk/zigbee2mqtt"
+ EGIT_BRANCH="dev"
+ inherit git-r3
+else
+ SRC_URI="https://github.com/Koenkk/zigbee2mqtt/archive/${PV}.tar.gz -> ${P}.tar.gz
+ https://raw.githubusercontent.com/inode64/inode64-overlay/main/dist/${P}-node_modules.tar.xz"
+fi
+
+inherit nodejs nodejs-pack systemd tmpfiles
+
+DESCRIPTION="It bridges events and allows you to control your Zigbee devices via MQTT"
+HOMEPAGE="https://www.zigbee2mqtt.io/"
+COMMIT="eb878d3d8ee47f77e27c771452e2d2c77ca83bb5"
+
+LICENSE="GPL-3"
+SLOT="0"
+KEYWORDS="~amd64"
+
+RDEPEND="
+ acct-group/zigbee2mqtt
+ acct-user/zigbee2mqtt
+ app-misc/mosquitto
+"
+
+NODEJS_EXTRA_FILES="scripts"
+
+src_install() {
+ echo "${COMMIT}" > dist/.hash
+
+ echo -e "\nadvanced:" >>data/configuration.yaml
+ echo -e " network_key: GENERATE" >>data/configuration.yaml
+ echo -e " pan_id: GENERATE" >>data/configuration.yaml
+ echo -e " log_directory: /var/log/${PN}" >>data/configuration.yaml
+
+ enpm_clean
+ enpm_install
+
+ keepdir /var/log/${PN}
+
+ insinto /var/lib/${PN}
+ doins data/configuration.yaml
+
+ dotmpfiles "${FILESDIR}"/zigbee2mqtt.conf
+
+ doinitd "${FILESDIR}"/${PN}
+ systemd_dounit "${FILESDIR}/${PN}.service"
+
+ dodir /etc/env.d
+ echo 'CONFIG_PROTECT="/var/lib/${PN}"' >>"${ED}"/etc/env.d/90${PN} || die
+}
+
+pkg_postinst() {
+ tmpfiles_process zigbee2mqtt.conf
+}
diff --git a/eclass/nodejs-mod.eclass b/eclass/nodejs-mod.eclass
new file mode 100644
index 000000000..2ecb6c9f0
--- /dev/null
+++ b/eclass/nodejs-mod.eclass
@@ -0,0 +1,109 @@
+# Copyright 2019-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: nodejs-mod.eclass
+# @MAINTAINER:
+# Fco. Javier Félix
+# @AUTHOR:
+# Fco. Javier Félix
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: An eclass for build NodeJS projects
+# @DESCRIPTION:
+# An eclass providing functions to build NodeJS projects
+#
+# Changelog:
+# Initial version from:
+# https://github.com/gentoo/gentoo/pull/930/files
+# https://github.com/samuelbernardo/ssnb-overlay/blob/master/eclass/npm.eclass
+# https://github.com/gentoo-mirror/lanodanOverlay/blob/master/eclass/nodejs.eclass
+# https://github.com/Tatsh/tatsh-overlay/blob/master/eclass/yarn.eclass
+
+#
+# Build package for node_modules:
+# npm:
+# npm install --audit false --color false --foreground-scripts --progress false --verbose --ignore-scripts
+#
+# yarn:
+# yarn install --color false --foreground-scripts --progress false --verbose --ignore-scripts
+#
+# Create archive in tar:
+# tar --create --auto-compress --file foo-1-node_modules.tar.xz foo-1/node_modules/
+
+case ${EAPI} in
+7 | 8) ;;
+*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ -z ${_NODEJS-MODE_ECLASS} ]]; then
+_NODEJS-MODE_ECLASS=1
+
+inherit nodejs
+
+if has nodejs-pack ${INHERITED}; then
+ eerror "nodejs-mod and nodejs-pack eclass are incompatible"
+fi
+
+EXPORT_FUNCTIONS src_compile src_install src_prepare src_test
+
+RDEPEND+=" net-libs/nodejs:="
+
+# @FUNCTION: nodejs-pack_src_prepare
+# @DESCRIPTION:
+# Nodejs preparation phase
+nodejs-pack_src_prepare() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if [[ ! -e package.json ]]; then
+ eerror "Unable to locate package.json"
+ eerror "Consider not inheriting the nodejs eclass."
+ die "FATAL: Unable to find package.json"
+ fi
+
+ default_src_prepare
+}
+
+# @FUNCTION: nodejs-pack_src_compile
+# @DESCRIPTION:
+# General function for compiling a nodejs module
+nodejs-pack_src_compile() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if [[ -d node_modules ]]; then
+ einfo "Compile native addon modules"
+ find node_modules/ -name binding.gyp -exec dirname {} \; | while read -r dir; do
+ pushd "${dir}" >/dev/null || die
+ # shellcheck disable=SC2046
+ npm_config_nodedir=/usr/ /usr/$(get_libdir)/node_modules/npm/bin/node-gyp-bin/node-gyp rebuild --verbose
+ popd >/dev/null || die
+ done
+ fi
+
+ if nodejs_has_build; then
+ einfo "Run build"
+ enpm run build || die "build failed"
+ fi
+}
+
+# @FUNCTION: nodejs-pack_src_test
+# @DESCRIPTION:
+# General function for testing a nodejs module
+nodejs-pack_src_test() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if nodejs_has_test; then
+ enpm run test || die "test failed"
+ fi
+}
+
+# @FUNCTION: nodejs_src_install
+# @DESCRIPTION:
+# Function for installing the package
+nodejs-pack_src_install() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ nodejs_docs
+
+ enpm_clean
+ enpm_install
+}
+fi
diff --git a/eclass/nodejs-pack.eclass b/eclass/nodejs-pack.eclass
new file mode 100644
index 000000000..19b1a8dca
--- /dev/null
+++ b/eclass/nodejs-pack.eclass
@@ -0,0 +1,81 @@
+# Copyright 2019-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: nodejs-pack.eclass
+# @MAINTAINER:
+# Fco. Javier Félix
+# @AUTHOR:
+# Fco. Javier Félix
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: An eclass for build NodeJS projects
+# @DESCRIPTION:
+# An eclass providing functions to build NodeJS packages
+#
+# Changelog:
+# Initial version from:
+# https://github.com/gentoo/gentoo/pull/930/files
+# https://github.com/samuelbernardo/ssnb-overlay/blob/master/eclass/npm.eclass
+# https://github.com/gentoo-mirror/lanodanOverlay/blob/master/eclass/nodejs.eclass
+# https://github.com/Tatsh/tatsh-overlay/blob/master/eclass/yarn.eclass
+
+
+case ${EAPI} in
+7 | 8) ;;
+*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ -z ${_NODEJS_PACK_ECLASS} ]]; then
+_NODEJS_PACK_ECLASS=1
+
+inherit nodejs
+
+if has nodejs-mod ${INHERITED}; then
+ eerror "nodejs-mod and nodejs-pack eclass are incompatible"
+fi
+
+RDEPEND+=" net-libs/nodejs"
+
+# Upstream does not support stripping go packages
+RESTRICT="test strip"
+
+EXPORT_FUNCTIONS src_compile src_install src_prepare
+
+# @FUNCTION: nodejs-pack_src_prepare
+# @DESCRIPTION:
+# Nodejs preparation phase
+nodejs-pack_src_prepare() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if ! nodejs_has_package && ! test -e package.json ; then
+ eerror "Unable to locate package.json"
+ eerror "Consider not inheriting the nodejs-pack eclass."
+ die "FATAL: Unable to find package.json"
+ fi
+
+ default_src_prepare
+}
+
+# @FUNCTION: nodejs-pack_src_compile
+# @DESCRIPTION:
+# General function for compiling a nodejs module
+nodejs-pack_src_compile() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ einfo "Create pack file"
+ enpm --global pack || die "pack failed"
+}
+
+# @FUNCTION: nodejs-pack_src_install
+# @DESCRIPTION:
+# Function for installing the package
+nodejs-pack_src_install() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ nodejs_docs
+
+ einfo "Install pack files"
+ enpm --prefix "${ED}"/usr --global \
+ install \
+ "$(nodejs_package)-$(nodejs_version).tgz" || die "install failed"
+}
+fi
diff --git a/eclass/nodejs.eclass b/eclass/nodejs.eclass
new file mode 100644
index 000000000..4333b77ee
--- /dev/null
+++ b/eclass/nodejs.eclass
@@ -0,0 +1,304 @@
+# Copyright 2019-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: nodejs.eclass
+# @MAINTAINER:
+# Fco. Javier Félix
+# @AUTHOR:
+# Fco. Javier Félix
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: An eclass for build NodeJS projects
+# @DESCRIPTION:
+# An eclass providing functions to build NodeJS projects
+#
+# Changelog:
+# Initial version from:
+# https://github.com/gentoo/gentoo/pull/930/files
+# https://github.com/samuelbernardo/ssnb-overlay/blob/master/eclass/npm.eclass
+# https://github.com/gentoo-mirror/lanodanOverlay/blob/master/eclass/nodejs.eclass
+# https://github.com/Tatsh/tatsh-overlay/blob/master/eclass/yarn.eclass
+
+#
+# Build package for node_modules:
+# npm:
+# npm install --audit false --color false --foreground-scripts --progress false --verbose --ignore-scripts
+#
+# yarn:
+# yarn install --color false --foreground-scripts --progress false --verbose --ignore-scripts
+#
+# Create archive in tar:
+# tar --create --auto-compress --file foo-1-node_modules.tar.xz foo-1/node_modules/
+
+case ${EAPI} in
+7 | 8) ;;
+*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ -z ${_NODEJS_ECLASS} ]]; then
+_NODEJS_ECLASS=1
+
+# @ECLASS_VARIABLE: NODEJS_MANAGEMENT
+# @PRE_INHERIT
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Specify a package management
+# The default is set to "npm".
+: "${NODEJS_MANAGEMENT:=npm}"
+
+# @ECLASS_VARIABLE: NODEJS_FILES
+# @INTERNAL
+# @DESCRIPTION:
+# Files and directories that usually come in a standard NodeJS/npm module.
+NODEJS_FILES="babel.config.js babel.config.json cli.js dist index.js lib node_modules package.json"
+
+# @ECLASS_VARIABLE: NODEJS_EXTRA_FILES
+# @DESCRIPTION:
+# If additional dist files are present in the NodeJS/npm module that are not
+# listed in NODEJS_FILES, then this is the place to put them in.
+# Can be either files, or directories.
+# Example: NODEJS_EXTRA_FILES="rigger.js modules"
+
+case ${NODEJS_MANAGEMENT} in
+npm)
+ BDEPEND+=" net-libs/nodejs[npm]"
+ ;;
+yarn)
+ BDEPEND+=" sys-apps/yarn"
+ ;;
+*)
+ eerror "Unknown value for \${NODEJS_MANAGEMENT}"
+ die "Value ${NODEJS_MANAGEMENT} is not supported"
+ ;;
+esac
+
+# @FUNCTION: nodejs_version
+# @DESCRIPTION:
+# Returns the package version
+nodejs_version() {
+ node -p "require('./package.json').version"
+}
+
+# @FUNCTION: nodejs_package
+# @DESCRIPTION:
+# Returns the package name
+nodejs_package() {
+ node -p "require('./package.json').name"
+}
+
+# @FUNCTION: nodejs_has_test
+# @DESCRIPTION:
+# Returns true if test script exist
+nodejs_has_test() {
+ node -p "if (require('./package.json').scripts.test === undefined) { process.exit(1) }" &>/dev/null
+}
+
+# @FUNCTION: nodejs_has_build
+# @DESCRIPTION:
+# Returns true if build script exist
+nodejs_has_build() {
+ node -p "if (require('./package.json').scripts.build === undefined) { process.exit(1) }" &>/dev/null
+}
+
+# @FUNCTION: _NODEJS_MODULES
+# @DESCRIPTION:
+# Returns location where to install nodejs
+_NODEJS_MODULES() {
+ # shellcheck disable=SC2046
+ echo /usr/$(get_libdir)/node_modules/$(nodejs_package)
+}
+
+# @FUNCTION: nodejs_has_package
+# @DESCRIPTION:
+# Returns true (0) if is a package
+nodejs_has_package() {
+ [[ -d "${S}"/package ]] || return 1
+}
+
+# @FUNCTION: nodejs_docs
+# @DESCRIPTION:
+# Install docs usually found in NodeJS/NPM packages
+nodejs_docs() {
+ # If docs variable is not empty when install docs usually found in NodeJS/NPM packages
+ [[ ! "${DOCS}" ]] || return
+
+ local f
+
+ for f in README* HISTORY* ChangeLog AUTHORS NEWS TODO CHANGES \
+ THANKS BUGS FAQ CREDITS CHANGELOG* *.md; do
+ if [[ -s "${f}" ]]; then
+ dodoc "${f}"
+ fi
+ done
+}
+
+# @FUNCTION: nodejs_remove_dev
+# @INTERNAL
+# @DESCRIPTION:
+# Remove docs, licenses and development files
+nodejs_remove_dev() {
+ # Remove license files
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*/\(...-\)?license\(-...\|-apache\)?\(\.\(md\|rtf\|txt\|markdown\|bsd\)\)?$' -delete || die
+
+ # Remove documentation files
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*/*.\.md$' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*/\(readme\(.*\)?\|changelog\|roadmap\|security\|release\|contributors\|todo\|authors\)$' -delete || die
+
+ # Remove typscript files
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*\.\(tsx?\|jsx\|map\)$' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -name tsconfig.json -delete || die
+ # shellcheck disable=SC2185
+ find -type f -name docker-compose.yml -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iname CopyrightNotice.txt -delete || die
+
+ # Remove misc files
+ # shellcheck disable=SC2185
+ find -type f -iname '*.musl.node' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*\.\(editorconfig\|bak\|npmignore\|exe\|gitattributes\|ps1\|ds_store\|log\|pyc\)$' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*\.\(travis.yml\|makefile\|jshintrc\|flake8\|mk\|env\|nycrc\|eslint.*\|coveralls.*\)$' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*\.\(jscs.json\|jshintignore\|gitignore\|babelrc.*\|runkit_example.js\|airtap.yml\)$' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iregex '.*\.\(jekyll-metadata\|codeclimate.yml\|prettierrc.yaml\|drone.jsonnet\|mocharc.*\)$' -delete || die
+ # shellcheck disable=SC2185
+ find -type f -iname makefile -delete || die
+ # shellcheck disable=SC2185
+ find -type f -name '*\~' -delete || die
+
+ # shellcheck disable=SC2185
+ find -type d \
+ \( \
+ -iwholename '*.github' -o \
+ -iwholename '*.tscache' -o \
+ -iwholename '*.vscode' -o \
+ -iwholename '*.idea' -o \
+ -iwholename '*.nyc_output' -o \
+ -iwholename '*.deps' -o \
+ -iwholename '*/man' -o \
+ -iwholename '*/test' -o \
+ -iwholename '*/scripts' -o \
+ -iwholename '*/git-hooks' -o \
+ -iwholename '*/prebuilds' -o \
+ -iwholename '*/android-arm' -o \
+ -iwholename '*/android-arm64' -o \
+ -iwholename '*/linux-arm64' -o \
+ -iwholename '*/linux-armvy' -o \
+ -iwholename '*/linux-armv7' -o \
+ -iwholename '*/linux-arm' -o \
+ -iwholename '*/win32-ia32' -o \
+ -iwholename '*/win32-x64' -o \
+ -iwholename '*/darwin-x64' \
+ -iwholename '*/darwin-x64+arm64' \
+ \) \
+ -exec rm -rvf {} +
+}
+
+# @FUNCTION: enpm
+# @DESCRIPTION:
+# Packet manager execution wrapper
+enpm() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local mynpmflags_local mynpmflagstype npmflags
+
+ # Make the array a local variable since <=portage-2.1.6.x does not support
+ # global arrays (see bug #297255). But first make sure it is initialised.
+ [[ -z ${mynpmflags} ]] && declare -a mynpmflags=()
+ mynpmflagstype=$(declare -p mynpmflags 2>&-)
+ if [[ "${mynpmflagstype}" != "declare -a mynpmflags="* ]]; then
+ die "mynpmflags must be declared as array"
+ fi
+
+ mynpmflags_local=("${mynpmflags[@]}")
+
+ npmflags=(
+ --color false
+ --foreground-scripts
+ --offline
+ --progress false
+ --verbose
+ "${mynpmflags_local[@]}"
+ )
+
+ case ${NODEJS_MANAGEMENT} in
+ npm)
+ npmflags+=(
+ --audit false
+ )
+ npm "$@" "${npmflags[@]}"
+ ;;
+ yarn)
+ npmflags+=(
+ --cache-folder "${S}/.cache"
+ )
+ yarn "$@" "${npmflags[@]}"
+ ;;
+ esac
+}
+
+# @FUNCTION: enpm_clean
+# @DESCRIPTION:
+# Delete all unnecessary files
+enpm_clean() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local nodejs_files f
+
+ einfo "Clean files"
+ case ${NODEJS_MANAGEMENT} in
+ npm)
+ enpm prune --omit=dev || die
+ ;;
+ yarn)
+ enpm install production || die
+ # TODO
+ #enpm autoclean --init || die
+ #enpm autoclean --force || die
+ ;;
+ esac
+
+ nodejs_files="${NODEJS_FILES} ${NODEJS_EXTRA_FILES}"
+
+ # Cleanups
+ for f in ${nodejs_files}; do
+ if [[ -d "${S}/${f}" ]]; then
+ pushd "${S}/${f}" >/dev/null || die
+ nodejs_remove_dev
+ popd >/dev/null || die
+ fi
+ done
+}
+
+# @FUNCTION: enpm_install
+# @DESCRIPTION:
+# Install the files and folders necessary for the execution of nodejs
+enpm_install() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local nodejs_files f
+
+ if nodejs_has_package; then
+ einfo "Install pack files"
+ enpm --prefix "${ED}"/usr \
+ install \
+ "$(nodejs_package)-$(nodejs_version).tgz" || die "install failed"
+ fi
+
+ nodejs_files="${NODEJS_FILES} ${NODEJS_EXTRA_FILES} $(nodejs_package).js"
+
+ dodir "$(_NODEJS_MODULES)" || die "Could not create DEST folder"
+
+ for f in ${nodejs_files}; do
+ if [[ -e "${S}/${f}" ]]; then
+ cp -r "${S}/${f}" "${ED}/$(_NODEJS_MODULES)"
+ fi
+ done
+}
+fi