From f64955c69d91e578e580b409ba31ac4b3477da96 Mon Sep 17 00:00:00 2001 From: vnugent Date: Wed, 12 Jul 2023 01:28:23 -0400 Subject: Initial commit --- back-end/src/StorageExtensions.cs | 181 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 back-end/src/StorageExtensions.cs (limited to 'back-end/src/StorageExtensions.cs') diff --git a/back-end/src/StorageExtensions.cs b/back-end/src/StorageExtensions.cs new file mode 100644 index 0000000..cb4ba5a --- /dev/null +++ b/back-end/src/StorageExtensions.cs @@ -0,0 +1,181 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: CMNext +* Package: Content.Publishing.Blog.Admin +* File: StorageExtensions.cs +* +* CMNext is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* CMNext is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +using VNLib.Utils.IO; +using VNLib.Net.Http; + +using Content.Publishing.Blog.Admin.Model; +using Content.Publishing.Blog.Admin.Storage; + +namespace Content.Publishing.Blog.Admin +{ + internal static class StorageExtensions + { + /// + /// Writes a file of the given content type to the given path in the given channel context. + /// + /// + /// The channel context to write the file in + /// The stream containing the file data to write to the storage layer + /// The relative path to the file within the context to write + /// The file content type + /// A token to cancel the operation + /// A task that completes when the file data has been written to the storage layer + public static Task SetObjectDataAsync(this IStorageFacade storage, IChannelContext context, Stream data, string path, ContentType ct, CancellationToken cancellation) + { + return storage.SetFileAsync($"{context.BaseDir}/{path}", data, ct, cancellation); + } + + /// + /// Removes an item from a pauth scoped within the given channel context + /// + /// + /// The channel to scope the item into + /// The item path within the channel to delete + /// A token to cancel the operation + /// A task that completes when the deletion operation has completed + public static Task RemoveObjectAsync(this IStorageFacade storage, IChannelContext context, string path, CancellationToken cancellation) + { + return storage.DeleteFileAsync($"{context.BaseDir}/{path}", cancellation); + } + + /// + /// Creates and loads a new with the file data from the given path + /// that resides in the given channel context + /// + /// + /// + /// The channel context to get the file data from + /// The relative path inside the channel to load the database from + /// A token to cancel the operation + /// A task that resolves the new from file + public static Task> LoadDbAsync(this IStorageFacade storage, IChannelContext context, string fileName, CancellationToken cancellation) where T : IRecord + { + return storage.LoadDbAsync($"{context.BaseDir}/{fileName}", cancellation); + } + + /// + /// Stores the given in the given channel context at the given file path + /// + /// + /// + /// The channel context to write the database file inside + /// The path to the database file to overwrite + /// The database to capture the file data from + /// A token to cancel the operation + /// A task that completes when the database has been stored + public static Task StoreAsync(this IStorageFacade storage, IChannelContext context, string fileName, IRecordDb store, CancellationToken cancellation) + { + return storage.StoreAsync($"{context.BaseDir}/{fileName}", store, cancellation); + } + + /// + /// Reads the file data from the given path that resides in the given channel context + /// and writes it to the given stream + /// + /// + /// The channel context to read the file from + /// The realtive path within the channel to the file + /// The stream to write the file data to from the storage layer + /// A token to cancel the operation + /// A task that resolves the number of bytes read into the output stream + public static Task ReadFileAsync(this IStorageFacade storage, IChannelContext context, string fileName, Stream stream, CancellationToken cancellation) + { + return storage.ReadFileAsync($"{context.BaseDir}/{fileName}", stream, cancellation); + } + + /// + /// Gets the external file path for the given path that exists in the given channel context + /// + /// + /// The channel context that contains the item + /// The realtive path inside the channel to the item to get the path for + /// The full external path of the item + public static string GetExternalFilePath(this IStorageFacade storage, IChannelContext context, string path) + { + return storage.GetExternalFilePath($"{context.BaseDir}/{path}"); + } + + /// + /// Stores the at the given file path async + /// + /// The record type + /// + /// The database to store + /// The file path to store the record at + /// A token to cancel the operation + /// A task that completes when the operation has completed + public static async Task StoreAsync(this IStorageFacade storage, string path, IRecordDb store, CancellationToken cancellation) + { + //Alloc ms to write records to + using VnMemoryStream ms = new(); + + //Write the records to the stream + store.Store(ms); + + await storage.SetFileAsync(path, ms, ContentType.Json, cancellation); + } + + /// + /// Creates a new from the given object path and populates + /// it with records from the file + /// + /// + /// + /// The path to the stored database file + /// A token to cancel the operation + /// The populated , if loading fails (file not found etc) the store will be returned empty + public static async Task> LoadDbAsync(this IStorageFacade storage, string objPath, CancellationToken cancellation) where T : IRecord + { + //Create the db + IRecordDb db = JsonRecordDb.Create(); + + await storage.LoadDbAsync(objPath, db, cancellation); + + return db; + } + + /// + /// Populates the given with records from the file at the given path + /// + /// + /// + /// The path to the database file + /// The record database store ready to accept the database content + /// A token to cancel the operation + /// A task that completes when the database has been populated + public static async Task LoadDbAsync(this IStorageFacade storage, string objPath, IRecordDb db, CancellationToken cancellation) where T : IRecord + { + //Mem stream to read the object into + using VnMemoryStream ms = new(); + + await storage.ReadFileAsync(objPath, ms, cancellation); + + //Load the db from the stream + db.Load(ms); + } + + } +} -- cgit