Browse Source

migration to node.js v22.10.0 (LTS)

psy 3 months ago
parent
commit
d9ae63495e
19 changed files with 20807 additions and 21423 deletions
  1. 13 13
      README.md
  2. 6 0
      docs/CHANGELOG.md
  3. 2 2
      docs/install.md
  4. 1 1
      docs/security.md
  5. 20504 21228
      package-lock.json
  6. 70 44
      package.json
  7. 1 1
      scripts/build.sh
  8. 2 1
      src/assets/style.css
  9. 8 2
      src/cli.js
  10. 2 2
      src/http.js
  11. 112 72
      src/index.js
  12. 3 1
      src/models.js
  13. 4 2
      src/server.js
  14. 6 2
      src/ssb/flotilla.js
  15. 1 2
      src/ssb/index.js
  16. 15 9
      src/supports.js
  17. 56 39
      src/updater.js
  18. 0 1
      src/views/index.js
  19. 1 1
      src/views/markdown.js

+ 13 - 13
README.md

@@ -28,17 +28,17 @@ Follow ['INSTALL.md'](docs/install.md) to build and install it on your device.
 
 ## Setup:
 
-Visit ['Settings'](https://solarnethub.com/socialnet/snh#settings_minimal) to learn how to choose your language, set a theme & configure your avatar.
+Visit ['Settings'](https://wiki.solarnethub.com/socialnet/snh#settings_minimal) to learn how to choose your language, set a theme & configure your avatar.
 
 ----------
 
 ## Multiverse:
 
-Join ['PUB: "La Plaza"'](https://solarnethub.com/socialnet/snh-pub) to start to be connected with other interesting projects in the Multiverse.
+Join ['PUB: "La Plaza"'](https://wiki.solarnethub.com/socialnet/snh-pub) to start to be connected with other interesting projects in the Multiverse.
 
   ![SNH](https://solarnethub.com/_media/socialnet/snh-oasis_federation-2.png "SolarNET.HuB")
   
-This allows you to communicate and access content from outside the [project network](https://solarnethub.com/socialnet/overview). 
+This allows you to communicate and access content from outside the [project network](https://wiki.solarnethub.com/socialnet/overview). 
 
   ![SNH](https://solarnethub.com/_media/socialnet/snh-multiverse.png "SolarNET.HuB")
 
@@ -46,7 +46,7 @@ This allows you to communicate and access content from outside the [project netw
 
 ## SNH-Hub:
 
-The public content of the ['PUB: "La Plaza"'](https://solarnethub.com/socialnet/snh-pub) can be visited from outside the [project network](https://solarnethub.com/socialnet/overview), through the [World Wide Web](https://en.wikipedia.org/wiki/World_Wide_Web) (aka [Clearnet](https://en.wikipedia.org/wiki/Clearnet_(networking))).
+The public content of the ['PUB: "La Plaza"'](https://wiki.solarnethub.com/socialnet/snh-pub) can be visited from outside the [project network](https://wiki.solarnethub.com/socialnet/overview), through the [World Wide Web](https://en.wikipedia.org/wiki/World_Wide_Web) (aka [Clearnet](https://en.wikipedia.org/wiki/Clearnet_(networking))).
 
   ![SNH](https://solarnethub.com/_media/socialnet/snh-pub-feed.png "SolarNET.HuB") 
   
@@ -58,13 +58,13 @@ Just visit: https://pub.solarnethub.com/
 
 ## Roadmap:
 
-Review ['Roadmap'](https://solarnethub.com/project/roadmap#the_project_network) to know about some required functionalities that can be implemented.
+Review ['Roadmap'](https://wiki.solarnethub.com/project/roadmap#the_project_network) to know about some required functionalities that can be implemented.
 
 ----------
 
 ## Development:
 
-Check ['Call 4 Hackers'](https://solarnethub.com/community/hackers) for contributing with developments.
+Check ['Call 4 Hackers'](https://wiki.solarnethub.com/community/hackers) for contributing with developments.
 
 ----------
 
@@ -72,10 +72,10 @@ Check ['Call 4 Hackers'](https://solarnethub.com/community/hackers) for contribu
 
  + SNH Website: https://solarnethub.com
  + Kräkens.Lab: https://krakenslab.com
- + Research: https://solarnethub.com/docs/research
- + Code of Conduct: https://solarnethub.com/docs/code_of_conduct
- + The KIT: https://solarnethub.com/kit/overview
- + Ecosystem: https://solarnethub.com/socialnet/ecosystem
- + Project Network: https://solarnethub.com/socialnet/snh#the_project_network
- + Role-playing: https://solarnethub.com/socialnet/roleplaying
- + Warehouse: https://solarnethub.com/stock/submit_request
+ + Research: https://wiki.solarnethub.com/docs/research
+ + Code of Conduct: https://wiki.solarnethub.com/docs/code_of_conduct
+ + The KIT: https://wiki.solarnethub.com/kit/overview
+ + Ecosystem: https://wiki.solarnethub.com/socialnet/ecosystem
+ + Project Network: https://wiki.solarnethub.com/socialnet/snh#the_project_network
+ + Role-playing: https://wiki.solarnethub.com/socialnet/roleplaying
+ + Warehouse: https://wiki.solarnethub.com/stock/submit_request

+ 6 - 0
docs/CHANGELOG.md

@@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file.
 ### Security
 -->
 
+## v0.3.0 - 2024-12-15
+
+### Changed
+
+- Migration to Node.js v22.12.0 (LTS)
+
 ## v0.2.3 - 2022-11-05
 
 ### Added

+ 2 - 2
docs/install.md

@@ -1,6 +1,6 @@
 # Install
 
-This is a guide on how to download the source code for SNH-Oasis so that you can
+This is a guide on how to download the source code for Oasis so that you can
 build and install it on your device.
 
 --------------
@@ -8,7 +8,7 @@ build and install it on your device.
 For a GNU/Linux based system, execute the following steps (from a shell):
 
     sudo apt-get install git curl
-    curl -sL http://deb.nodesource.com/setup_14.x | sudo bash -
+    curl -sL http://deb.nodesource.com/setup_22.x | sudo bash -
     sudo apt-get install -y nodejs
     git clone https://code.03c8.net/KrakensLab/oasis
     cd oasis

+ 1 - 1
docs/security.md

@@ -13,7 +13,7 @@ If everything is working correctly, it's likely that:
 
 It's important to know that this is not a silver bullet:
 
-- Your public messages can be read by anyone on the Secure Scuttlebutt network.
+- Your public messages can be read by anyone on the network.
 - Your IP address can be seen by anyone that peers with you.
 - Your private messages can be read by anyone with access to your private key.
 

File diff suppressed because it is too large
+ 20504 - 21228
package-lock.json


+ 70 - 44
package.json

@@ -1,6 +1,6 @@
 {
   "name": "@krakenslab/oasis",
-  "version": "0.2.9",
+  "version": "0.3.0",
   "description": "SNH-Oasis Project Network GUI",
   "repository": {
     "type": "git",
@@ -15,6 +15,7 @@
   "scripts": {
     "dev": "nodemon --inspect src/index.js --debug --no-open",
     "fix": "common-good fix",
+    "postinstall": "patch-package",
     "prestart": "",
     "start": "npm run start-server && npm run start-client",
     "start-server": "node src/server.js start &",
@@ -25,36 +26,40 @@
   },
   "dependencies": {
     "@fraction/base16-css": "^1.1.0",
-    "@koa/router": "^10.0.0",
+    "@koa/router": "^13.1.0",
+    "abstract-level": "^2.0.1",
     "await-exec": "^0.1.2",
+    "axios": "^1.7.9",
     "broadcast-stream": "^0.2.1",
+    "caller-path": "^4.0.0",
     "debug": "^4.3.1",
-    "env-paths": "^2.2.0",
+    "env-paths": "^2.2.1",
     "epidemic-broadcast-trees": "^9.0.4",
-    "file-type": "^16.0.1",
+    "file-type": "^16.5.4",
     "has-network": "0.0.1",
-    "highlight.js": "^11.0.0",
-    "hyperaxe": "^1.3.0",
-    "ip": "^1.1.5",
-    "is-svg": "^4.2.1",
+    "highlight.js": "11.0.0",
+    "hyperaxe": "^2.0.1",
+    "ip": "https://registry.npmjs.org/neoip/-/neoip-3.0.0.tgz",
+    "is-svg": "^4.4.0",
+    "is-valid-domain": "^0.1.6",
     "koa": "^2.7.0",
-    "koa-body": "^4.1.0",
+    "koa-body": "^6.0.1",
     "koa-mount": "^4.0.0",
     "koa-static": "^5.0.0",
-    "lodash": "^4.17.11",
+    "lodash": "^4.17.21",
     "lodash.shuffle": "^4.2.0",
-    "markdown-it": "^12.0.2",
-    "mdmanifest": "^1.0.8",
-    "minimist": "^1.1.3",
-    "mkdirp": "^1.0.4",
+    "minimist": "^1.2.8",
+    "mkdirp": "^3.0.1",
+    "module-alias": "^2.2.3",
     "multiblob": "^1.13.0",
     "multiserver": "^3.3.1",
     "multiserver-address": "^1.0.1",
-    "muxrpc": "^6.7.3",
+    "muxrpc": "^8.0.0",
     "muxrpc-validation": "^3.0.2",
     "muxrpcli": "^3.1.2",
     "node-iframe": "^1.8.5",
-    "open": "^8.0.1",
+    "non-private-ip": "^2.2.0",
+    "open": "^8.4.2",
     "packet-stream": "^2.0.6",
     "packet-stream-codec": "^1.2.0",
     "piexifjs": "^1.0.4",
@@ -66,11 +71,12 @@
     "pull-paramap": "^1.2.2",
     "pull-pushable": "^2.2.0",
     "pull-sort": "^1.0.2",
-    "pull-stream": "^3.6.12",
-    "request": "^2.88.1",
+    "pull-stream": "^3.7.0",
+    "punycode.js": "^2.3.1",
+    "remark-html": "^16.0.1",
     "require-style": "^1.1.0",
-    "scuttle-poll": "^1.5.1",
-    "secret-stack": "^6.4.1",
+    "scuttle-poll": "^1.0.3",
+    "secret-stack": "^6.3.1",
     "ssb-about": "^2.0.1",
     "ssb-backlinks": "^2.1.1",
     "ssb-blobs": "^2.0.1",
@@ -78,27 +84,27 @@
     "ssb-caps": "^1.0.1",
     "ssb-client": "^4.9.0",
     "ssb-config": "^3.4.4",
-    "ssb-conn": "^6.0.3",
+    "ssb-conn": "6.0.3",
     "ssb-conn-db": "^1.0.5",
     "ssb-conn-hub": "^1.2.0",
     "ssb-conn-query": "^1.2.2",
     "ssb-conn-staging": "^1.0.0",
     "ssb-db": "^20.3.0",
-    "ssb-db2": "^6.1.1",
+    "ssb-db2": "^8.1.0",
     "ssb-device-address": "^1.1.6",
-    "ssb-ebt": "^8.1.2",
+    "ssb-ebt": "^9.0.0",
     "ssb-friend-pub": "^1.0.7",
     "ssb-friends": "^5.0.0",
     "ssb-gossip": "^1.1.1",
-    "ssb-invite": "^3.0.1",
+    "ssb-invite": "^3.0.3",
     "ssb-invite-client": "^1.3.3",
     "ssb-keys": "^8.0.0",
     "ssb-lan": "^1.0.0",
-    "ssb-legacy-conn": "^2.0.0",
+    "ssb-legacy-conn": "^1.0.17",
     "ssb-links": "^3.0.10",
     "ssb-local": "^1.0.0",
     "ssb-logging": "^1.0.0",
-    "ssb-markdown": "^6.0.7",
+    "ssb-markdown": "^3.6.0",
     "ssb-master": "^1.0.3",
     "ssb-meme": "^1.1.0",
     "ssb-mentions": "^0.5.2",
@@ -111,45 +117,64 @@
     "ssb-private1": "^1.0.1",
     "ssb-query": "^2.4.5",
     "ssb-ref": "^2.16.0",
-    "ssb-replication-scheduler": "^2.0.2",
-    "ssb-room": "^1.3.0",
+    "ssb-replication-scheduler": "^3.0.0",
+    "ssb-room": "^0.0.10",
     "ssb-search": "^1.3.0",
     "ssb-search2": "^2.1.3",
-    "ssb-server": "^15.3.0",
+    "ssb-server": "file:./packages/ssb-server",
     "ssb-tangle": "^1.0.1",
     "ssb-thread-schema": "^1.1.1",
     "ssb-threads": "^10.0.4",
-    "ssb-tribes": "^3.1.1",
+    "ssb-tribes": "^4.0.1",
     "ssb-tunnel": "^2.0.0",
     "ssb-unix-socket": "^1.0.0",
     "ssb-ws": "^6.2.3",
-    "yargs": "^17.0.0"
+    "yargs": "^17.7.2"
+  },
+  "overrides": {
+    "caller-path": "^4.0.0",
+    "is-valid-domain": "^0.1.6",
+    "highlight.js": "11.0.0",
+    "@babel/traverse": "7.23.2",
+    "trim": "0.0.3",
+    "json5": "2.2.2",
+    "debug": "^4.3.1",
+    "postcss": "8.4.31",
+    "punycode": "2.3.1",
+    "ejs": "3.1.10",
+    "babel-traverse": "7.0.0-alpha.1",
+    "ssb-conn": "6.0.3",
+    "ssb-ref": "^2.16.0",
+    "secret-stack": "^6.3.1",
+    "ip": "https://registry.npmjs.org/neoip/-/neoip-3.0.0.tgz",
+    "lodash.set": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
   },
   "devDependencies": {
     "@types/debug": "^4.1.5",
     "@types/koa": "^2.11.3",
-    "@types/koa__router": "^8.0.2",
+    "@types/koa__router": "^12.0.4",
     "@types/koa-mount": "^4.0.0",
     "@types/koa-static": "^4.0.1",
     "@types/lodash": "^4.14.150",
-    "@types/markdown-it": "^12.0.0",
-    "@types/mkdirp": "^1.0.0",
+    "@types/mkdirp": "^2.0.0",
     "@types/nodemon": "^1.19.0",
     "@types/pull-stream": "^3.6.0",
-    "@types/sharp": "^0.28.0",
-    "@types/supertest": "^2.0.9",
+    "@types/sharp": "^0.32.0",
+    "@types/supertest": "^6.0.2",
     "@types/yargs": "^17.0.2",
     "changelog-version": "^2.0.0",
     "common-good": "^4.0.3",
-    "husky": "^7.0.1",
-    "nodemon": "^2.0.3",
-    "stylelint-config-recommended": "^5.0.0",
-    "supertest": "^6.0.1",
-    "tap": "^14.10.7"
+    "husky": "^9.1.7",
+    "nodemon": "^3.1.7",
+    "npm-force-resolutions": "^0.0.10",
+    "patch-package": "^8.0.0",
+    "stylelint-config-recommended": "^14.0.1",
+    "supertest": "^7.0.0",
+    "tap": "^21.0.1"
   },
   "optionalDependencies": {
-    "sharp": "^0.31.1",
-    "fsevents": "^2.3.2"
+    "fsevents": "^2.3.2",
+    "sharp": "^0.33.5"
   },
   "bugs": {
     "url": "https://code.03c8.net/KrakensLab/snh-oasis/issues"
@@ -161,5 +186,6 @@
   "keywords": [],
   "engines": {
     "node": "^10.0.0 || >=12.0.0"
-  }
+  },
+  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
 }

+ 1 - 1
scripts/build.sh

@@ -3,7 +3,7 @@
 set -ex
 
 BASEDIR="$(dirname "$0")"
-TARGET_VERSION="0.1.2"
+TARGET_VERSION="22.12.0"
 
 cd "$BASEDIR/.."
 

+ 2 - 1
src/assets/style.css

@@ -480,7 +480,8 @@ nav > ul {
   justify-content: space-between;
   margin: 0;
   margin-right: 30px;
-  #padding: 0;
+  margin-left: 30px;
+  padding: 0;
 }
 
 nav > ul > li {

+ 8 - 2
src/cli.js

@@ -1,14 +1,18 @@
 "use strict";
 
 const yargs = require("yargs");
+const { hideBin } = require("yargs/helpers"); // Helper to parse arguments
 const _ = require("lodash");
 
+const moduleAlias = require('module-alias');
+moduleAlias.addAlias('punycode', 'punycode/');
+
 /**
  * @param {object} presets
  * @param {string} defaultConfigFile
  */
-module.exports = (presets, defaultConfigFile) =>
-  yargs
+const cli = (presets, defaultConfigFile) =>
+  yargs(hideBin(process.argv))
     .scriptName("oasis")
     .env("OASIS")
     .help("h")
@@ -59,3 +63,5 @@ module.exports = (presets, defaultConfigFile) =>
       type: "string",
     })
     .epilog(`The defaults can be configured in ${defaultConfigFile}.`).argv;
+
+module.exports = { cli };

+ 2 - 2
src/http.js

@@ -1,6 +1,6 @@
 const Koa = require("koa");
 const koaStatic = require("koa-static");
-const path = require("path");
+const { join } = require("path");
 const mount = require("koa-mount");
 
 /**
@@ -10,7 +10,7 @@ const mount = require("koa-mount");
  */
 module.exports = ({ host, port, middleware, allowHost }) => {
   const assets = new Koa();
-  assets.use(koaStatic(path.join(__dirname, "assets")));
+  assets.use(koaStatic(join(__dirname, "..", "assets")));
 
   const app = new Koa();
 

+ 112 - 72
src/index.js

@@ -5,9 +5,11 @@
 // Minimum required to get config
 const path = require("path");
 const envPaths = require("env-paths");
-const cli = require("./cli");
+const {cli} = require("./cli");
 const fs = require("fs");
-const exif = require("piexifjs");
+
+const promisesFs = require("fs").promises;
+
 
 const supports = require("./supports.js").supporting;
 const blocks = require("./supports.js").blocking;
@@ -18,7 +20,9 @@ const defaultConfigFile = path.join(
   envPaths("oasis", { suffix: "" }).config,
   "/default.json"
 );
+
 let haveConfig;
+
 try {
   const defaultConfigOverride = fs.readFileSync(defaultConfigFile, "utf8");
   Object.entries(JSON.parse(defaultConfigOverride)).forEach(([key, value]) => {
@@ -57,7 +61,8 @@ try {
   }
 }
 
-const nodeHttp = require("http");
+const { get } = require("node:http");
+
 const debug = require("debug")("oasis");
 
 const log = (formatter, ...args) => {
@@ -97,7 +102,7 @@ const oasisCheckPath = "/.well-known/oasis";
 process.on("uncaughtException", function (err) {
   // This isn't `err.code` because TypeScript doesn't like that.
   if (err["code"] === "EADDRINUSE") {
-    nodeHttp.get(url + oasisCheckPath, (res) => {
+    get(url + oasisCheckPath, (res) => {
       let rawData = "";
       res.on("data", (chunk) => {
         rawData += chunk;
@@ -146,15 +151,13 @@ process.argv = [];
 
 const http = require("./http");
 
-const koaBody = require("koa-body");
+const {koaBody} = require("koa-body");
 const { nav, ul, li, a } = require("hyperaxe");
 const open = require("open");
 const pull = require("pull-stream");
-const requireStyle = require("require-style");
 const koaRouter = require("@koa/router");
 const ssbMentions = require("ssb-mentions");
-const ssbRef = require("ssb-ref");
-const isSvg = require("is-svg");
+const isSvg = require('is-svg');
 const { themeNames } = require("@fraction/base16-css");
 const { isFeed, isMsg, isBlob } = require("ssb-ref");
 
@@ -166,7 +169,9 @@ const router = new koaRouter();
 // This handle is passed to the models for their convenience.
 const cooler = ssb({ offline: config.offline });
 
-const { about, blob, friend, meta, post, vote } = require("./models")({
+const models = require("./models");
+
+const { about, blob, friend, meta, post, vote } = models({
   cooler,
   isPublic: config.public,
 });
@@ -258,7 +263,7 @@ const handleBlobUpload = async function (ctx) {
     return "";
   }
 
-  let data = await fs.promises.readFile(blobUpload.path);
+  let data = await promisesFs.readFile(blobUpload.filepath);
   if (data.length == 0) {
     return "";
   }
@@ -272,15 +277,15 @@ const handleBlobUpload = async function (ctx) {
 
   try {
     const removeExif = (fileData) => {
-      const exifOrientation = exif.load(fileData);
-      const orientation = exifOrientation["0th"][exif.ImageIFD.Orientation];
-      const clean = exif.remove(fileData);
+      const exifOrientation = load(fileData);
+      const orientation = exifOrientation["0th"][ImageIFD.Orientation];
+      const clean = remove(fileData);
       if (orientation !== undefined) {
         // preserve img orientation
         const exifData = { "0th": {} };
-        exifData["0th"][exif.ImageIFD.Orientation] = orientation;
-        const exifStr = exif.dump(exifData);
-        return exif.insert(exifStr, clean);
+        exifData["0th"][ImageIFD.Orientation] = orientation;
+        const exifStr = dump(exifData);
+        return insert(exifStr, clean);
       } else {
         return clean;
       }
@@ -373,7 +378,6 @@ const {
   likesView,
   threadView,
   hashtagView,
-  markdownView,
   mentionsView,
   popularView,
   previewView,
@@ -391,8 +395,11 @@ const {
   topicsView,
   summaryView,
   threadsView,
-  spreadedView,
-} = require("./views");
+} = require("./views/index.js");
+
+const ssbRef = require("ssb-ref");
+
+const markdownView = require("./views/markdown.js");
 
 let sharp;
 
@@ -445,16 +452,21 @@ router
   .get("/public/popular/:period", async (ctx) => {
     const { period } = ctx.params;
     const publicPopular = async ({ period }) => {
-    const messages = await post.popular({ period });
-    const selectedLanguage = ctx.cookies.get("language") || "en";
-    const i18nBase = require("./views/i18n");
-    let i18n = i18nBase[selectedLanguage];
-    exports.setLanguage = (language) => {
-    selectedLanguage = language;
-    i18n = Object.assign({}, i18nBase.en, i18nBase[language]);
-    };
+      const messages = await post.popular({ period });
+      const selectedLanguage = ctx.cookies.get("language") || "en";
+      const i18nBase = require("./views/i18n");
+      let i18n = i18nBase[selectedLanguage];
+      exports.setLanguage = (language) => {
+        selectedLanguage = language;
+        i18n = Object.assign({}, i18nBase.en, i18nBase[language]);
+      };
       const prefix = nav(
-        ul(a({ href: "./day" }, i18n.day), a({ href: "./week" }, i18n.week), a({ href: "./month" }, i18n.month), a({ href: "./year" }, i18n.year))
+        ul(
+          a({ href: "./day" }, i18n.day),
+          a({ href: "./week" }, i18n.week),
+          a({ href: "./month" }, i18n.month),
+          a({ href: "./year" }, i18n.year)
+        )
       );
       return popularView({
         messages,
@@ -565,17 +577,49 @@ router
 
     ctx.body = await hashtagView({ hashtag, messages });
   })
-  .get("/theme.css", (ctx) => {
-    const theme = ctx.cookies.get("theme") || config.theme;
 
+  .get("/theme.css", async (ctx) => {
+    const theme = ctx.cookies.get("theme") || config.theme;
+  
     const packageName = "@fraction/base16-css";
-    const filePath = `${packageName}/src/base16-${theme}.css`;
-    ctx.type = "text/css";
-    ctx.body = requireStyle(filePath);
+    const filePath = path.resolve(
+      "node_modules",
+      packageName,
+      "src",
+      `base16-${theme}.css`
+    );
+  
+    try {
+      
+      // await the css content
+      const cssContent = await promisesFs.readFile(filePath, { encoding: "utf8" });
+  
+      ctx.type = "text/css"; // Set the Content-Type header
+      ctx.body = cssContent; // Serve the CSS content
+
+    } catch (err) {
+      console.error("Error reading CSS file:", err.message);
+  
+      ctx.status = 404; // Return a 404 status if the file is not found
+      ctx.body = "Theme not found.";
+    }
   })
-  .get("/custom-style.css", (ctx) => {
+  
+  .get("/custom-style.css", async (ctx) => {
     ctx.type = "text/css";
-    ctx.body = requireStyle(customStyleFile);
+    try {
+
+      // Read the CSS file
+      const cssContent = await fs.readFileSync(customStyleFile, "utf8");
+
+      ctx.type = "text/css"; // Set the Content-Type header
+      ctx.body = cssContent; // Serve the CSS content
+    } catch (err) {
+      console.error("Error reading custom style file:", err.message);
+
+      ctx.status = 404; // Return a 404 status if the file is not found
+      ctx.body = "Custom style not found.";
+    }
   })
   .get("/profile", async (ctx) => {
     const myFeedId = await meta.myFeedId();
@@ -620,7 +664,8 @@ router
     const name = String(ctx.request.body.name);
     const description = String(ctx.request.body.description);
 
-    const image = await fs.promises.readFile(ctx.request.files.image.path);
+    const image = await promisesFs.readFile(ctx.request.files.image.filepath);
+
     ctx.body = await post.publishProfileEdit({
       name,
       description,
@@ -748,33 +793,33 @@ router
       });
     };
     ctx.body = await getMeta({ theme });
-   })
+  })
   .get("/peers", async (ctx) => {
     const theme = ctx.cookies.get("theme") || config.theme;
     const getMeta = async ({ theme }) => {
-    const peers = await meta.connectedPeers();
-    const peersWithNames = await Promise.all(
-    peers.map(async ([key, value]) => {
-     value.name = await about.name(value.key);
-     return [key, value];
-     }))
-    return peersView({
-      peers: peersWithNames,
-      supports: supports,
-      blocks: blocks,
-      recommends: recommends,
-    });
-   };
+      const peers = await meta.connectedPeers();
+      const peersWithNames = await Promise.all(
+        peers.map(async ([key, value]) => {
+          value.name = await about.name(value.key);
+          return [key, value];
+        })
+      );
+      return peersView({
+        peers: peersWithNames,
+        supports: supports,
+        blocks: blocks,
+        recommends: recommends,
+      });
+    };
     ctx.body = await getMeta({ theme });
-   })
+  })
   .get("/invites", async (ctx) => {
     const theme = ctx.cookies.get("theme") || config.theme;
     const getMeta = async ({ theme }) => {
-      return invitesView({
-      });
+      return invitesView({});
     };
     ctx.body = await getMeta({ theme });
-   })
+  })
   .get("/likes/:feed", async (ctx) => {
     const { feed } = ctx.params;
     const likes = async ({ feed }) => {
@@ -822,11 +867,8 @@ router
     ctx.body = await publishView();
   })
   .get("/comment/:message", async (ctx) => {
-    const {
-      messages,
-      myFeedId,
-      parentMessage,
-    } = await resolveCommentComponents(ctx);
+    const { messages, myFeedId, parentMessage } =
+      await resolveCommentComponents(ctx);
     ctx.body = await commentView({ messages, myFeedId, parentMessage });
   })
   .post(
@@ -878,12 +920,8 @@ router
     "/comment/preview/:message",
     koaBody({ multipart: true }),
     async (ctx) => {
-      const {
-        messages,
-        contentWarning,
-        myFeedId,
-        parentMessage,
-      } = await resolveCommentComponents(ctx);
+      const { messages, contentWarning, myFeedId, parentMessage } =
+        await resolveCommentComponents(ctx);
 
       const previewData = await preparePreview(ctx);
 
@@ -1018,10 +1056,12 @@ router
     ctx.redirect(referer.href);
   })
   .post("/update", koaBody(), async (ctx) => {
-    const util = require('node:util');
-    const exec = util.promisify(require('node:child_process').exec);
+    const util = require("node:util");
+    const exec = util.promisify(require("node:child_process").exec);
     async function updateTool() {
-      const { stdout, stderr } = await exec('git reset --hard && git pull && npm install .');
+      const { stdout, stderr } = await exec(
+        "git reset --hard && git pull && npm install ."
+      );
       console.log("updating Oasis");
       console.log(stdout);
       console.log(stderr);
@@ -1062,10 +1102,10 @@ router
     try {
       const invite = String(ctx.request.body.invite);
       await meta.acceptInvite(invite);
-      } catch (e) {
-          // Just in case it's an invalid invite code. :(
-          debug(e);
-      }
+    } catch (e) {
+      // Just in case it's an invalid invite code. :(
+      debug(e);
+    }
     ctx.redirect("/invites");
   })
   .post("/settings/rebuild", async (ctx) => {

+ 3 - 1
src/models.js

@@ -310,6 +310,8 @@ module.exports = ({ cooler, isPublic }) => {
               dirty = true;
               feeds_to_name[feed] = newEntry;
             }
+          }, (err) => {
+            console.error(err);
           })
         );
       });
@@ -1914,4 +1916,4 @@ module.exports = ({ cooler, isPublic }) => {
   };
 
   return models;
-};
+};

+ 4 - 2
src/server.js

@@ -1,8 +1,11 @@
 #! /usr/bin/env node
 
+const moduleAlias = require('module-alias');
+moduleAlias.addAlias('punycode', 'punycode/');
+
 var fs = require('fs')
 var path = require('path')
-var SecretStack = require('secret-stack')
+const SecretStack = require('secret-stack')
 var caps = require('ssb-caps')
 var SSB = require('ssb-db')
 var Client       = require('ssb-client')
@@ -170,4 +173,3 @@ if(process.stdout.isTTY && (config.logging.level != 'info'))
     muxrpcli(argv, manifest, rpc, config.verbose)
   })
 }
-

+ 6 - 2
src/ssb/flotilla.js

@@ -1,7 +1,9 @@
-const stack = require("secret-stack");
+const SecretStack = require("secret-stack");
 const debug = require("debug")("oasis");
 const ssbConfig = require("ssb-config");
 
+const caps = require('ssb-caps')
+
 const plugins = [
   // Authentication often hooked for authentication.
   require("ssb-master"),
@@ -31,8 +33,9 @@ const plugins = [
 ];
 
 module.exports = (config) => {
-  const server = stack();
+  const server = SecretStack({caps});
   const walk = (input) => {
+
     if (Array.isArray(input)) {
       input.forEach(walk);
     } else {
@@ -45,3 +48,4 @@ module.exports = (config) => {
 
   return server({ ...ssbConfig, ...config });
 };
+

+ 1 - 2
src/ssb/index.js

@@ -4,7 +4,6 @@
 // to call methods over MuxRPC. It's a thin wrapper around SSB-Client, which is
 // a thin wrapper around the MuxRPC module.
 
-const { promisify } = require("util");
 const ssbClient = require("ssb-client");
 const ssbConfig = require("ssb-config");
 const ssbKeys = require("ssb-keys");
@@ -187,4 +186,4 @@ module.exports = ({ offline }) => {
   cooler.open();
 
   return cooler;
-};
+};

+ 15 - 9
src/supports.js

@@ -1,6 +1,8 @@
 #!/usr/bin/env node
 
-const fs = require("fs");
+const { readFileSync } = require("fs");
+const { join } =require("path");
+
 const path = require("path");
 const homedir = require('os').homedir();
 const supportingPath = path.join(homedir, ".ssb/flume/contacts2.json");
@@ -11,11 +13,12 @@ const {
 } = require("hyperaxe");
 
 const envPaths = require("env-paths");
-const cli = require("./cli");
+const {cli} = require("./cli");
 const ssb = require("./ssb");
+
 const defaultConfig = {};
-const defaultConfigFile = path.join(
-  envPaths("oasis", { suffix: "" }).config,
+const defaultConfigFile = join(
+  envPaths.default("oasis", { suffix: "" }).config,
   "/default.json"
 );
 
@@ -24,13 +27,16 @@ if (config.debug) {
   process.env.DEBUG = "oasis,oasis:*";
 }
 const cooler = ssb({ offline: config.offline });
-const { about} = require("./models")({
+
+const models = require("./models.js");
+
+const { about } = models({
   cooler,
   isPublic: config.public,
 });
 
 async function getNameByIdSupported(supported){
-  name_supported = await about.name(supported);
+  const name_supported = await about.name(supported);
   return name_supported
 }
 
@@ -45,7 +51,7 @@ async function getNameByIdRecommended(recommended){
 }
 
   try{
-      var supporting = JSON.parse(fs.readFileSync(supportingPath, {encoding:'utf8', flag:'r'})).value;
+      var supporting = JSON.parse(readFileSync(supportingPath, {encoding:'utf8', flag:'r'})).value;
     }catch{
       var supporting = undefined;
     }
@@ -70,7 +76,7 @@ async function getNameByIdRecommended(recommended){
            if (!arr.includes(supported)) {
               getNameSupported(supported);
               async function getNameSupported(supported){
-                 name_supported = await getNameByIdSupported(supported);
+                 const name_supported = await getNameByIdSupported(supported);
               arr.push(
                li(
                  name_supported,br,
@@ -149,4 +155,4 @@ async function getNameByIdRecommended(recommended){
 
 module.exports.supporting = supports;
 module.exports.blocking = blocks;
-module.exports.recommending = recommends;
+module.exports.recommending = recommends

+ 56 - 39
src/updater.js

@@ -1,43 +1,60 @@
-const request = require("request");
-const fs = require("fs");
-const path = require("path");
-const
-  promisify = require('util').promisify,
-  cb = promisify(request);
-const localpackage = path.join("package.json");
+const axios = require("axios");
+const {existsSync, readFileSync} = require("fs");
+const {join} = require("path");
+  
+const localpackage = join("package.json");
 const remoteUrl = "https://code.03c8.net/KrakensLab/oasis/src/master/package.json" // Official SNH-Oasis
 const remoteUrl2 = "https://github.com/epsylon/oasis/blob/main/package.json" // Mirror SNH-Oasis
 
-let requestInstance;
+// Splitted function
+async function checkMirror(callback) {
+  try {
+    // Try fetching from the mirror URL
+    const { data } = await axios.get(remoteUrl2, { responseType: "text" });
+    diffVersion(data);
+  } catch (error) {
+    console.error("Error fetching from mirror URL:", error.message);
+    callback("error");
+  }
+}
 
-exports.getRemoteVersion = function(callback){
-(async () => {
-  if (fs.existsSync(".git")) {
-    requestInstance = await cb(remoteUrl, function(error, response, body) {
-      if (error != null){
-        checkMirror(); 
-      }else{
-        diffVersion(body);
-      };
-    });
-    function checkMirror(){
-      requestInstance2 = request(remoteUrl2, function (error, response, body) {
-        diffVersion(body);
-      });
-    };
-    function diffVersion(body){
-      remoteVersion =  body.split('<li class="L3" rel="L3">').pop().split('</li>')[0];
-      remoteVersion = remoteVersion.split('&#34;version&#34;: &#34;').pop().split('&#34;,')[0];
-      localVersion = fs.readFileSync(localpackage, "utf8");
-      localVersion = localVersion.split('"name":').pop().split('"description":')[0];
-      localVersion = localVersion.split('"version"').pop().split('"')[1];
-      if (remoteVersion != localVersion){
-        checkversion = "required";
-      }else{
-        checkversion = "";
-      };
-    callback(checkversion);
-    };
-  };
-})();
-};
+function diffVersion(body, callback) {
+  let remoteVersion = body
+    .split('<li class="L3" rel="L3">')
+    .pop()
+    .split("</li>")[0];
+  remoteVersion = remoteVersion
+    .split("&#34;version&#34;: &#34;")
+    .pop()
+    .split("&#34;,")[0];
+  let localVersion = readFileSync(localpackage, "utf8");
+  localVersion = localVersion
+    .split('"name":')
+    .pop()
+    .split('"description":')[0];
+  localVersion = localVersion.split('"version"').pop().split('"')[1];
+  
+  let checkversion = ""
+
+  if (remoteVersion != localVersion) {
+    checkversion = "required";
+  } else {
+    checkversion = "";
+  }
+  callback(checkversion);
+}
+
+exports.getRemoteVersion = (callback) => {
+  (async () => {
+    if (existsSync(".git")) {
+      try {
+
+        // Now uses axios to get the package
+        const { data } = await axios.get(remoteUrl, { responseType: "text" });
+        diffVersion(data, callback);
+      } catch (error) {
+        checkMirror(callback);
+      }
+    }  
+  })();
+}

+ 0 - 1
src/views/index.js

@@ -7,7 +7,6 @@ const homedir = require('os').homedir();
 const gossipPath = path.join(homedir, ".ssb/gossip.json");
 const debug = require("debug")("oasis");
 const highlightJs = require("highlight.js");
-const MarkdownIt = require("markdown-it");
 const prettyMs = require("pretty-ms");
 
 const updater = require("../updater.js");

+ 1 - 1
src/views/markdown.js

@@ -59,4 +59,4 @@ module.exports = (input, mentions = []) =>
     toUrl: toUrl(mentions),
     /** @param character {string} */
     emoji: (character) => span({ class: "emoji" }, character).outerHTML,
-  });
+  });