diff --git a/src/MyWebLog.Data/MyWebLog.Data.fsproj b/src/MyWebLog.Data/MyWebLog.Data.fsproj
index d2e5d31..5c8082d 100644
--- a/src/MyWebLog.Data/MyWebLog.Data.fsproj
+++ b/src/MyWebLog.Data/MyWebLog.Data.fsproj
@@ -4,12 +4,9 @@
-
-
-
-
+
diff --git a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
index 7ab5dbc..425bd8c 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
@@ -1,8 +1,8 @@
namespace MyWebLog.Data.SQLite
open System.Threading.Tasks
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -23,11 +23,10 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
/// Count all top-level categories for the given web log
let countTopLevel webLogId =
log.LogTrace "Category.countTopLevel"
- Custom.scalar
+ conn.customScalar
$"{Document.Query.countByWebLog} AND data ->> '{parentIdField}' IS NULL"
[ webLogParam webLogId ]
- (fun rdr -> int (rdr.GetInt64(0)))
- conn
+ (toCount >> int)
/// Find all categories for the given web log
let findByWebLog webLogId =
@@ -54,9 +53,9 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
SELECT COUNT(DISTINCT data ->> '{nameof Post.Empty.Id}')
FROM {Table.Post}
WHERE {Document.Query.whereByWebLog}
- AND {Query.whereFieldEquals (nameof Post.Empty.Status) $"'{string Published}'"}
+ AND {Query.whereByField (nameof Post.Empty.Status) EQ $"'{string Published}'"}
AND {catSql}"""
- let! postCount = Custom.scalar query (webLogParam webLogId :: catParams) (_.GetInt64(0)) conn
+ let! postCount = conn.customScalar query (webLogParam webLogId :: catParams) toCount
return it.Id, int postCount
})
|> Task.WhenAll
@@ -80,13 +79,13 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
match! findById catId webLogId with
| Some cat ->
// Reassign any children to the category's parent category
- let! children = Count.byFieldEquals Table.Category parentIdField catId conn
+ let! children = conn.countByField Table.Category parentIdField EQ catId
if children > 0 then
- do! Update.partialByFieldEquals Table.Category parentIdField catId {| ParentId = cat.ParentId |} conn
+ do! conn.patchByField Table.Category parentIdField EQ catId {| ParentId = cat.ParentId |}
// Delete the category off all posts where it is assigned, and the category itself
let catIdField = Post.Empty.CategoryIds
let! posts =
- Custom.list
+ conn.customList
$"SELECT data ->> '{Post.Empty.Id}', data -> '{catIdField}'
FROM {Table.Post}
WHERE {Document.Query.whereByWebLog}
@@ -96,11 +95,10 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
WHERE json_each.value = @id)"
[ idParam catId; webLogParam webLogId ]
(fun rdr -> rdr.GetString(0), Utils.deserialize ser (rdr.GetString(1)))
- conn
for postId, cats in posts do
- do! Update.partialById
- Table.Post postId {| CategoryIds = cats |> List.filter (fun it -> it <> string catId) |} conn
- do! Delete.byId Table.Category catId conn
+ do! conn.patchById
+ Table.Post postId {| CategoryIds = cats |> List.filter (fun it -> it <> string catId) |}
+ do! conn.deleteById Table.Category catId
return if children = 0L then CategoryDeleted else ReassignedChildCategories
| None -> return CategoryNotFound
}
@@ -108,7 +106,7 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
/// Save a category
let save cat =
log.LogTrace "Category.save"
- save Table.Category cat conn
+ conn.save Table.Category cat
/// Restore categories from a backup
let restore cats = backgroundTask {
diff --git a/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs b/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs
index d11cd7a..b1008d3 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs
@@ -222,17 +222,14 @@ module Map =
let sqlParam name (value: obj) =
SqliteParameter(name, value)
-/// Create a document ID parameter
-let idParam (key: 'TKey) =
- sqlParam "@id" (string key)
-
/// Create a web log ID parameter
let webLogParam (webLogId: WebLogId) =
sqlParam "@webLogId" (string webLogId)
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
+open BitBadger.Documents.Sqlite.WithConn
/// Functions for manipulating documents
module Document =
@@ -242,7 +239,7 @@ module Document =
/// Fragment to add a web log ID condition to a WHERE clause (parameter @webLogId)
let whereByWebLog =
- Query.whereFieldEquals "WebLogId" "@webLogId"
+ Query.whereByField "WebLogId" EQ "@webLogId"
/// A SELECT query to count documents for a given web log ID
let countByWebLog table =
@@ -250,7 +247,7 @@ module Document =
/// A query to select from a table by the document's ID and its web log ID
let selectByIdAndWebLog table =
- $"{Query.Find.byFieldEquals table} AND {whereByWebLog}"
+ $"{Query.Find.byId table} AND {whereByWebLog}"
/// A query to select from a table by its web log ID
let selectByWebLog table =
@@ -258,7 +255,7 @@ module Document =
/// Count documents for the given web log ID
let countByWebLog table (webLogId: WebLogId) conn = backgroundTask {
- let! count = Count.byFieldEquals table "WebLogId" webLogId conn
+ let! count = Count.byField table "WebLogId" EQ webLogId conn
return int count
}
@@ -268,7 +265,7 @@ module Document =
/// Find documents for the given web log
let findByWebLog<'TDoc> table (webLogId: WebLogId) conn =
- Find.byFieldEquals<'TDoc> table "WebLogId" webLogId conn
+ Find.byField<'TDoc> table "WebLogId" EQ webLogId conn
/// Functions to support revisions
diff --git a/src/MyWebLog.Data/SQLite/SQLitePageData.fs b/src/MyWebLog.Data/SQLite/SQLitePageData.fs
index ba62ea0..4427fa8 100644
--- a/src/MyWebLog.Data/SQLite/SQLitePageData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLitePageData.fs
@@ -1,8 +1,8 @@
namespace MyWebLog.Data.SQLite
open System.Threading.Tasks
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -39,11 +39,10 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
/// Get all pages for a web log (without text or revisions)
let all webLogId =
log.LogTrace "Page.all"
- Custom.list
+ conn.customList
$"{Query.selectFromTable Table.Page} WHERE {Document.Query.whereByWebLog} ORDER BY LOWER({titleField})"
[ webLogParam webLogId ]
(fun rdr -> { fromData rdr with Text = "" })
- conn
/// Count all pages for the given web log
let countAll webLogId =
@@ -53,11 +52,10 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
/// Count all pages shown in the page list for the given web log
let countListed webLogId =
log.LogTrace "Page.countListed"
- Custom.scalar
- $"""{Document.Query.countByWebLog} AND {Query.whereFieldEquals pgListName "'true'"}"""
+ conn.customScalar
+ $"""{Document.Query.countByWebLog} AND {Query.whereByField pgListName EQ "'true'"}"""
[ webLogParam webLogId ]
- (fun rdr -> int (rdr.GetInt64(0)))
- conn
+ (toCount >> int)
/// Find a page by its ID (without revisions)
let findById pageId webLogId =
@@ -80,10 +78,9 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Page.delete"
match! findById pageId webLogId with
| Some _ ->
- do! Custom.nonQuery
+ do! conn.customNonQuery
$"DELETE FROM {Table.PageRevision} WHERE page_id = @id; {Query.Delete.byId Table.Page}"
[ idParam pageId ]
- conn
return true
| None -> return false
}
@@ -91,23 +88,21 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
/// Find a page by its permalink for the given web log
let findByPermalink (permalink: Permalink) webLogId =
log.LogTrace "Page.findByPermalink"
- Custom.single
- $"""{Document.Query.selectByWebLog} AND {Query.whereFieldEquals linkName "@link"}"""
+ conn.customSingle
+ $"""{Document.Query.selectByWebLog} AND {Query.whereByField linkName EQ "@link"}"""
[ webLogParam webLogId; SqliteParameter("@link", string permalink) ]
fromData
- conn
/// Find the current permalink within a set of potential prior permalinks for the given web log
let findCurrentPermalink (permalinks: Permalink list) webLogId =
log.LogTrace "Page.findCurrentPermalink"
let linkSql, linkParams = inJsonArray Table.Page (nameof Page.Empty.PriorPermalinks) "link" permalinks
- Custom.single
+ conn.customSingle
$"SELECT data ->> '{linkName}' AS permalink
FROM {Table.Page}
WHERE {Document.Query.whereByWebLog} AND {linkSql}"
(webLogParam webLogId :: linkParams)
Map.toPermalink
- conn
/// Get all complete pages for the given web log
let findFullByWebLog webLogId = backgroundTask {
@@ -120,27 +115,25 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
/// Get all listed pages for the given web log (without revisions or text)
let findListed webLogId =
log.LogTrace "Page.findListed"
- Custom.list
- $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereFieldEquals pgListName "'true'"}
+ conn.customList
+ $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField pgListName EQ "'true'"}
ORDER BY LOWER({titleField})"""
[ webLogParam webLogId ]
(fun rdr -> { fromData rdr with Text = "" })
- conn
/// Get a page of pages for the given web log (without revisions)
let findPageOfPages webLogId pageNbr =
log.LogTrace "Page.findPageOfPages"
- Custom.list
+ conn.customList
$"{Document.Query.selectByWebLog Table.Page} ORDER BY LOWER({titleField}) LIMIT @pageSize OFFSET @toSkip"
[ webLogParam webLogId; SqliteParameter("@pageSize", 26); SqliteParameter("@toSkip", (pageNbr - 1) * 25) ]
fromData
- conn
/// Save a page
let save (page: Page) = backgroundTask {
log.LogTrace "Page.update"
let! oldPage = findFullById page.Id page.WebLogId
- do! save Table.Page { page with Revisions = [] } conn
+ do! conn.save Table.Page { page with Revisions = [] }
do! updatePageRevisions page.Id (match oldPage with Some p -> p.Revisions | None -> []) page.Revisions
}
@@ -155,7 +148,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Page.updatePriorPermalinks"
match! findById pageId webLogId with
| Some _ ->
- do! Update.partialById Table.Page pageId {| PriorPermalinks = permalinks |} conn
+ do! conn.patchById Table.Page pageId {| PriorPermalinks = permalinks |}
return true
| None -> return false
}
diff --git a/src/MyWebLog.Data/SQLite/SQLitePostData.fs b/src/MyWebLog.Data/SQLite/SQLitePostData.fs
index 5ada20c..7990818 100644
--- a/src/MyWebLog.Data/SQLite/SQLitePostData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLitePostData.fs
@@ -1,8 +1,8 @@
namespace MyWebLog.Data.SQLite
open System.Threading.Tasks
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -34,7 +34,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let postByWebLog = Document.Query.selectByWebLog Table.Post
/// The SELECT statement to retrieve published posts with a web log ID parameter
- let publishedPostByWebLog = $"""{postByWebLog} AND {Query.whereFieldEquals statName $"'{string Published}'"}"""
+ let publishedPostByWebLog = $"""{postByWebLog} AND {Query.whereByField statName EQ $"'{string Published}'"}"""
/// Update a post's revisions
let updatePostRevisions (postId: PostId) oldRevs newRevs =
@@ -46,11 +46,10 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
/// Count posts in a status for the given web log
let countByStatus (status: PostStatus) webLogId =
log.LogTrace "Post.countByStatus"
- Custom.scalar
- $"""{Document.Query.countByWebLog} AND {Query.whereFieldEquals statName "@status"}"""
+ conn.customScalar
+ $"""{Document.Query.countByWebLog} AND {Query.whereByField statName EQ "@status"}"""
[ webLogParam webLogId; SqliteParameter("@status", string status) ]
- (fun rdr -> int (rdr.GetInt64(0)))
- conn
+ (toCount >> int)
/// Find a post by its ID for the given web log (excluding revisions)
let findById postId webLogId =
@@ -60,11 +59,10 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
/// Find a post by its permalink for the given web log (excluding revisions)
let findByPermalink (permalink: Permalink) webLogId =
log.LogTrace "Post.findByPermalink"
- Custom.single
- $"""{Document.Query.selectByWebLog Table.Post} AND {Query.whereFieldEquals linkName "@link"}"""
+ conn.customSingle
+ $"""{Document.Query.selectByWebLog Table.Post} AND {Query.whereByField linkName EQ "@link"}"""
[ webLogParam webLogId; SqliteParameter("@link", string permalink) ]
fromData
- conn
/// Find a complete post by its ID for the given web log
let findFullById postId webLogId = backgroundTask {
@@ -81,13 +79,12 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Post.delete"
match! findById postId webLogId with
| Some _ ->
- do! Custom.nonQuery
+ do! conn.customNonQuery
$"""DELETE FROM {Table.PostRevision} WHERE post_id = @id;
DELETE FROM {Table.PostComment}
- WHERE {Query.whereFieldEquals (nameof Comment.Empty.PostId) "@id"};
+ WHERE {Query.whereByField (nameof Comment.Empty.PostId) EQ "@id"};
{Query.Delete.byId Table.Post}"""
[ idParam postId ]
- conn
return true
| None -> return false
}
@@ -96,13 +93,12 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let findCurrentPermalink (permalinks: Permalink list) webLogId =
log.LogTrace "Post.findCurrentPermalink"
let linkSql, linkParams = inJsonArray Table.Post (nameof Post.Empty.PriorPermalinks) "link" permalinks
- Custom.single
+ conn.customSingle
$"SELECT data ->> '{linkName}' AS permalink
FROM {Table.Post}
WHERE {Document.Query.whereByWebLog} AND {linkSql}"
(webLogParam webLogId :: linkParams)
Map.toPermalink
- conn
/// Get all complete posts for the given web log
let findFullByWebLog webLogId = backgroundTask {
@@ -116,63 +112,57 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let findPageOfCategorizedPosts webLogId (categoryIds: CategoryId list) pageNbr postsPerPage =
log.LogTrace "Post.findPageOfCategorizedPosts"
let catSql, catParams = inJsonArray Table.Post (nameof Post.Empty.CategoryIds) "catId" categoryIds
- Custom.list
+ conn.customList
$"{publishedPostByWebLog} AND {catSql}
ORDER BY {publishField} DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
(webLogParam webLogId :: catParams)
fromData
- conn
/// Get a page of posts for the given web log (excludes text and revisions)
let findPageOfPosts webLogId pageNbr postsPerPage =
log.LogTrace "Post.findPageOfPosts"
- Custom.list
+ conn.customList
$"{postByWebLog}
ORDER BY {publishField} DESC NULLS FIRST, data ->> '{nameof Post.Empty.UpdatedOn}'
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ webLogParam webLogId ]
(fun rdr -> { fromData rdr with Text = "" })
- conn
/// Get a page of published posts for the given web log (excludes revisions)
let findPageOfPublishedPosts webLogId pageNbr postsPerPage =
log.LogTrace "Post.findPageOfPublishedPosts"
- Custom.list
+ conn.customList
$"{publishedPostByWebLog}
ORDER BY {publishField} DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ webLogParam webLogId ]
fromData
- conn
/// Get a page of tagged posts for the given web log (excludes revisions)
let findPageOfTaggedPosts webLogId (tag : string) pageNbr postsPerPage =
log.LogTrace "Post.findPageOfTaggedPosts"
let tagSql, tagParams = inJsonArray Table.Post (nameof Post.Empty.Tags) "tag" [ tag ]
- Custom.list
+ conn.customList
$"{publishedPostByWebLog} AND {tagSql}
ORDER BY p.published_on DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
(webLogParam webLogId :: tagParams)
fromData
- conn
/// Find the next newest and oldest post from a publish date for the given web log
let findSurroundingPosts webLogId (publishedOn : Instant) = backgroundTask {
log.LogTrace "Post.findSurroundingPosts"
let! older =
- Custom.single
+ conn.customSingle
$"{publishedPostByWebLog} AND {publishField} < @publishedOn ORDER BY {publishField} DESC LIMIT 1"
[ webLogParam webLogId; SqliteParameter("@publishedOn", instantParam publishedOn) ]
fromData
- conn
let! newer =
- Custom.single
+ conn.customSingle
$"{publishedPostByWebLog} AND {publishField} > @publishedOn ORDER BY {publishField} LIMIT 1"
[ webLogParam webLogId; SqliteParameter("@publishedOn", instantParam publishedOn) ]
fromData
- conn
return older, newer
}
@@ -180,7 +170,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let save (post: Post) = backgroundTask {
log.LogTrace "Post.save"
let! oldPost = findFullById post.Id post.WebLogId
- do! save Table.Post { post with Revisions = [] } conn
+ do! conn.save Table.Post { post with Revisions = [] }
do! updatePostRevisions post.Id (match oldPost with Some p -> p.Revisions | None -> []) post.Revisions
}
@@ -194,7 +184,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let updatePriorPermalinks postId webLogId (permalinks: Permalink list) = backgroundTask {
match! findById postId webLogId with
| Some _ ->
- do! Update.partialById Table.Post postId {| PriorPermalinks = permalinks |} conn
+ do! conn.patchById Table.Post postId {| PriorPermalinks = permalinks |}
return true
| None -> return false
}
diff --git a/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs b/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs
index 0303034..50a4b04 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs
@@ -1,7 +1,7 @@
namespace MyWebLog.Data.SQLite
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -20,7 +20,7 @@ type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "TagMap.delete"
match! findById tagMapId webLogId with
| Some _ ->
- do! Delete.byId Table.TagMap tagMapId conn
+ do! conn.deleteById Table.TagMap tagMapId
return true
| None -> return false
}
@@ -28,12 +28,11 @@ type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) =
/// Find a tag mapping by its URL value for the given web log
let findByUrlValue (urlValue: string) webLogId =
log.LogTrace "TagMap.findByUrlValue"
- Custom.single
+ conn.customSingle
$"""{Document.Query.selectByWebLog Table.TagMap}
- AND {Query.whereFieldEquals (nameof TagMap.Empty.UrlValue) "@urlValue"}"""
+ AND {Query.whereByField (nameof TagMap.Empty.UrlValue) EQ "@urlValue"}"""
[ webLogParam webLogId; SqliteParameter("@urlValue", urlValue) ]
fromData
- conn
/// Get all tag mappings for the given web log
let findByWebLog webLogId =
@@ -44,16 +43,15 @@ type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) =
let findMappingForTags (tags: string list) webLogId =
log.LogTrace "TagMap.findMappingForTags"
let mapSql, mapParams = inClause $"AND data ->> '{nameof TagMap.Empty.Tag}'" "tag" id tags
- Custom.list
+ conn.customList
$"{Document.Query.selectByWebLog Table.TagMap} {mapSql}"
(webLogParam webLogId :: mapParams)
fromData
- conn
/// Save a tag mapping
let save (tagMap: TagMap) =
log.LogTrace "TagMap.save"
- save Table.TagMap tagMap conn
+ conn.save Table.TagMap tagMap
/// Restore tag mappings from a backup
let restore tagMaps = backgroundTask {
diff --git a/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs b/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
index f5d50a1..cb41ddc 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
@@ -1,7 +1,7 @@
namespace MyWebLog.Data.SQLite
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -25,36 +25,34 @@ type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
/// Retrieve all themes (except 'admin'; excludes template text)
let all () =
log.LogTrace "Theme.all"
- Custom.list
+ conn.customList
$"{Query.selectFromTable Table.Theme} WHERE {idField} <> 'admin' ORDER BY {idField}"
[]
withoutTemplateText
- conn
/// Does a given theme exist?
let exists (themeId: ThemeId) =
log.LogTrace "Theme.exists"
- Exists.byId Table.Theme themeId conn
+ conn.existsById Table.Theme themeId
/// Find a theme by its ID
let findById themeId =
log.LogTrace "Theme.findById"
- Find.byId Table.Theme themeId conn
+ conn.findById Table.Theme themeId
/// Find a theme by its ID (excludes the text of templates)
let findByIdWithoutText (themeId: ThemeId) =
log.LogTrace "Theme.findByIdWithoutText"
- Custom.single (Query.Find.byId Table.Theme) [ idParam themeId ] withoutTemplateText conn
+ conn.customSingle (Query.Find.byId Table.Theme) [ idParam themeId ] withoutTemplateText
/// Delete a theme by its ID
let delete themeId = backgroundTask {
log.LogTrace "Theme.delete"
match! findByIdWithoutText themeId with
| Some _ ->
- do! Custom.nonQuery
+ do! conn.customNonQuery
$"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id; {Query.Delete.byId Table.Theme}"
[ idParam themeId ]
- conn
return true
| None -> return false
}
@@ -62,7 +60,7 @@ type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
/// Save a theme
let save (theme: Theme) =
log.LogTrace "Theme.save"
- save Table.Theme theme conn
+ conn.save Table.Theme theme
interface IThemeData with
member _.All() = all ()
@@ -86,44 +84,41 @@ type SQLiteThemeAssetData(conn : SqliteConnection, log: ILogger) =
/// Get all theme assets (excludes data)
let all () =
log.LogTrace "ThemeAsset.all"
- Custom.list $"SELECT theme_id, path, updated_on FROM {Table.ThemeAsset}" [] (Map.toThemeAsset false) conn
+ conn.customList $"SELECT theme_id, path, updated_on FROM {Table.ThemeAsset}" [] (Map.toThemeAsset false)
/// Delete all assets for the given theme
let deleteByTheme (themeId: ThemeId) =
log.LogTrace "ThemeAsset.deleteByTheme"
- Custom.nonQuery $"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id" [ idParam themeId ] conn
+ conn.customNonQuery $"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id" [ idParam themeId ]
/// Find a theme asset by its ID
let findById assetId =
log.LogTrace "ThemeAsset.findById"
- Custom.single
+ conn.customSingle
$"SELECT *, ROWID FROM {Table.ThemeAsset} WHERE theme_id = @id AND path = @path"
(assetIdParams assetId)
(Map.toThemeAsset true)
- conn
/// Get theme assets for the given theme (excludes data)
let findByTheme (themeId: ThemeId) =
log.LogTrace "ThemeAsset.findByTheme"
- Custom.list
+ conn.customList
$"SELECT theme_id, path, updated_on FROM {Table.ThemeAsset} WHERE theme_id = @id"
[ idParam themeId ]
(Map.toThemeAsset false)
- conn
/// Get theme assets for the given theme
let findByThemeWithData (themeId: ThemeId) =
log.LogTrace "ThemeAsset.findByThemeWithData"
- Custom.list
+ conn.customList
$"SELECT *, ROWID FROM {Table.ThemeAsset} WHERE theme_id = @id"
[ idParam themeId ]
(Map.toThemeAsset true)
- conn
/// Save a theme asset
let save (asset: ThemeAsset) = backgroundTask {
log.LogTrace "ThemeAsset.save"
- do! Custom.nonQuery
+ do! conn.customNonQuery
$"INSERT INTO {Table.ThemeAsset} (
theme_id, path, updated_on, data
) VALUES (
@@ -134,14 +129,12 @@ type SQLiteThemeAssetData(conn : SqliteConnection, log: ILogger) =
[ sqlParam "@updatedOn" (instantParam asset.UpdatedOn)
sqlParam "@dataLength" asset.Data.Length
yield! (assetIdParams asset.Id) ]
- conn
let! rowId =
- Custom.scalar
+ conn.customScalar
$"SELECT ROWID FROM {Table.ThemeAsset} WHERE theme_id = @id AND path = @path"
(assetIdParams asset.Id)
- (_.GetInt64(0))
- conn
+ _.GetInt64(0)
use dataStream = new MemoryStream(asset.Data)
use blobStream = new SqliteBlob(conn, Table.ThemeAsset, "data", rowId)
do! dataStream.CopyToAsync blobStream
diff --git a/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs b/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs
index e6bc5e0..fbc2ce9 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs
@@ -1,7 +1,7 @@
namespace MyWebLog.Data.SQLite
open System.IO
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -13,7 +13,7 @@ type SQLiteUploadData(conn: SqliteConnection, log: ILogger) =
/// Save an uploaded file
let add (upload: Upload) = backgroundTask {
log.LogTrace "Upload.add"
- do! Custom.nonQuery
+ do! conn.customNonQuery
$"INSERT INTO {Table.Upload} (
id, web_log_id, path, updated_on, data
) VALUES (
@@ -24,9 +24,8 @@ type SQLiteUploadData(conn: SqliteConnection, log: ILogger) =
sqlParam "@path" (string upload.Path)
sqlParam "@updatedOn" (instantParam upload.UpdatedOn)
sqlParam "@dataLength" upload.Data.Length ]
- conn
let! rowId =
- Custom.scalar $"SELECT ROWID FROM {Table.Upload} WHERE id = @id" [ idParam upload.Id ] (_.GetInt64(0)) conn
+ conn.customScalar $"SELECT ROWID FROM {Table.Upload} WHERE id = @id" [ idParam upload.Id ] _.GetInt64(0)
use dataStream = new MemoryStream(upload.Data)
use blobStream = new SqliteBlob(conn, Table.Upload, "data", rowId)
do! dataStream.CopyToAsync blobStream
@@ -36,14 +35,13 @@ type SQLiteUploadData(conn: SqliteConnection, log: ILogger) =
let delete (uploadId: UploadId) webLogId = backgroundTask {
log.LogTrace "Upload.delete"
let! upload =
- Custom.single
+ conn.customSingle
$"SELECT id, web_log_id, path, updated_on FROM {Table.Upload} WHERE id = @id AND web_log_id = @webLogId"
[ idParam uploadId; webLogParam webLogId ]
(Map.toUpload false)
- conn
match upload with
| Some up ->
- do! Custom.nonQuery $"DELETE FROM {Table.Upload} WHERE id = @id" [ idParam up.Id ] conn
+ do! conn.customNonQuery $"DELETE FROM {Table.Upload} WHERE id = @id" [ idParam up.Id ]
return Ok (string up.Path)
| None -> return Error $"Upload ID {string uploadId} not found"
}
@@ -51,29 +49,26 @@ type SQLiteUploadData(conn: SqliteConnection, log: ILogger) =
/// Find an uploaded file by its path for the given web log
let findByPath (path: string) webLogId =
log.LogTrace "Upload.findByPath"
- Custom.single
+ conn.customSingle
$"SELECT *, ROWID FROM {Table.Upload} WHERE web_log_id = @webLogId AND path = @path"
[ webLogParam webLogId; sqlParam "@path" path ]
(Map.toUpload true)
- conn
/// Find all uploaded files for the given web log (excludes data)
let findByWebLog webLogId =
log.LogTrace "Upload.findByWebLog"
- Custom.list
+ conn.customList
$"SELECT id, web_log_id, path, updated_on FROM {Table.Upload} WHERE web_log_id = @webLogId"
[ webLogParam webLogId ]
(Map.toUpload false)
- conn
/// Find all uploaded files for the given web log
let findByWebLogWithData webLogId =
log.LogTrace "Upload.findByWebLogWithData"
- Custom.list
+ conn.customList
$"SELECT *, ROWID FROM {Table.Upload} WHERE web_log_id = @webLogId"
[ webLogParam webLogId ]
(Map.toUpload true)
- conn
/// Restore uploads from a backup
let restore uploads = backgroundTask {
diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs
index e308e94..a9d1d17 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs
@@ -1,7 +1,7 @@
namespace MyWebLog.Data.SQLite
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -13,56 +13,55 @@ type SQLiteWebLogData(conn: SqliteConnection, log: ILogger) =
/// Add a web log
let add webLog =
log.LogTrace "WebLog.add"
- insert Table.WebLog webLog conn
+ conn.insert Table.WebLog webLog
/// Retrieve all web logs
let all () =
log.LogTrace "WebLog.all"
- Find.all Table.WebLog conn
+ conn.findAll Table.WebLog
/// Delete a web log by its ID
let delete webLogId =
log.LogTrace "WebLog.delete"
let subQuery table =
- $"""(SELECT data ->> 'Id' FROM {table} WHERE {Query.whereFieldEquals "WebLogId" "@webLogId"}"""
+ $"""(SELECT data ->> 'Id' FROM {table} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}"""
Custom.nonQuery
$"""DELETE FROM {Table.PostComment} WHERE data ->> 'PostId' IN {subQuery Table.Post};
DELETE FROM {Table.PostRevision} WHERE post_id IN {subQuery Table.Post};
DELETE FROM {Table.PageRevision} WHERE page_id IN {subQuery Table.Page};
- DELETE FROM {Table.Post} WHERE {Query.whereFieldEquals "WebLogId" "@webLogId"};
- DELETE FROM {Table.Page} WHERE {Query.whereFieldEquals "WebLogId" "@webLogId"};
- DELETE FROM {Table.Category} WHERE {Query.whereFieldEquals "WebLogId" "@webLogId"};
- DELETE FROM {Table.TagMap} WHERE {Query.whereFieldEquals "WebLogId" "@webLogId"};
- DELETE FROM {Table.Upload} WHERE web_log_id = @id;
- DELETE FROM {Table.WebLogUser} WHERE {Query.whereFieldEquals "WebLogId" "@webLogId"};
+ DELETE FROM {Table.Post} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"};
+ DELETE FROM {Table.Page} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"};
+ DELETE FROM {Table.Category} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"};
+ DELETE FROM {Table.TagMap} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"};
+ DELETE FROM {Table.Upload} WHERE web_log_id = @webLogId;
+ DELETE FROM {Table.WebLogUser} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"};
DELETE FROM {Table.WebLog} WHERE {Query.whereById "@webLogId"}"""
[ webLogParam webLogId ]
- conn
/// Find a web log by its host (URL base)
let findByHost (url: string) =
log.LogTrace "WebLog.findByHost"
- Find.firstByFieldEquals Table.WebLog (nameof WebLog.Empty.UrlBase) url conn
+ conn.findFirstByField Table.WebLog (nameof WebLog.Empty.UrlBase) EQ url
/// Find a web log by its ID
let findById webLogId =
log.LogTrace "WebLog.findById"
- Find.byId Table.WebLog webLogId conn
+ conn.findById Table.WebLog webLogId
/// Update redirect rules for a web log
let updateRedirectRules (webLog: WebLog) =
log.LogTrace "WebLog.updateRedirectRules"
- Update.partialById Table.WebLog webLog.Id {| RedirectRules = webLog.RedirectRules |} conn
+ conn.patchById Table.WebLog webLog.Id {| RedirectRules = webLog.RedirectRules |}
/// Update RSS options for a web log
let updateRssOptions (webLog: WebLog) =
log.LogTrace "WebLog.updateRssOptions"
- Update.partialById Table.WebLog webLog.Id {| Rss = webLog.Rss |} conn
+ conn.patchById Table.WebLog webLog.Id {| Rss = webLog.Rss |}
/// Update settings for a web log
let updateSettings (webLog: WebLog) =
log.LogTrace "WebLog.updateSettings"
- Update.full Table.WebLog webLog.Id webLog conn
+ conn.updateById Table.WebLog webLog.Id webLog
interface IWebLogData with
member _.Add webLog = add webLog
diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs
index 35771e7..61cae3b 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs
@@ -1,7 +1,7 @@
namespace MyWebLog.Data.SQLite
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -20,12 +20,12 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "WebLogUser.delete"
match! findById userId webLogId with
| Some _ ->
- let! pageCount = Count.byFieldEquals Table.Page (nameof Page.Empty.AuthorId) (string userId) conn
- let! postCount = Count.byFieldEquals Table.Post (nameof Post.Empty.AuthorId) (string userId) conn
+ let! pageCount = conn.countByField Table.Page (nameof Page.Empty.AuthorId) EQ (string userId)
+ let! postCount = conn.countByField Table.Post (nameof Post.Empty.AuthorId) EQ (string userId)
if pageCount + postCount > 0 then
return Error "User has pages or posts; cannot delete"
else
- do! Delete.byId Table.WebLogUser userId conn
+ do! conn.deleteById Table.WebLogUser userId
return Ok true
| None -> return Error "User does not exist"
}
@@ -33,12 +33,11 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) =
/// Find a user by their e-mail address for the given web log
let findByEmail (email: string) webLogId =
log.LogTrace "WebLogUser.findByEmail"
- Custom.single
+ conn.customSingle
$"""{Document.Query.selectByWebLog Table.WebLogUser}
- AND {Query.whereFieldEquals (nameof WebLogUser.Empty.Email) "@email"}"""
+ AND {Query.whereByField (nameof WebLogUser.Empty.Email) EQ "@email"}"""
[ webLogParam webLogId; sqlParam "@email" email ]
fromData
- conn
/// Get all users for the given web log
let findByWebLog webLogId = backgroundTask {
@@ -51,18 +50,17 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) =
let findNames webLogId (userIds: WebLogUserId list) =
log.LogTrace "WebLogUser.findNames"
let nameSql, nameParams = inClause "AND data ->> 'Id'" "id" string userIds
- Custom.list
+ conn.customList
$"{Document.Query.selectByWebLog Table.WebLogUser} {nameSql}"
(webLogParam webLogId :: nameParams)
(fun rdr ->
let user = fromData rdr
{ Name = string user.Id; Value = user.DisplayName })
- conn
/// Save a user
let save user =
log.LogTrace "WebLogUser.update"
- save Table.WebLogUser user conn
+ conn.save Table.WebLogUser user
/// Restore users from a backup
let restore users = backgroundTask {
@@ -74,7 +72,7 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) =
let setLastSeen userId webLogId = backgroundTask {
log.LogTrace "WebLogUser.setLastSeen"
match! findById userId webLogId with
- | Some _ -> do! Update.partialById Table.WebLogUser userId {| LastSeenOn = Noda.now () |} conn
+ | Some _ -> do! conn.patchById Table.WebLogUser userId {| LastSeenOn = Noda.now () |}
| None -> ()
}
diff --git a/src/MyWebLog.Data/SQLiteData.fs b/src/MyWebLog.Data/SQLiteData.fs
index 4386d09..e312395 100644
--- a/src/MyWebLog.Data/SQLiteData.fs
+++ b/src/MyWebLog.Data/SQLiteData.fs
@@ -1,8 +1,8 @@
namespace MyWebLog.Data
open System.Threading.Tasks
-open BitBadger.Sqlite.FSharp.Documents
-open BitBadger.Sqlite.FSharp.Documents.WithConn
+open BitBadger.Documents
+open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
open Microsoft.Extensions.Logging
open MyWebLog
@@ -16,13 +16,13 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
/// Create tables (and their associated indexes) if they do not exist
let ensureTables () = backgroundTask {
- let! tables = Custom.list "SELECT name FROM sqlite_master WHERE type = 'table'" [] (_.GetString(0)) conn
+ let! tables = conn.customList "SELECT name FROM sqlite_master WHERE type = 'table'" [] _.GetString(0)
let needsTable table =
not (List.contains table tables)
let jsonTable table =
- $"{Definition.createTable table}; {Definition.createKey table}"
+ $"{Query.Definition.ensureTable table}; {Query.Definition.ensureKey table}"
let tasks =
seq {
@@ -41,21 +41,23 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
// Category table
if needsTable Table.Category then
- $"{jsonTable Table.Category};
- CREATE INDEX idx_{Table.Category}_web_log ON {Table.Category} ((data ->> 'WebLogId'))"
+ $"""{jsonTable Table.Category};
+ {Query.Definition.ensureIndexOn Table.Category "web_log" [ nameof Category.Empty.WebLogId ]}"""
// Web log user table
if needsTable Table.WebLogUser then
- $"{jsonTable Table.WebLogUser};
- CREATE INDEX idx_{Table.WebLogUser}_email
- ON {Table.WebLogUser} ((data ->> 'WebLogId'), (data ->> 'Email'))"
+ $"""{jsonTable Table.WebLogUser};
+ {Query.Definition.ensureIndexOn
+ Table.WebLogUser
+ "email"
+ [ nameof WebLogUser.Empty.WebLogId; nameof WebLogUser.Empty.Email ]}"""
// Page tables
if needsTable Table.Page then
- $"{jsonTable Table.Page};
- CREATE INDEX idx_{Table.Page}_author ON {Table.Page} ((data ->> 'AuthorId'));
- CREATE INDEX idx_{Table.Page}_permalink
- ON {Table.Page} ((data ->> 'WebLogId'), (data ->> 'Permalink'))"
+ $"""{jsonTable Table.Page};
+ {Query.Definition.ensureIndexOn Table.Page "author" [ nameof Page.Empty.AuthorId ]};
+ {Query.Definition.ensureIndexOn
+ Table.Page "permalink" [ nameof Page.Empty.WebLogId; nameof Page.Empty.Permalink ]}"""
if needsTable Table.PageRevision then
$"CREATE TABLE {Table.PageRevision} (
page_id TEXT NOT NULL,
@@ -65,12 +67,14 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
// Post tables
if needsTable Table.Post then
- $"{jsonTable Table.Post};
- CREATE INDEX idx_{Table.Post}_author ON {Table.Post} ((data ->> 'AuthorId'));
- CREATE INDEX idx_{Table.Post}_status
- ON {Table.Post} ((data ->> 'WebLogId'), (data ->> 'Status'), (data ->> 'UpdatedOn'));
- CREATE INDEX idx_{Table.Post}_permalink
- ON {Table.Post} ((data ->> 'WebLogId'), (data ->> 'Permalink'))"
+ $"""{jsonTable Table.Post};
+ {Query.Definition.ensureIndexOn Table.Post "author" [ nameof Post.Empty.AuthorId ]};
+ {Query.Definition.ensureIndexOn
+ Table.Post "permalink" [ nameof Post.Empty.WebLogId; nameof Post.Empty.Permalink ]};
+ {Query.Definition.ensureIndexOn
+ Table.Post
+ "status"
+ [ nameof Post.Empty.WebLogId; nameof Post.Empty.Status; nameof Post.Empty.UpdatedOn ]}"""
// TODO: index categories by post?
if needsTable Table.PostRevision then
$"CREATE TABLE {Table.PostRevision} (
@@ -79,13 +83,14 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
revision_text TEXT NOT NULL,
PRIMARY KEY (post_id, as_of))"
if needsTable Table.PostComment then
- $"{jsonTable Table.PostComment};
- CREATE INDEX idx_{Table.PostComment}_post ON {Table.PostComment} ((data ->> 'PostId'))"
+ $"""{jsonTable Table.PostComment};
+ {Query.Definition.ensureIndexOn Table.PostComment "post" [ nameof Comment.Empty.PostId ]}"""
// Tag map table
if needsTable Table.TagMap then
- $"{jsonTable Table.TagMap};
- CREATE INDEX idx_{Table.TagMap}_tag ON {Table.TagMap} ((data ->> 'WebLogId'), (data ->> 'UrlValue'))"
+ $"""{jsonTable Table.TagMap};
+ {Query.Definition.ensureIndexOn
+ Table.TagMap "url" [ nameof TagMap.Empty.WebLogId; nameof TagMap.Empty.UrlValue ]}"""
// Uploaded file table
if needsTable Table.Upload then
@@ -104,7 +109,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
}
|> Seq.map (fun sql ->
log.LogInformation $"""Creating {(sql.Replace("IF NOT EXISTS ", "").Split ' ')[2]} table..."""
- Custom.nonQuery sql [] conn)
+ conn.customNonQuery sql [])
let! _ = Task.WhenAll tasks
()
@@ -112,7 +117,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
/// Set the database version to the specified version
let setDbVersion version =
- Custom.nonQuery $"DELETE FROM {Table.DbVersion}; INSERT INTO {Table.DbVersion} VALUES ('%s{version}')" [] conn
+ conn.customNonQuery $"DELETE FROM {Table.DbVersion}; INSERT INTO {Table.DbVersion} VALUES ('%s{version}')" []
/// Implement the changes between v2-rc1 and v2-rc2
let migrateV2Rc1ToV2Rc2 () = backgroundTask {
@@ -467,6 +472,6 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
member _.StartUp () = backgroundTask {
do! ensureTables ()
- let! version = Custom.single $"SELECT id FROM {Table.DbVersion}" [] (_.GetString(0)) conn
+ let! version = conn.customSingle $"SELECT id FROM {Table.DbVersion}" [] _.GetString(0)
do! migrate version
}
diff --git a/src/MyWebLog/Program.fs b/src/MyWebLog/Program.fs
index e8c7380..884fe55 100644
--- a/src/MyWebLog/Program.fs
+++ b/src/MyWebLog/Program.fs
@@ -56,9 +56,6 @@ open MyWebLog.Data
open Newtonsoft.Json
open Npgsql
-// The SQLite document library
-module Sqlite = BitBadger.Sqlite.FSharp.Documents
-
/// Logic to obtain a data connection and implementation based on configured values
module DataImplementation =
@@ -176,11 +173,7 @@ let main args =
| :? SQLiteData ->
// ADO.NET connections are designed to work as per-request instantiation
let cfg = sp.GetRequiredService()
- let _ =
- builder.Services.AddScoped(fun sp ->
- let conn = Sqlite.Configuration.dbConn ()
- conn.OpenAsync() |> Async.AwaitTask |> Async.RunSynchronously
- conn)
+ let _ = builder.Services.AddScoped(fun sp -> Sqlite.Configuration.dbConn ())
let _ = builder.Services.AddScoped()
// Use SQLite for caching as well
let cachePath = defaultArg (Option.ofObj (cfg.GetConnectionString "SQLiteCachePath")) "./session.db"