From a9b9e1ba02d9fe24451f6aa7399d6855dec52b29 Mon Sep 17 00:00:00 2001 From: becem-gharbi <99251251+becem-gharbi@users.noreply.github.com> Date: Tue, 23 May 2023 10:31:37 +0100 Subject: [PATCH] refactor: create a unified storage plugin (context + module) --- src/index.ts | 50 +++++++++--------- src/storage.ts | 98 ----------------------------------- src/{ => storage}/context.ts | 20 +++++--- src/storage/index.ts | 17 +++++++ src/storage/module.ts | 99 ++++++++++++++++++++++++++++++++++++ 5 files changed, 156 insertions(+), 128 deletions(-) delete mode 100644 src/storage.ts rename src/{ => storage}/context.ts (71%) create mode 100644 src/storage/index.ts create mode 100644 src/storage/module.ts diff --git a/src/index.ts b/src/index.ts index c62c4d2..2531e60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,20 +5,31 @@ import nodered from "node-red"; import { LocalSettings } from "@node-red/runtime"; import { dirname, resolve } from "path"; import { fileURLToPath } from "url"; -import { storageModule } from "./storage.js"; -import { createStorage } from "unstorage"; import mongodbDriver from "unstorage/drivers/mongodb"; -import { contextModule } from "./context.js"; +import storage from "./storage/index.js"; dotenv.config(); -const storage = createStorage({ - //@ts-ignore - driver: mongodbDriver({ - connectionString: process.env.MONGO_DB_URL, - databaseName: "nodeRed", - collectionName: "unstorage", - }), +const { contextStore, storageModule } = storage({ + app: "app0", + + storageOptions: { + //@ts-ignore + driver: mongodbDriver({ + connectionString: process.env.MONGO_DB_URL, + databaseName: "nodeRed", + collectionName: "storage", + }), + }, + + contextOptions: { + //@ts-ignore + driver: mongodbDriver({ + connectionString: process.env.MONGO_DB_URL, + databaseName: "nodeRed", + collectionName: "context", + }), + }, }); const cwd = dirname(fileURLToPath(import.meta.url)); @@ -36,9 +47,11 @@ const settings: LocalSettings = { //@ts-ignore storageModule: storageModule, - storageSettings: { - storage: storage, - appName: process.env.APP_NAME || "default", + contextStorage: { + unstorage: { + //@ts-ignore + module: contextStore, + }, }, adminAuth: { @@ -54,17 +67,6 @@ const settings: LocalSettings = { }, ], }, - - contextStorage: { - unstorage: { - //@ts-ignore - module: contextModule, - config: { - storage: storage, - appName: process.env.APP_NAME || "default", - }, - }, - }, }; const app = express(); diff --git a/src/storage.ts b/src/storage.ts deleted file mode 100644 index fbb6f69..0000000 --- a/src/storage.ts +++ /dev/null @@ -1,98 +0,0 @@ -//@ts-nocheck -import type { StorageModule } from "@node-red/runtime"; -import { prefixStorage, Storage } from "unstorage"; - -var appStorage: Storage; -var libraryStorage: Storage; - -export const storageModule: StorageModule = { - init: ({ storageSettings }) => { - appStorage = prefixStorage( - storageSettings.storage, - storageSettings.appName - ); - - libraryStorage = prefixStorage(appStorage, "library"); - }, - - getFlows: () => appStorage.getItem("flows").then((flows) => flows || []), - - saveFlows: (flows) => appStorage.setItem("flows", flows), - - getCredentials: () => - appStorage.getItem("credentials").then((creds) => creds || {}), - - saveCredentials: (credentials) => - appStorage.setItem("credentials", credentials), - - getSettings: () => - appStorage.getItem("settings").then((settings) => settings || {}), - - saveSettings: (settings) => appStorage.setItem("settings", settings), - - getSessions: () => - appStorage.getItem("sessions").then((sessions) => sessions || {}), - - saveSessions: (sessions) => appStorage.setItem("sessions", sessions), - - getLibraryEntry: async function (type, name) { - if (name == "") { - name = "/"; - } else if (!name.startsWith("/")) { - name = "/" + name; - } - - const library = await libraryStorage.getItem(name + ":" + type); - - if (library) { - const body = JSON.parse(library.body); - return body; - } - - let libraryKeys = await libraryStorage.getKeys(name); - - if (!libraryKeys) { - return []; - } - - libraryKeys = libraryKeys.filter((el) => el.endsWith(type)); - - var dirs = []; - var files = []; - - for (var i = 0; i < libraryKeys.length; i++) { - const library = await libraryStorage.getItem(libraryKeys[i]); - - var n = library.name; - n = n.replace(name, ""); - if (n.indexOf("/") == -1) { - var f = library.meta; - f.fn = n; - files.push(f); - } else { - n = n.substr(0, n.indexOf("/")); - dirs.push(n); - } - } - - dirs = dirs.concat(files); - - return dirs; - }, - - saveLibraryEntry: function (type, name, meta, body) { - var p = name.split("/"); // strip multiple slash - p = p.filter(Boolean); - name = p.slice(0, p.length).join("/"); - if (name != "" && !name.startsWith("/")) { - name = "/" + name; - } - - return libraryStorage.setItem(name + ":" + type, { - name, - meta, - body, - type, - }); - }, -}; diff --git a/src/context.ts b/src/storage/context.ts similarity index 71% rename from src/context.ts rename to src/storage/context.ts index 187f483..8e2b723 100644 --- a/src/context.ts +++ b/src/storage/context.ts @@ -1,9 +1,17 @@ -import { prefixStorage, Storage } from "unstorage"; +import { prefixStorage, Storage, createStorage } from "unstorage"; +import type { CreateStorageOptions } from "unstorage"; var appStorage: Storage; -var ContextStore = function (storageSettings) { - appStorage = prefixStorage(storageSettings.storage, storageSettings.appName); +var ContextStore = function (args: { + app: string; + options: CreateStorageOptions; +}) { + let appStorage: Storage; + + const storage = createStorage(args.options); + + appStorage = prefixStorage(storage, args.app); }; ContextStore.prototype.open = () => {}; @@ -49,6 +57,6 @@ ContextStore.prototype.delete = (scope: string) => ContextStore.prototype.clean = (activeNodes) => {}; -export function contextModule(config) { - return new ContextStore(config); -} +export default (args: { app: string; options: CreateStorageOptions }) => { + return new ContextStore(args); +}; diff --git a/src/storage/index.ts b/src/storage/index.ts new file mode 100644 index 0000000..2263934 --- /dev/null +++ b/src/storage/index.ts @@ -0,0 +1,17 @@ +import type { CreateStorageOptions } from "unstorage"; +import contextStore from "./context.js"; +import storageModule from "./module.js"; + +export default function (args: { + app: string; + storageOptions: CreateStorageOptions; + contextOptions: CreateStorageOptions; +}) { + const module = storageModule({ app: args.app, options: args.storageOptions }); + + return { + storageModule: module, + contextStore: () => + contextStore({ app: args.app, options: args.contextOptions }), + }; +} diff --git a/src/storage/module.ts b/src/storage/module.ts new file mode 100644 index 0000000..ff8eaa5 --- /dev/null +++ b/src/storage/module.ts @@ -0,0 +1,99 @@ +//@ts-nocheck +import { prefixStorage, Storage, createStorage } from "unstorage"; +import type { CreateStorageOptions } from "unstorage"; + +var appStorage: Storage; +var libraryStorage: Storage; + +export default (args: { app: string; options: CreateStorageOptions }) => { + return { + init: () => { + const storage = createStorage(args.options); + + appStorage = prefixStorage(storage, args.app); + + libraryStorage = prefixStorage(appStorage, "library"); + }, + + getFlows: () => appStorage.getItem("flows").then((flows) => flows || []), + + saveFlows: (flows) => appStorage.setItem("flows", flows), + + getCredentials: () => + appStorage.getItem("credentials").then((creds) => creds || {}), + + saveCredentials: (credentials) => + appStorage.setItem("credentials", credentials), + + getSettings: () => + appStorage.getItem("settings").then((settings) => settings || {}), + + saveSettings: (settings) => appStorage.setItem("settings", settings), + + getSessions: () => + appStorage.getItem("sessions").then((sessions) => sessions || {}), + + saveSessions: (sessions) => appStorage.setItem("sessions", sessions), + + getLibraryEntry: async function (type, name) { + if (name == "") { + name = "/"; + } else if (!name.startsWith("/")) { + name = "/" + name; + } + + const library = await libraryStorage.getItem(name + ":" + type); + + if (library) { + const body = JSON.parse(library.body); + return body; + } + + let libraryKeys = await libraryStorage.getKeys(name); + + if (!libraryKeys) { + return []; + } + + libraryKeys = libraryKeys.filter((el) => el.endsWith(type)); + + var dirs = []; + var files = []; + + for (var i = 0; i < libraryKeys.length; i++) { + const library = await libraryStorage.getItem(libraryKeys[i]); + + var n = library.name; + n = n.replace(name, ""); + if (n.indexOf("/") == -1) { + var f = library.meta; + f.fn = n; + files.push(f); + } else { + n = n.substr(0, n.indexOf("/")); + dirs.push(n); + } + } + + dirs = dirs.concat(files); + + return dirs; + }, + + saveLibraryEntry: function (type, name, meta, body) { + var p = name.split("/"); // strip multiple slash + p = p.filter(Boolean); + name = p.slice(0, p.length).join("/"); + if (name != "" && !name.startsWith("/")) { + name = "/" + name; + } + + return libraryStorage.setItem(name + ":" + type, { + name, + meta, + body, + type, + }); + }, + }; +};