Version 2.1 #41

Merged
danieljsummers merged 123 commits from version-2.1 into main 2024-03-27 00:13:28 +00:00
10 changed files with 19 additions and 23 deletions
Showing only changes of commit b69b6c37a4 - Show all commits

View File

@ -17,16 +17,13 @@ type PostgresData(log: ILogger<PostgresData>, ser: JsonSerializer) =
Configuration.useSerializer (Utils.createDocumentSerializer ser) Configuration.useSerializer (Utils.createDocumentSerializer ser)
let! tables = let! tables =
Custom.list "SELECT tablename FROM pg_tables WHERE schemaname = 'public'" [] Custom.list
(fun row -> row.string "tablename") "SELECT tablename FROM pg_tables WHERE schemaname = 'public'" [] (fun row -> row.string "tablename")
let needsTable table = not (List.contains table tables) let needsTable table = not (List.contains table tables)
// Create a document table
let mutable isNew = false
let sql = seq { let sql = seq {
// Theme tables // Theme tables
if needsTable Table.Theme then if needsTable Table.Theme then
isNew <- true
Query.Definition.ensureTable Table.Theme Query.Definition.ensureTable Table.Theme
Query.Definition.ensureKey Table.Theme Query.Definition.ensureKey Table.Theme
if needsTable Table.ThemeAsset then if needsTable Table.ThemeAsset then
@ -152,8 +149,7 @@ type PostgresData(log: ILogger<PostgresData>, ser: JsonSerializer) =
" - Drop all tables from the database" " - Drop all tables from the database"
" - Use this executable to restore each backup"; "" " - Use this executable to restore each backup"; ""
"Commands to back up all web logs:" "Commands to back up all web logs:"
yield! webLogs |> List.map (fun (url, slug) -> $"./myWebLog backup {url} v2-rc2.{slug}.json") yield! webLogs |> List.map (fun (url, slug) -> $"./myWebLog backup {url} v2-rc2.{slug}.json") ]
]
|> String.concat "\n" |> String.concat "\n"
|> log.LogWarning |> log.LogWarning

View File

@ -24,7 +24,7 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
let countTopLevel webLogId = let countTopLevel webLogId =
log.LogTrace "Category.countTopLevel" log.LogTrace "Category.countTopLevel"
conn.customScalar conn.customScalar
$"{Document.Query.countByWebLog} AND data ->> '{parentIdField}' IS NULL" $"{Document.Query.countByWebLog Table.Category} AND data ->> '{parentIdField}' IS NULL"
[ webLogParam webLogId ] [ webLogParam webLogId ]
(toCount >> int) (toCount >> int)
@ -79,11 +79,11 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
match! findById catId webLogId with match! findById catId webLogId with
| Some cat -> | Some cat ->
// Reassign any children to the category's parent category // Reassign any children to the category's parent category
let! children = conn.countByField Table.Category parentIdField EQ catId let! children = conn.countByField Table.Category parentIdField EQ (string catId)
if children > 0 then if children > 0 then
do! conn.patchByField Table.Category parentIdField EQ catId {| ParentId = cat.ParentId |} do! conn.patchByField Table.Category parentIdField EQ (string catId) {| ParentId = cat.ParentId |}
// Delete the category off all posts where it is assigned, and the category itself // Delete the category off all posts where it is assigned, and the category itself
let catIdField = Post.Empty.CategoryIds let catIdField = nameof Post.Empty.CategoryIds
let! posts = let! posts =
conn.customList conn.customList
$"SELECT data ->> '{Post.Empty.Id}', data -> '{catIdField}' $"SELECT data ->> '{Post.Empty.Id}', data -> '{catIdField}'
@ -94,7 +94,7 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
FROM json_each({Table.Post}.data -> '{catIdField}') FROM json_each({Table.Post}.data -> '{catIdField}')
WHERE json_each.value = @id)" WHERE json_each.value = @id)"
[ idParam catId; webLogParam webLogId ] [ idParam catId; webLogParam webLogId ]
(fun rdr -> rdr.GetString(0), Utils.deserialize<string list> ser (rdr.GetString(1))) (fun rdr -> rdr.GetString 0, Utils.deserialize<string list> ser (rdr.GetString 1))
for postId, cats in posts do for postId, cats in posts do
do! conn.patchById do! conn.patchById
Table.Post postId {| CategoryIds = cats |> List.filter (fun it -> it <> string catId) |} Table.Post postId {| CategoryIds = cats |> List.filter (fun it -> it <> string catId) |}

View File

@ -255,7 +255,7 @@ module Document =
/// Count documents for the given web log ID /// Count documents for the given web log ID
let countByWebLog table (webLogId: WebLogId) conn = backgroundTask { let countByWebLog table (webLogId: WebLogId) conn = backgroundTask {
let! count = Count.byField table "WebLogId" EQ webLogId conn let! count = Count.byField table "WebLogId" EQ (string webLogId) conn
return int count return int count
} }
@ -265,7 +265,7 @@ module Document =
/// Find documents for the given web log /// Find documents for the given web log
let findByWebLog<'TDoc> table (webLogId: WebLogId) conn = let findByWebLog<'TDoc> table (webLogId: WebLogId) conn =
Find.byField<'TDoc> table "WebLogId" EQ webLogId conn Find.byField<'TDoc> table "WebLogId" EQ (string webLogId) conn
/// Functions to support revisions /// Functions to support revisions
@ -302,6 +302,6 @@ module Revisions =
for addRev in toAdd do for addRev in toAdd do
do! Custom.nonQuery do! Custom.nonQuery
$"INSERT INTO {revTable} VALUES (@id, @asOf, @text)" $"INSERT INTO {revTable} VALUES (@id, @asOf, @text)"
[ idParam key; sqlParam "asOf" (instantParam addRev.AsOf); sqlParam "@text" addRev.Text ] [ idParam key; sqlParam "asOf" (instantParam addRev.AsOf); sqlParam "@text" (string addRev.Text) ]
conn conn
} }

View File

@ -53,7 +53,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
let countListed webLogId = let countListed webLogId =
log.LogTrace "Page.countListed" log.LogTrace "Page.countListed"
conn.customScalar conn.customScalar
$"""{Document.Query.countByWebLog} AND {Query.whereByField pgListName EQ "'true'"}""" $"""{Document.Query.countByWebLog Table.Page} AND {Query.whereByField pgListName EQ "'true'"}"""
[ webLogParam webLogId ] [ webLogParam webLogId ]
(toCount >> int) (toCount >> int)
@ -89,7 +89,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
let findByPermalink (permalink: Permalink) webLogId = let findByPermalink (permalink: Permalink) webLogId =
log.LogTrace "Page.findByPermalink" log.LogTrace "Page.findByPermalink"
conn.customSingle conn.customSingle
$"""{Document.Query.selectByWebLog} AND {Query.whereByField linkName EQ "@link"}""" $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField linkName EQ "@link"}"""
[ webLogParam webLogId; SqliteParameter("@link", string permalink) ] [ webLogParam webLogId; SqliteParameter("@link", string permalink) ]
fromData<Page> fromData<Page>

View File

@ -47,7 +47,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let countByStatus (status: PostStatus) webLogId = let countByStatus (status: PostStatus) webLogId =
log.LogTrace "Post.countByStatus" log.LogTrace "Post.countByStatus"
conn.customScalar conn.customScalar
$"""{Document.Query.countByWebLog} AND {Query.whereByField statName EQ "@status"}""" $"""{Document.Query.countByWebLog Table.Post} AND {Query.whereByField statName EQ "@status"}"""
[ webLogParam webLogId; SqliteParameter("@status", string status) ] [ webLogParam webLogId; SqliteParameter("@status", string status) ]
(toCount >> int) (toCount >> int)

View File

@ -122,7 +122,7 @@ type SQLiteThemeAssetData(conn : SqliteConnection, log: ILogger) =
$"INSERT INTO {Table.ThemeAsset} ( $"INSERT INTO {Table.ThemeAsset} (
theme_id, path, updated_on, data theme_id, path, updated_on, data
) VALUES ( ) VALUES (
@themeId, @path, @updatedOn, ZEROBLOB(@dataLength) @id, @path, @updatedOn, ZEROBLOB(@dataLength)
) ON CONFLICT (theme_id, path) DO UPDATE ) ON CONFLICT (theme_id, path) DO UPDATE
SET updated_on = @updatedOn, SET updated_on = @updatedOn,
data = ZEROBLOB(@dataLength)" data = ZEROBLOB(@dataLength)"

View File

@ -13,7 +13,7 @@ module private Helpers =
/// Create a new ID (short GUID) /// Create a new ID (short GUID)
// https://www.madskristensen.net/blog/A-shorter-and-URL-friendly-GUID // https://www.madskristensen.net/blog/A-shorter-and-URL-friendly-GUID
let newId () = let newId () =
Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-')[..22] Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-')[..21]
/// Pipeline with most extensions enabled /// Pipeline with most extensions enabled
let markdownPipeline = MarkdownPipelineBuilder().UseSmartyPants().UseAdvancedExtensions().UseColorCode().Build() let markdownPipeline = MarkdownPipelineBuilder().UseSmartyPants().UseAdvancedExtensions().UseColorCode().Build()

View File

@ -443,7 +443,7 @@ module Theme =
let themeName = fileName.Split(".").[0].ToLowerInvariant().Replace(" ", "-") let themeName = fileName.Split(".").[0].ToLowerInvariant().Replace(" ", "-")
if themeName.EndsWith "-theme" then if themeName.EndsWith "-theme" then
if Regex.IsMatch(themeName, """^[a-z0-9\-]+$""") then if Regex.IsMatch(themeName, """^[a-z0-9\-]+$""") then
Ok(ThemeId(themeName[..themeName.Length - 6])) Ok(ThemeId(themeName[..themeName.Length - 7]))
else Error $"Theme ID {fileName} is invalid" else Error $"Theme ID {fileName} is invalid"
else Error "Theme .zip file name must end in \"-theme.zip\"" else Error "Theme .zip file name must end in \"-theme.zip\""

View File

@ -18,7 +18,7 @@ module CatchAll =
let textLink = let textLink =
let extra = webLog.ExtraPath let extra = webLog.ExtraPath
let url = string ctx.Request.Path let url = string ctx.Request.Path
(if extra = "" then url else url[..extra.Length]).ToLowerInvariant() (if extra = "" then url else url[extra.Length..]).ToLowerInvariant()
let await it = (Async.AwaitTask >> Async.RunSynchronously) it let await it = (Async.AwaitTask >> Async.RunSynchronously) it
seq { seq {
debug (fun () -> $"Considering URL {textLink}") debug (fun () -> $"Considering URL {textLink}")

View File

@ -79,7 +79,7 @@ module DataImplementation =
let createSQLite connStr : IData = let createSQLite connStr : IData =
Sqlite.Configuration.useConnectionString connStr Sqlite.Configuration.useConnectionString connStr
let log = sp.GetRequiredService<ILogger<SQLiteData>>() let log = sp.GetRequiredService<ILogger<SQLiteData>>()
let conn = new SqliteConnection(connStr) let conn = Sqlite.Configuration.dbConn ()
log.LogInformation $"Using SQLite database {conn.DataSource}" log.LogInformation $"Using SQLite database {conn.DataSource}"
SQLiteData(conn, log, Json.configure (JsonSerializer.CreateDefault())) SQLiteData(conn, log, Json.configure (JsonSerializer.CreateDefault()))