diff --git a/src/MyWebLog.Data/Converters.fs b/src/MyWebLog.Data/Converters.fs
index d68025d..b4e07a1 100644
--- a/src/MyWebLog.Data/Converters.fs
+++ b/src/MyWebLog.Data/Converters.fs
@@ -12,120 +12,120 @@ module Json =
type CategoryIdConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: CategoryId, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: CategoryId, _: bool, _: JsonSerializer) =
(string >> CategoryId) reader.Value
type CommentIdConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: CommentId, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: CommentId, _: bool, _: JsonSerializer) =
(string >> CommentId) reader.Value
type CommentStatusConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: CommentStatus, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: CommentStatus, _: bool, _: JsonSerializer) =
(string >> CommentStatus.Parse) reader.Value
- type CustomFeedIdConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : CustomFeedId, _ : JsonSerializer) =
- writer.WriteValue (CustomFeedId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : CustomFeedId, _ : bool, _ : JsonSerializer) =
+ type CustomFeedIdConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: CustomFeedId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: CustomFeedId, _: bool, _: JsonSerializer) =
(string >> CustomFeedId) reader.Value
- type CustomFeedSourceConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : CustomFeedSource, _ : JsonSerializer) =
- writer.WriteValue (CustomFeedSource.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : CustomFeedSource, _ : bool, _ : JsonSerializer) =
- (string >> CustomFeedSource.parse) reader.Value
+ type CustomFeedSourceConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: CustomFeedSource, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: CustomFeedSource, _: bool, _: JsonSerializer) =
+ (string >> CustomFeedSource.Parse) reader.Value
type ExplicitRatingConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: ExplicitRating, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: ExplicitRating, _: bool, _: JsonSerializer) =
(string >> ExplicitRating.Parse) reader.Value
type MarkupTextConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: MarkupText, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: MarkupText, _: bool, _: JsonSerializer) =
(string >> MarkupText.Parse) reader.Value
type PermalinkConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: Permalink, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: Permalink, _: bool, _: JsonSerializer) =
(string >> Permalink) reader.Value
type PageIdConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: PageId, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: PageId, _: bool, _: JsonSerializer) =
(string >> PageId) reader.Value
type PodcastMediumConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: PodcastMedium, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: PodcastMedium, _: bool, _: JsonSerializer) =
(string >> PodcastMedium.Parse) reader.Value
type PostIdConverter() =
inherit JsonConverter()
override _.WriteJson(writer: JsonWriter, value: PostId, _: JsonSerializer) =
- writer.WriteValue value.Value
+ writer.WriteValue(string value)
override _.ReadJson(reader: JsonReader, _: Type, _: PostId, _: bool, _: JsonSerializer) =
(string >> PostId) reader.Value
- type TagMapIdConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : TagMapId, _ : JsonSerializer) =
- writer.WriteValue (TagMapId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : TagMapId, _ : bool, _ : JsonSerializer) =
+ type TagMapIdConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: TagMapId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: TagMapId, _: bool, _: JsonSerializer) =
(string >> TagMapId) reader.Value
- type ThemeAssetIdConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : ThemeAssetId, _ : JsonSerializer) =
- writer.WriteValue (ThemeAssetId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : ThemeAssetId, _ : bool, _ : JsonSerializer) =
- (string >> ThemeAssetId.ofString) reader.Value
+ type ThemeAssetIdConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: ThemeAssetId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: ThemeAssetId, _: bool, _: JsonSerializer) =
+ (string >> ThemeAssetId.Parse) reader.Value
- type ThemeIdConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : ThemeId, _ : JsonSerializer) =
- writer.WriteValue (ThemeId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : ThemeId, _ : bool, _ : JsonSerializer) =
+ type ThemeIdConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: ThemeId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: ThemeId, _: bool, _: JsonSerializer) =
(string >> ThemeId) reader.Value
- type UploadIdConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : UploadId, _ : JsonSerializer) =
- writer.WriteValue (UploadId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : UploadId, _ : bool, _ : JsonSerializer) =
+ type UploadIdConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: UploadId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: UploadId, _: bool, _: JsonSerializer) =
(string >> UploadId) reader.Value
- type WebLogIdConverter () =
- inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : WebLogId, _ : JsonSerializer) =
- writer.WriteValue (WebLogId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : WebLogId, _ : bool, _ : JsonSerializer) =
+ type WebLogIdConverter() =
+ inherit JsonConverter()
+ override _.WriteJson(writer: JsonWriter, value: WebLogId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: WebLogId, _: bool, _: JsonSerializer) =
(string >> WebLogId) reader.Value
- type WebLogUserIdConverter () =
+ type WebLogUserIdConverter() =
inherit JsonConverter ()
- override _.WriteJson (writer : JsonWriter, value : WebLogUserId, _ : JsonSerializer) =
- writer.WriteValue (WebLogUserId.toString value)
- override _.ReadJson (reader : JsonReader, _ : Type, _ : WebLogUserId, _ : bool, _ : JsonSerializer) =
+ override _.WriteJson(writer: JsonWriter, value: WebLogUserId, _: JsonSerializer) =
+ writer.WriteValue(string value)
+ override _.ReadJson(reader: JsonReader, _: Type, _: WebLogUserId, _: bool, _: JsonSerializer) =
(string >> WebLogUserId) reader.Value
open Microsoft.FSharpLu.Json
diff --git a/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs b/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs
index 08d041c..b78be64 100644
--- a/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs
@@ -43,7 +43,7 @@ type PostgresCategoryData(log: ILogger) =
FROM {Table.Post}
WHERE {Query.whereDataContains "@criteria"}
AND {catIdSql}"""
- [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published.Value |}
+ [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |}
catIdParams ]
Map.toCount
|> Async.AwaitTask
@@ -64,7 +64,7 @@ type PostgresCategoryData(log: ILogger) =
/// Find a category by its ID for the given web log
let findById catId webLogId =
log.LogTrace "Category.findById"
- Document.findByIdAndWebLog Table.Category catId (_.Value) webLogId
+ Document.findByIdAndWebLog Table.Category catId string webLogId
/// Find all categories for the given web log
let findByWebLog webLogId =
@@ -73,7 +73,7 @@ type PostgresCategoryData(log: ILogger) =
/// Create parameters for a category insert / update
let catParameters (cat : Category) =
- Query.docParameters cat.Id.Value cat
+ Query.docParameters (string cat.Id) cat
/// Delete a category
let delete catId webLogId = backgroundTask {
@@ -81,7 +81,7 @@ type PostgresCategoryData(log: ILogger) =
match! findById catId webLogId with
| Some cat ->
// Reassign any children to the category's parent category
- let! children = Find.byContains Table.Category {| ParentId = catId.Value |}
+ let! children = Find.byContains Table.Category {| ParentId = string catId |}
let hasChildren = not (List.isEmpty children)
if hasChildren then
let! _ =
@@ -90,7 +90,7 @@ type PostgresCategoryData(log: ILogger) =
|> Sql.executeTransactionAsync [
Query.Update.partialById Table.Category,
children |> List.map (fun child -> [
- "@id", Sql.string child.Id.Value
+ "@id", Sql.string (string child.Id)
"@data", Query.jsonbDocParam {| ParentId = cat.ParentId |}
])
]
@@ -98,7 +98,7 @@ type PostgresCategoryData(log: ILogger) =
// Delete the category off all posts where it is assigned
let! posts =
Custom.list $"SELECT data FROM {Table.Post} WHERE data -> '{nameof Post.empty.CategoryIds}' @> @id"
- [ "@id", Query.jsonbDocParam [| catId.Value |] ] fromData
+ [ "@id", Query.jsonbDocParam [| string catId |] ] fromData
if not (List.isEmpty posts) then
let! _ =
Configuration.dataSource ()
@@ -106,14 +106,14 @@ type PostgresCategoryData(log: ILogger) =
|> Sql.executeTransactionAsync [
Query.Update.partialById Table.Post,
posts |> List.map (fun post -> [
- "@id", Sql.string post.Id.Value
+ "@id", Sql.string (string post.Id)
"@data", Query.jsonbDocParam
{| CategoryIds = post.CategoryIds |> List.filter (fun cat -> cat <> catId) |}
])
]
()
// Delete the category itself
- do! Delete.byId Table.Category catId.Value
+ do! Delete.byId Table.Category (string catId)
return if hasChildren then ReassignedChildCategories else CategoryDeleted
| None -> return CategoryNotFound
}
diff --git a/src/MyWebLog.Data/Postgres/PostgresHelpers.fs b/src/MyWebLog.Data/Postgres/PostgresHelpers.fs
index b51b1e6..ae73f49 100644
--- a/src/MyWebLog.Data/Postgres/PostgresHelpers.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresHelpers.fs
@@ -70,7 +70,7 @@ open Npgsql.FSharp
/// Create a SQL parameter for the web log ID
let webLogIdParam webLogId =
- "@webLogId", Sql.string (WebLogId.toString webLogId)
+ "@webLogId", Sql.string (string webLogId)
/// Create an anonymous record with the given web log ID
let webLogDoc (webLogId : WebLogId) =
@@ -206,7 +206,7 @@ module Revisions =
let revParams<'TKey> (key : 'TKey) (keyFunc : 'TKey -> string) rev = [
typedParam "asOf" rev.AsOf
"@id", Sql.string (keyFunc key)
- "@text", Sql.string rev.Text.Value
+ "@text", Sql.string (string rev.Text)
]
/// The SQL statement to insert a revision
diff --git a/src/MyWebLog.Data/Postgres/PostgresPageData.fs b/src/MyWebLog.Data/Postgres/PostgresPageData.fs
index 8be3d1b..7bf8c80 100644
--- a/src/MyWebLog.Data/Postgres/PostgresPageData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresPageData.fs
@@ -14,7 +14,7 @@ type PostgresPageData (log: ILogger) =
/// Append revisions to a page
let appendPageRevisions (page: Page) = backgroundTask {
log.LogTrace "Page.appendPageRevisions"
- let! revisions = Revisions.findByEntityId Table.PageRevision Table.Page page.Id _.Value
+ let! revisions = Revisions.findByEntityId Table.PageRevision Table.Page page.Id string
return { page with Revisions = revisions }
}
@@ -25,12 +25,12 @@ type PostgresPageData (log: ILogger) =
/// Update a page's revisions
let updatePageRevisions (pageId: PageId) oldRevs newRevs =
log.LogTrace "Page.updatePageRevisions"
- Revisions.update Table.PageRevision Table.Page pageId (_.Value) oldRevs newRevs
+ Revisions.update Table.PageRevision Table.Page pageId string oldRevs newRevs
/// Does the given page exist?
let pageExists (pageId: PageId) webLogId =
log.LogTrace "Page.pageExists"
- Document.existsByWebLog Table.Page pageId (_.Value) webLogId
+ Document.existsByWebLog Table.Page pageId string webLogId
// IMPLEMENTATION FUNCTIONS
@@ -51,9 +51,9 @@ type PostgresPageData (log: ILogger) =
Count.byContains Table.Page {| webLogDoc webLogId with IsInPageList = true |}
/// Find a page by its ID (without revisions)
- let findById (pageId: PageId) webLogId =
+ let findById pageId webLogId =
log.LogTrace "Page.findById"
- Document.findByIdAndWebLog Table.Page pageId (_.Value) webLogId
+ Document.findByIdAndWebLog Table.Page pageId string webLogId
/// Find a complete page by its ID
let findFullById pageId webLogId = backgroundTask {
@@ -70,7 +70,7 @@ type PostgresPageData (log: ILogger) =
log.LogTrace "Page.delete"
match! pageExists pageId webLogId with
| true ->
- do! Delete.byId Table.Page pageId.Value
+ do! Delete.byId Table.Page (string pageId)
return true
| false -> return false
}
@@ -78,16 +78,15 @@ type PostgresPageData (log: ILogger) =
/// Find a page by its permalink for the given web log
let findByPermalink (permalink: Permalink) webLogId =
log.LogTrace "Page.findByPermalink"
- Find.byContains Table.Page {| webLogDoc webLogId with Permalink = permalink.Value |}
+ Find.byContains Table.Page {| webLogDoc webLogId with Permalink = string permalink |}
|> tryHead
/// Find the current permalink within a set of potential prior permalinks for the given web log
- let findCurrentPermalink permalinks webLogId = backgroundTask {
+ let findCurrentPermalink (permalinks: Permalink list) webLogId = backgroundTask {
log.LogTrace "Page.findCurrentPermalink"
if List.isEmpty permalinks then return None
else
- let linkSql, linkParam =
- arrayContains (nameof Page.empty.PriorPermalinks) (fun (it: Permalink) -> it.Value) permalinks
+ let linkSql, linkParam = arrayContains (nameof Page.empty.PriorPermalinks) string permalinks
return!
Custom.single
$"""SELECT data ->> '{nameof Page.empty.Permalink}' AS permalink
@@ -134,9 +133,9 @@ type PostgresPageData (log: ILogger) =
|> Sql.executeTransactionAsync [
Query.insert Table.Page,
pages
- |> List.map (fun page -> Query.docParameters page.Id.Value { page with Revisions = [] })
+ |> List.map (fun page -> Query.docParameters (string page.Id) { page with Revisions = [] })
Revisions.insertSql Table.PageRevision,
- revisions |> List.map (fun (pageId, rev) -> Revisions.revParams pageId (_.Value) rev)
+ revisions |> List.map (fun (pageId, rev) -> Revisions.revParams pageId string rev)
]
()
}
@@ -155,7 +154,7 @@ type PostgresPageData (log: ILogger) =
log.LogTrace "Page.updatePriorPermalinks"
match! pageExists pageId webLogId with
| true ->
- do! Update.partialById Table.Page pageId.Value {| PriorPermalinks = permalinks |}
+ do! Update.partialById Table.Page (string pageId) {| PriorPermalinks = permalinks |}
return true
| false -> return false
}
diff --git a/src/MyWebLog.Data/Postgres/PostgresPostData.fs b/src/MyWebLog.Data/Postgres/PostgresPostData.fs
index c1f6248..7984d35 100644
--- a/src/MyWebLog.Data/Postgres/PostgresPostData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresPostData.fs
@@ -15,7 +15,7 @@ type PostgresPostData(log: ILogger) =
/// Append revisions to a post
let appendPostRevisions (post: Post) = backgroundTask {
log.LogTrace "Post.appendPostRevisions"
- let! revisions = Revisions.findByEntityId Table.PostRevision Table.Post post.Id _.Value
+ let! revisions = Revisions.findByEntityId Table.PostRevision Table.Post post.Id string
return { post with Revisions = revisions }
}
@@ -26,30 +26,30 @@ type PostgresPostData(log: ILogger) =
/// Update a post's revisions
let updatePostRevisions (postId: PostId) oldRevs newRevs =
log.LogTrace "Post.updatePostRevisions"
- Revisions.update Table.PostRevision Table.Post postId (_.Value) oldRevs newRevs
+ Revisions.update Table.PostRevision Table.Post postId string oldRevs newRevs
/// Does the given post exist?
let postExists (postId: PostId) webLogId =
log.LogTrace "Post.postExists"
- Document.existsByWebLog Table.Post postId (_.Value) webLogId
+ Document.existsByWebLog Table.Post postId string webLogId
// IMPLEMENTATION FUNCTIONS
/// Count posts in a status for the given web log
let countByStatus (status: PostStatus) webLogId =
log.LogTrace "Post.countByStatus"
- Count.byContains Table.Post {| webLogDoc webLogId with Status = status.Value |}
+ Count.byContains Table.Post {| webLogDoc webLogId with Status = status |}
/// Find a post by its ID for the given web log (excluding revisions)
let findById postId webLogId =
log.LogTrace "Post.findById"
- Document.findByIdAndWebLog Table.Post postId (_.Value) webLogId
+ Document.findByIdAndWebLog Table.Post postId string webLogId
/// Find a post by its permalink for the given web log (excluding revisions and prior permalinks)
let findByPermalink (permalink: Permalink) webLogId =
log.LogTrace "Post.findByPermalink"
Custom.single (selectWithCriteria Table.Post)
- [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Permalink = permalink.Value |} ]
+ [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Permalink = string permalink |} ]
fromData
/// Find a complete post by its ID for the given web log
@@ -70,18 +70,17 @@ type PostgresPostData(log: ILogger) =
do! Custom.nonQuery
$"""DELETE FROM {Table.PostComment} WHERE {Query.whereDataContains "@criteria"};
DELETE FROM {Table.Post} WHERE id = @id"""
- [ "@id", Sql.string postId.Value; "@criteria", Query.jsonbDocParam {| PostId = postId.Value |} ]
+ [ "@id", Sql.string (string postId); "@criteria", Query.jsonbDocParam {| PostId = postId |} ]
return true
| false -> return false
}
/// Find the current permalink from a list of potential prior permalinks for the given web log
- let findCurrentPermalink permalinks webLogId = backgroundTask {
+ let findCurrentPermalink (permalinks: Permalink list) webLogId = backgroundTask {
log.LogTrace "Post.findCurrentPermalink"
if List.isEmpty permalinks then return None
else
- let linkSql, linkParam =
- arrayContains (nameof Post.empty.PriorPermalinks) (fun (it: Permalink) -> it.Value) permalinks
+ let linkSql, linkParam = arrayContains (nameof Post.empty.PriorPermalinks) string permalinks
return!
Custom.single
$"""SELECT data ->> '{nameof Post.empty.Permalink}' AS permalink
@@ -102,16 +101,15 @@ type PostgresPostData(log: ILogger) =
}
/// Get a page of categorized posts for the given web log (excludes revisions)
- let findPageOfCategorizedPosts webLogId categoryIds pageNbr postsPerPage =
+ let findPageOfCategorizedPosts webLogId (categoryIds: CategoryId list) pageNbr postsPerPage =
log.LogTrace "Post.findPageOfCategorizedPosts"
- let catSql, catParam =
- arrayContains (nameof Post.empty.CategoryIds) (fun (it: CategoryId) -> it.Value) categoryIds
+ let catSql, catParam = arrayContains (nameof Post.empty.CategoryIds) string categoryIds
Custom.list
$"{selectWithCriteria Table.Post}
AND {catSql}
ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
- [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published.Value |}
+ [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |}
catParam
] fromData
@@ -132,7 +130,7 @@ type PostgresPostData(log: ILogger) =
$"{selectWithCriteria Table.Post}
ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
- [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published.Value |} ]
+ [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |} ]
fromData
/// Get a page of tagged posts for the given web log (excludes revisions and prior permalinks)
@@ -143,7 +141,7 @@ type PostgresPostData(log: ILogger) =
AND data['{nameof Post.empty.Tags}'] @> @tag
ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
- [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published.Value |}
+ [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |}
"@tag", Query.jsonbDocParam [| tag |]
] fromData
@@ -151,8 +149,8 @@ type PostgresPostData(log: ILogger) =
let findSurroundingPosts webLogId publishedOn = backgroundTask {
log.LogTrace "Post.findSurroundingPosts"
let queryParams () = [
- "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published.Value |}
- "@publishedOn", Sql.string ((InstantPattern.General.Format publishedOn).Substring (0, 19))
+ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |}
+ "@publishedOn", Sql.string ((InstantPattern.General.Format publishedOn)[..19])
]
let pubField = nameof Post.empty.PublishedOn
let! older =
@@ -187,9 +185,9 @@ type PostgresPostData(log: ILogger) =
|> Sql.fromDataSource
|> Sql.executeTransactionAsync [
Query.insert Table.Post,
- posts |> List.map (fun post -> Query.docParameters post.Id.Value { post with Revisions = [] })
+ posts |> List.map (fun post -> Query.docParameters (string post.Id) { post with Revisions = [] })
Revisions.insertSql Table.PostRevision,
- revisions |> List.map (fun (postId, rev) -> Revisions.revParams postId (_.Value) rev)
+ revisions |> List.map (fun (postId, rev) -> Revisions.revParams postId string rev)
]
()
}
@@ -199,7 +197,7 @@ type PostgresPostData(log: ILogger) =
log.LogTrace "Post.updatePriorPermalinks"
match! postExists postId webLogId with
| true ->
- do! Update.partialById Table.Post postId.Value {| PriorPermalinks = permalinks |}
+ do! Update.partialById Table.Post (string postId) {| PriorPermalinks = permalinks |}
return true
| false -> return false
}
diff --git a/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs b/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs
index 210dc14..100523a 100644
--- a/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs
@@ -12,14 +12,14 @@ type PostgresTagMapData (log : ILogger) =
/// Find a tag mapping by its ID for the given web log
let findById tagMapId webLogId =
log.LogTrace "TagMap.findById"
- Document.findByIdAndWebLog Table.TagMap tagMapId TagMapId.toString webLogId
+ Document.findByIdAndWebLog Table.TagMap tagMapId string webLogId
/// Delete a tag mapping for the given web log
- let delete tagMapId webLogId = backgroundTask {
+ let delete (tagMapId: TagMapId) webLogId = backgroundTask {
log.LogTrace "TagMap.delete"
- let! exists = Document.existsByWebLog Table.TagMap tagMapId TagMapId.toString webLogId
+ let! exists = Document.existsByWebLog Table.TagMap tagMapId string webLogId
if exists then
- do! Delete.byId Table.TagMap (TagMapId.toString tagMapId)
+ do! Delete.byId Table.TagMap (string tagMapId)
return true
else return false
}
@@ -55,7 +55,7 @@ type PostgresTagMapData (log : ILogger) =
|> Sql.fromDataSource
|> Sql.executeTransactionAsync [
Query.insert Table.TagMap,
- tagMaps |> List.map (fun tagMap -> Query.docParameters (TagMapId.toString tagMap.Id) tagMap)
+ tagMaps |> List.map (fun tagMap -> Query.docParameters (string tagMap.Id) tagMap)
]
()
}
diff --git a/src/MyWebLog.Data/Postgres/PostgresThemeData.fs b/src/MyWebLog.Data/Postgres/PostgresThemeData.fs
index cf3a569..ed7e4bb 100644
--- a/src/MyWebLog.Data/Postgres/PostgresThemeData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresThemeData.fs
@@ -20,26 +20,26 @@ type PostgresThemeData (log : ILogger) =
Custom.list $"{Query.selectFromTable Table.Theme} WHERE id <> 'admin' ORDER BY id" [] withoutTemplateText
/// Does a given theme exist?
- let exists themeId =
+ let exists (themeId: ThemeId) =
log.LogTrace "Theme.exists"
- Exists.byId Table.Theme (ThemeId.toString themeId)
+ Exists.byId Table.Theme (string themeId)
/// Find a theme by its ID
- let findById themeId =
+ let findById (themeId: ThemeId) =
log.LogTrace "Theme.findById"
- Find.byId Table.Theme (ThemeId.toString themeId)
+ Find.byId Table.Theme (string themeId)
/// Find a theme by its ID (excludes the text of templates)
- let findByIdWithoutText themeId =
+ let findByIdWithoutText (themeId: ThemeId) =
log.LogTrace "Theme.findByIdWithoutText"
- Custom.single (Query.Find.byId Table.Theme) [ "@id", Sql.string (ThemeId.toString themeId) ] withoutTemplateText
+ Custom.single (Query.Find.byId Table.Theme) [ "@id", Sql.string (string themeId) ] withoutTemplateText
/// Delete a theme by its ID
let delete themeId = backgroundTask {
log.LogTrace "Theme.delete"
match! exists themeId with
| true ->
- do! Delete.byId Table.Theme (ThemeId.toString themeId)
+ do! Delete.byId Table.Theme (string themeId)
return true
| false -> return false
}
@@ -67,10 +67,10 @@ type PostgresThemeAssetData (log : ILogger) =
Custom.list $"SELECT theme_id, path, updated_on FROM {Table.ThemeAsset}" [] (Map.toThemeAsset false)
/// Delete all assets for the given theme
- let deleteByTheme themeId =
+ let deleteByTheme (themeId: ThemeId) =
log.LogTrace "ThemeAsset.deleteByTheme"
Custom.nonQuery $"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @themeId"
- [ "@themeId", Sql.string (ThemeId.toString themeId) ]
+ [ "@themeId", Sql.string (string themeId) ]
/// Find a theme asset by its ID
let findById assetId =
@@ -80,16 +80,16 @@ type PostgresThemeAssetData (log : ILogger) =
[ "@themeId", Sql.string themeId; "@path", Sql.string path ] (Map.toThemeAsset true)
/// Get theme assets for the given theme (excludes data)
- let findByTheme themeId =
+ let findByTheme (themeId: ThemeId) =
log.LogTrace "ThemeAsset.findByTheme"
Custom.list $"SELECT theme_id, path, updated_on FROM {Table.ThemeAsset} WHERE theme_id = @themeId"
- [ "@themeId", Sql.string (ThemeId.toString themeId) ] (Map.toThemeAsset false)
+ [ "@themeId", Sql.string (string themeId) ] (Map.toThemeAsset false)
/// Get theme assets for the given theme
- let findByThemeWithData themeId =
+ let findByThemeWithData (themeId: ThemeId) =
log.LogTrace "ThemeAsset.findByThemeWithData"
Custom.list $"SELECT * FROM {Table.ThemeAsset} WHERE theme_id = @themeId"
- [ "@themeId", Sql.string (ThemeId.toString themeId) ] (Map.toThemeAsset true)
+ [ "@themeId", Sql.string (string themeId) ] (Map.toThemeAsset true)
/// Save a theme asset
let save (asset : ThemeAsset) =
diff --git a/src/MyWebLog.Data/Postgres/PostgresUploadData.fs b/src/MyWebLog.Data/Postgres/PostgresUploadData.fs
index 136da11..e97b212 100644
--- a/src/MyWebLog.Data/Postgres/PostgresUploadData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresUploadData.fs
@@ -21,8 +21,8 @@ type PostgresUploadData (log : ILogger) =
let upParams (upload : Upload) = [
webLogIdParam upload.WebLogId
typedParam "updatedOn" upload.UpdatedOn
- "@id", Sql.string (UploadId.toString upload.Id)
- "@path", Sql.string upload.Path.Value
+ "@id", Sql.string (string upload.Id)
+ "@path", Sql.string (string upload.Path)
"@data", Sql.bytea upload.Data
]
@@ -34,14 +34,14 @@ type PostgresUploadData (log : ILogger) =
/// Delete an uploaded file by its ID
let delete uploadId webLogId = backgroundTask {
log.LogTrace "Upload.delete"
- let idParam = [ "@id", Sql.string (UploadId.toString uploadId) ]
+ let idParam = [ "@id", Sql.string (string uploadId) ]
let! path =
Custom.single $"SELECT path FROM {Table.Upload} WHERE id = @id AND web_log_id = @webLogId"
(webLogIdParam webLogId :: idParam) (fun row -> row.string "path")
if Option.isSome path then
do! Custom.nonQuery (Query.Delete.byId Table.Upload) idParam
return Ok path.Value
- else return Error $"""Upload ID {UploadId.toString uploadId} not found"""
+ else return Error $"""Upload ID {uploadId} not found"""
}
/// Find an uploaded file by its path for the given web log
diff --git a/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs b/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs
index f583cc2..0efc85d 100644
--- a/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs
@@ -41,29 +41,30 @@ type PostgresWebLogData (log : ILogger) =
fromData
/// Find a web log by its ID
- let findById webLogId =
+ let findById (webLogId: WebLogId) =
log.LogTrace "WebLog.findById"
- Find.byId Table.WebLog (WebLogId.toString webLogId)
+ Find.byId Table.WebLog (string webLogId)
- let updateRedirectRules (webLog : WebLog) = backgroundTask {
+ let updateRedirectRules (webLog: WebLog) = backgroundTask {
log.LogTrace "WebLog.updateRedirectRules"
match! findById webLog.Id with
| Some _ ->
- do! Update.partialById Table.WebLog (WebLogId.toString webLog.Id) {| RedirectRules = webLog.RedirectRules |}
+ do! Update.partialById Table.WebLog (string webLog.Id) {| RedirectRules = webLog.RedirectRules |}
| None -> ()
}
+
/// Update RSS options for a web log
- let updateRssOptions (webLog : WebLog) = backgroundTask {
+ let updateRssOptions (webLog: WebLog) = backgroundTask {
log.LogTrace "WebLog.updateRssOptions"
match! findById webLog.Id with
- | Some _ -> do! Update.partialById Table.WebLog (WebLogId.toString webLog.Id) {| Rss = webLog.Rss |}
+ | Some _ -> do! Update.partialById Table.WebLog (string webLog.Id) {| Rss = webLog.Rss |}
| None -> ()
}
/// Update settings for a web log
- let updateSettings (webLog : WebLog) =
+ let updateSettings (webLog: WebLog) =
log.LogTrace "WebLog.updateSettings"
- Update.full Table.WebLog (WebLogId.toString webLog.Id) webLog
+ Update.full Table.WebLog (string webLog.Id) webLog
interface IWebLogData with
member _.Add webLog = add webLog
diff --git a/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs b/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs
index 32b912e..dba0985 100644
--- a/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs
@@ -12,7 +12,7 @@ type PostgresWebLogUserData (log : ILogger) =
/// Find a user by their ID for the given web log
let findById userId webLogId =
log.LogTrace "WebLogUser.findById"
- Document.findByIdAndWebLog Table.WebLogUser userId WebLogUserId.toString webLogId
+ Document.findByIdAndWebLog Table.WebLogUser userId string webLogId
/// Delete a user if they have no posts or pages
let delete userId webLogId = backgroundTask {
@@ -29,7 +29,7 @@ type PostgresWebLogUserData (log : ILogger) =
if isAuthor then
return Error "User has pages or posts; cannot delete"
else
- do! Delete.byId Table.WebLogUser (WebLogUserId.toString userId)
+ do! Delete.byId Table.WebLogUser (string userId)
return Ok true
| None -> return Error "User does not exist"
}
@@ -49,41 +49,38 @@ type PostgresWebLogUserData (log : ILogger) =
[ webLogContains webLogId ] fromData
/// Find the names of users by their IDs for the given web log
- let findNames webLogId userIds = backgroundTask {
+ let findNames webLogId (userIds: WebLogUserId list) = backgroundTask {
log.LogTrace "WebLogUser.findNames"
- let idSql, idParams = inClause "AND id" "id" WebLogUserId.toString userIds
+ let idSql, idParams = inClause "AND id" "id" string userIds
let! users =
Custom.list $"{selectWithCriteria Table.WebLogUser} {idSql}" (webLogContains webLogId :: idParams)
fromData
- return
- users
- |> List.map (fun u -> { Name = WebLogUserId.toString u.Id; Value = WebLogUser.displayName u })
+ return users |> List.map (fun u -> { Name = string u.Id; Value = WebLogUser.displayName u })
}
/// Restore users from a backup
- let restore (users : WebLogUser list) = backgroundTask {
+ let restore (users: WebLogUser list) = backgroundTask {
log.LogTrace "WebLogUser.restore"
let! _ =
Configuration.dataSource ()
|> Sql.fromDataSource
|> Sql.executeTransactionAsync [
Query.insert Table.WebLogUser,
- users |> List.map (fun user -> Query.docParameters (WebLogUserId.toString user.Id) user)
+ users |> List.map (fun user -> Query.docParameters (string user.Id) user)
]
()
}
/// Set a user's last seen date/time to now
- let setLastSeen userId webLogId = backgroundTask {
+ let setLastSeen (userId: WebLogUserId) webLogId = backgroundTask {
log.LogTrace "WebLogUser.setLastSeen"
- match! Document.existsByWebLog Table.WebLogUser userId WebLogUserId.toString webLogId with
- | true ->
- do! Update.partialById Table.WebLogUser (WebLogUserId.toString userId) {| LastSeenOn = Some (Noda.now ()) |}
+ match! Document.existsByWebLog Table.WebLogUser userId string webLogId with
+ | true -> do! Update.partialById Table.WebLogUser (string userId) {| LastSeenOn = Some (Noda.now ()) |}
| false -> ()
}
/// Save a user
- let save (user : WebLogUser) =
+ let save (user: WebLogUser) =
log.LogTrace "WebLogUser.save"
save Table.WebLogUser user
diff --git a/src/MyWebLog.Data/RethinkDbData.fs b/src/MyWebLog.Data/RethinkDbData.fs
index e653b1f..acda3a6 100644
--- a/src/MyWebLog.Data/RethinkDbData.fs
+++ b/src/MyWebLog.Data/RethinkDbData.fs
@@ -96,12 +96,12 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger row[nameof ThemeAsset.empty.Id].Match keyPrefix :> obj
/// Function to exclude template text from themes
let withoutTemplateText (row : Ast.ReqlExpr) : obj =
- {| Templates = row[nameof Theme.empty.Templates].Without [| nameof ThemeTemplate.empty.Text |] |}
+ {| Templates = row[nameof Theme.empty.Templates].Without [| nameof ThemeTemplate.Empty.Text |] |}
/// Ensure field indexes exist, as well as special indexes for selected tables
let ensureIndexes table fields = backgroundTask {
@@ -917,8 +917,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger return Result.Error $"Upload ID {UploadId.toString uploadId} not found"
+ return Ok (string up.Path)
+ | None -> return Result.Error $"Upload ID {uploadId} not found"
}
member _.FindByPath path webLogId =
@@ -1133,9 +1133,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger List.map (fun u -> { Name = WebLogUserId.toString u.Id; Value = WebLogUser.displayName u })
+ return users |> List.map (fun u -> { Name = string u.Id; Value = WebLogUser.displayName u })
}
member _.Restore users = backgroundTask {
diff --git a/src/MyWebLog.Data/SQLite/Helpers.fs b/src/MyWebLog.Data/SQLite/Helpers.fs
index cdd31a2..b37c7bc 100644
--- a/src/MyWebLog.Data/SQLite/Helpers.fs
+++ b/src/MyWebLog.Data/SQLite/Helpers.fs
@@ -222,7 +222,7 @@ module Map =
/// Create a custom feed from the current row in the given data reader
let toCustomFeed ser rdr : CustomFeed =
{ Id = getString "id" rdr |> CustomFeedId
- Source = getString "source" rdr |> CustomFeedSource.parse
+ Source = getString "source" rdr |> CustomFeedSource.Parse
Path = getString "path" rdr |> Permalink
Podcast = tryString "podcast" rdr |> Option.map (Utils.deserialize ser)
}
@@ -339,7 +339,7 @@ module Map =
UrlBase = getString "url_base" rdr
TimeZone = getString "time_zone" rdr
AutoHtmx = getBoolean "auto_htmx" rdr
- Uploads = getString "uploads" rdr |> UploadDestination.parse
+ Uploads = getString "uploads" rdr |> UploadDestination.Parse
Rss = {
IsFeedEnabled = getBoolean "is_feed_enabled" rdr
FeedName = getString "feed_name" rdr
@@ -368,5 +368,5 @@ module Map =
}
/// Add a web log ID parameter
-let addWebLogId (cmd : SqliteCommand) webLogId =
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString webLogId) |> ignore
+let addWebLogId (cmd: SqliteCommand) (webLogId: WebLogId) =
+ cmd.Parameters.AddWithValue ("@webLogId", string webLogId) |> ignore
diff --git a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
index 3caae20..d3d96b2 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
@@ -5,17 +5,17 @@ open Microsoft.Data.Sqlite
open MyWebLog
open MyWebLog.Data
-/// SQLite myWebLog category data implementation
-type SQLiteCategoryData (conn : SqliteConnection) =
+/// SQLite myWebLog category data implementation
+type SQLiteCategoryData(conn: SqliteConnection) =
/// Add parameters for category INSERT or UPDATE statements
- let addCategoryParameters (cmd : SqliteCommand) (cat : Category) =
- [ cmd.Parameters.AddWithValue ("@id", cat.Id.Value)
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString cat.WebLogId)
+ let addCategoryParameters (cmd: SqliteCommand) (cat: Category) =
+ [ cmd.Parameters.AddWithValue ("@id", string cat.Id)
+ cmd.Parameters.AddWithValue ("@webLogId", string cat.WebLogId)
cmd.Parameters.AddWithValue ("@name", cat.Name)
cmd.Parameters.AddWithValue ("@slug", cat.Slug)
cmd.Parameters.AddWithValue ("@description", maybe cat.Description)
- cmd.Parameters.AddWithValue ("@parentId", maybe (cat.ParentId |> Option.map _.Value))
+ cmd.Parameters.AddWithValue ("@parentId", maybe (cat.ParentId |> Option.map string))
] |> ignore
/// Add a category
@@ -102,18 +102,18 @@ type SQLiteCategoryData (conn : SqliteConnection) =
}
/// Find a category by its ID for the given web log
let findById (catId: CategoryId) webLogId = backgroundTask {
- use cmd = conn.CreateCommand ()
+ use cmd = conn.CreateCommand()
cmd.CommandText <- "SELECT * FROM category WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", catId.Value) |> ignore
- use! rdr = cmd.ExecuteReaderAsync ()
- return Helpers.verifyWebLog webLogId (fun c -> c.WebLogId) Map.toCategory rdr
+ cmd.Parameters.AddWithValue ("@id", string catId) |> ignore
+ use! rdr = cmd.ExecuteReaderAsync()
+ return verifyWebLog webLogId (_.WebLogId) Map.toCategory rdr
}
/// Find all categories for the given web log
- let findByWebLog webLogId = backgroundTask {
+ let findByWebLog (webLogId: WebLogId) = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT * FROM category WHERE web_log_id = @webLogId"
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString webLogId) |> ignore
+ cmd.Parameters.AddWithValue ("@webLogId", string webLogId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
return toList Map.toCategory rdr
}
@@ -125,11 +125,11 @@ type SQLiteCategoryData (conn : SqliteConnection) =
use cmd = conn.CreateCommand ()
// Reassign any children to the category's parent category
cmd.CommandText <- "SELECT COUNT(id) FROM category WHERE parent_id = @parentId"
- cmd.Parameters.AddWithValue ("@parentId", catId.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@parentId", string catId) |> ignore
let! children = count cmd
if children > 0 then
cmd.CommandText <- "UPDATE category SET parent_id = @newParentId WHERE parent_id = @parentId"
- cmd.Parameters.AddWithValue ("@newParentId", maybe (cat.ParentId |> Option.map _.Value))
+ cmd.Parameters.AddWithValue ("@newParentId", maybe (cat.ParentId |> Option.map string))
|> ignore
do! write cmd
// Delete the category off all posts where it is assigned, and the category itself
@@ -139,7 +139,7 @@ type SQLiteCategoryData (conn : SqliteConnection) =
AND post_id IN (SELECT id FROM post WHERE web_log_id = @webLogId);
DELETE FROM category WHERE id = @id"
cmd.Parameters.Clear ()
- let _ = cmd.Parameters.AddWithValue ("@id", catId.Value)
+ let _ = cmd.Parameters.AddWithValue ("@id", string catId)
addWebLogId cmd webLogId
do! write cmd
return if children = 0 then CategoryDeleted else ReassignedChildCategories
diff --git a/src/MyWebLog.Data/SQLite/SQLitePageData.fs b/src/MyWebLog.Data/SQLite/SQLitePageData.fs
index c3ae850..c8ebd49 100644
--- a/src/MyWebLog.Data/SQLite/SQLitePageData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLitePageData.fs
@@ -13,11 +13,11 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
/// Add parameters for page INSERT or UPDATE statements
let addPageParameters (cmd: SqliteCommand) (page: Page) =
- [ cmd.Parameters.AddWithValue ("@id", page.Id.Value)
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString page.WebLogId)
- cmd.Parameters.AddWithValue ("@authorId", WebLogUserId.toString page.AuthorId)
+ [ cmd.Parameters.AddWithValue ("@id", string page.Id)
+ cmd.Parameters.AddWithValue ("@webLogId", string page.WebLogId)
+ cmd.Parameters.AddWithValue ("@authorId", string page.AuthorId)
cmd.Parameters.AddWithValue ("@title", page.Title)
- cmd.Parameters.AddWithValue ("@permalink", page.Permalink.Value)
+ cmd.Parameters.AddWithValue ("@permalink", string page.Permalink)
cmd.Parameters.AddWithValue ("@publishedOn", instantParam page.PublishedOn)
cmd.Parameters.AddWithValue ("@updatedOn", instantParam page.UpdatedOn)
cmd.Parameters.AddWithValue ("@isInPageList", page.IsInPageList)
@@ -30,7 +30,7 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
/// Append revisions and permalinks to a page
let appendPageRevisionsAndPermalinks (page : Page) = backgroundTask {
use cmd = conn.CreateCommand ()
- cmd.Parameters.AddWithValue ("@pageId", page.Id.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@pageId", string page.Id) |> ignore
cmd.CommandText <- "SELECT permalink FROM page_permalink WHERE page_id = @pageId"
use! rdr = cmd.ExecuteReaderAsync ()
@@ -57,11 +57,11 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
return ()
else
use cmd = conn.CreateCommand ()
- [ cmd.Parameters.AddWithValue ("@pageId", pageId.Value)
+ [ cmd.Parameters.AddWithValue ("@pageId", string pageId)
cmd.Parameters.Add ("@link", SqliteType.Text)
] |> ignore
let runCmd (link: Permalink) = backgroundTask {
- cmd.Parameters["@link"].Value <- link.Value
+ cmd.Parameters["@link"].Value <- string link
do! write cmd
}
cmd.CommandText <- "DELETE FROM page_permalink WHERE page_id = @pageId AND permalink = @link"
@@ -85,10 +85,10 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
use cmd = conn.CreateCommand ()
let runCmd withText rev = backgroundTask {
cmd.Parameters.Clear ()
- [ cmd.Parameters.AddWithValue ("@pageId", pageId.Value)
+ [ cmd.Parameters.AddWithValue ("@pageId", string pageId)
cmd.Parameters.AddWithValue ("@asOf", instantParam rev.AsOf)
] |> ignore
- if withText then cmd.Parameters.AddWithValue ("@text", rev.Text.Value) |> ignore
+ if withText then cmd.Parameters.AddWithValue ("@text", string rev.Text) |> ignore
do! write cmd
}
cmd.CommandText <- "DELETE FROM page_revision WHERE page_id = @pageId AND as_of = @asOf"
@@ -157,7 +157,7 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
let findById (pageId: PageId) webLogId = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT * FROM page WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", pageId.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string pageId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
return verifyWebLog webLogId (_.WebLogId) (Map.toPage ser) rdr
}
@@ -175,7 +175,7 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
match! findById pageId webLogId with
| Some _ ->
use cmd = conn.CreateCommand ()
- cmd.Parameters.AddWithValue ("@id", pageId.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string pageId) |> ignore
cmd.CommandText <-
"DELETE FROM page_revision WHERE page_id = @id;
DELETE FROM page_permalink WHERE page_id = @id;
@@ -190,15 +190,15 @@ type SQLitePageData(conn: SqliteConnection, ser: JsonSerializer) =
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT * FROM page WHERE web_log_id = @webLogId AND permalink = @link"
addWebLogId cmd webLogId
- cmd.Parameters.AddWithValue ("@link", permalink.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@link", string permalink) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
return if rdr.Read () then Some (toPage rdr) else None
}
/// Find the current permalink within a set of potential prior permalinks for the given web log
- let findCurrentPermalink permalinks webLogId = backgroundTask {
+ let findCurrentPermalink (permalinks: Permalink list) webLogId = backgroundTask {
use cmd = conn.CreateCommand ()
- let linkSql, linkParams = inClause "AND pp.permalink" "link" (fun (it: Permalink) -> it.Value) permalinks
+ let linkSql, linkParams = inClause "AND pp.permalink" "link" string permalinks
cmd.CommandText <- $"
SELECT p.permalink
FROM page p
diff --git a/src/MyWebLog.Data/SQLite/SQLitePostData.fs b/src/MyWebLog.Data/SQLite/SQLitePostData.fs
index c12ecab..97c02b4 100644
--- a/src/MyWebLog.Data/SQLite/SQLitePostData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLitePostData.fs
@@ -14,12 +14,12 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
/// Add parameters for post INSERT or UPDATE statements
let addPostParameters (cmd: SqliteCommand) (post: Post) =
- [ cmd.Parameters.AddWithValue ("@id", post.Id.Value)
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString post.WebLogId)
- cmd.Parameters.AddWithValue ("@authorId", WebLogUserId.toString post.AuthorId)
- cmd.Parameters.AddWithValue ("@status", post.Status.Value)
+ [ cmd.Parameters.AddWithValue ("@id", string post.Id)
+ cmd.Parameters.AddWithValue ("@webLogId", string post.WebLogId)
+ cmd.Parameters.AddWithValue ("@authorId", string post.AuthorId)
+ cmd.Parameters.AddWithValue ("@status", string post.Status)
cmd.Parameters.AddWithValue ("@title", post.Title)
- cmd.Parameters.AddWithValue ("@permalink", post.Permalink.Value)
+ cmd.Parameters.AddWithValue ("@permalink", string post.Permalink)
cmd.Parameters.AddWithValue ("@publishedOn", maybeInstant post.PublishedOn)
cmd.Parameters.AddWithValue ("@updatedOn", instantParam post.UpdatedOn)
cmd.Parameters.AddWithValue ("@template", maybe post.Template)
@@ -34,7 +34,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
/// Append category IDs and tags to a post
let appendPostCategoryAndTag (post: Post) = backgroundTask {
use cmd = conn.CreateCommand ()
- cmd.Parameters.AddWithValue ("@id", post.Id.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string post.Id) |> ignore
cmd.CommandText <- "SELECT category_id AS id FROM post_category WHERE post_id = @id"
use! rdr = cmd.ExecuteReaderAsync ()
@@ -49,7 +49,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
/// Append revisions and permalinks to a post
let appendPostRevisionsAndPermalinks (post: Post) = backgroundTask {
use cmd = conn.CreateCommand ()
- cmd.Parameters.AddWithValue ("@postId", post.Id.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@postId", string post.Id) |> ignore
cmd.CommandText <- "SELECT permalink FROM post_permalink WHERE post_id = @postId"
use! rdr = cmd.ExecuteReaderAsync ()
@@ -72,7 +72,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
let findPostById (postId: PostId) webLogId = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- $"{selectPost} WHERE p.id = @id"
- cmd.Parameters.AddWithValue ("@id", postId.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string postId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
return verifyWebLog webLogId (_.WebLogId) toPost rdr
}
@@ -83,16 +83,16 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
/// Update a post's assigned categories
let updatePostCategories (postId: PostId) oldCats newCats = backgroundTask {
- let toDelete, toAdd = Utils.diffLists oldCats newCats _.Value
+ let toDelete, toAdd = Utils.diffLists oldCats newCats string
if List.isEmpty toDelete && List.isEmpty toAdd then
return ()
else
use cmd = conn.CreateCommand ()
- [ cmd.Parameters.AddWithValue ("@postId", postId.Value)
+ [ cmd.Parameters.AddWithValue ("@postId", string postId)
cmd.Parameters.Add ("@categoryId", SqliteType.Text)
] |> ignore
let runCmd (catId: CategoryId) = backgroundTask {
- cmd.Parameters["@categoryId"].Value <- catId.Value
+ cmd.Parameters["@categoryId"].Value <- string catId
do! write cmd
}
cmd.CommandText <- "DELETE FROM post_category WHERE post_id = @postId AND category_id = @categoryId"
@@ -114,7 +114,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
return ()
else
use cmd = conn.CreateCommand ()
- [ cmd.Parameters.AddWithValue ("@postId", postId.Value)
+ [ cmd.Parameters.AddWithValue ("@postId", string postId)
cmd.Parameters.Add ("@tag", SqliteType.Text)
] |> ignore
let runCmd (tag: string) = backgroundTask {
@@ -140,11 +140,11 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
return ()
else
use cmd = conn.CreateCommand ()
- [ cmd.Parameters.AddWithValue ("@postId", postId.Value)
+ [ cmd.Parameters.AddWithValue ("@postId", string postId)
cmd.Parameters.Add ("@link", SqliteType.Text)
] |> ignore
let runCmd (link: Permalink) = backgroundTask {
- cmd.Parameters["@link"].Value <- link.Value
+ cmd.Parameters["@link"].Value <- string link
do! write cmd
}
cmd.CommandText <- "DELETE FROM post_permalink WHERE post_id = @postId AND permalink = @link"
@@ -168,10 +168,10 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
use cmd = conn.CreateCommand ()
let runCmd withText rev = backgroundTask {
cmd.Parameters.Clear ()
- [ cmd.Parameters.AddWithValue ("@postId", postId.Value)
+ [ cmd.Parameters.AddWithValue ("@postId", string postId)
cmd.Parameters.AddWithValue ("@asOf", instantParam rev.AsOf)
] |> ignore
- if withText then cmd.Parameters.AddWithValue ("@text", rev.Text.Value) |> ignore
+ if withText then cmd.Parameters.AddWithValue ("@text", string rev.Text) |> ignore
do! write cmd
}
cmd.CommandText <- "DELETE FROM post_revision WHERE post_id = @postId AND as_of = @asOf"
@@ -212,7 +212,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT COUNT(id) FROM post WHERE web_log_id = @webLogId AND status = @status"
addWebLogId cmd webLogId
- cmd.Parameters.AddWithValue ("@status", status.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@status", string status) |> ignore
return! count cmd
}
@@ -230,7 +230,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
use cmd = conn.CreateCommand ()
cmd.CommandText <- $"{selectPost} WHERE p.web_log_id = @webLogId AND p.permalink = @link"
addWebLogId cmd webLogId
- cmd.Parameters.AddWithValue ("@link", permalink.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@link", string permalink) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
if rdr.Read () then
let! post = appendPostCategoryAndTag (toPost rdr)
@@ -253,7 +253,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
match! findFullById postId webLogId with
| Some _ ->
use cmd = conn.CreateCommand ()
- cmd.Parameters.AddWithValue ("@id", postId.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string postId) |> ignore
cmd.CommandText <-
"DELETE FROM post_revision WHERE post_id = @id;
DELETE FROM post_permalink WHERE post_id = @id;
@@ -267,9 +267,9 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
}
/// Find the current permalink from a list of potential prior permalinks for the given web log
- let findCurrentPermalink permalinks webLogId = backgroundTask {
+ let findCurrentPermalink (permalinks: Permalink list) webLogId = backgroundTask {
use cmd = conn.CreateCommand ()
- let linkSql, linkParams = inClause "AND pp.permalink" "link" (fun (it: Permalink) -> it.Value) permalinks
+ let linkSql, linkParams = inClause "AND pp.permalink" "link" string permalinks
cmd.CommandText <- $"
SELECT p.permalink
FROM post p
@@ -299,9 +299,9 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
}
/// Get a page of categorized posts for the given web log (excludes revisions and prior permalinks)
- let findPageOfCategorizedPosts webLogId categoryIds pageNbr postsPerPage = backgroundTask {
+ let findPageOfCategorizedPosts webLogId (categoryIds: CategoryId list) pageNbr postsPerPage = backgroundTask {
use cmd = conn.CreateCommand ()
- let catSql, catParams = inClause "AND pc.category_id" "catId" (fun (it: CategoryId) -> it.Value) categoryIds
+ let catSql, catParams = inClause "AND pc.category_id" "catId" string categoryIds
cmd.CommandText <- $"
{selectPost}
INNER JOIN post_category pc ON pc.post_id = p.id
@@ -311,7 +311,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
ORDER BY published_on DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
addWebLogId cmd webLogId
- cmd.Parameters.AddWithValue ("@status", Published.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@status", string Published) |> ignore
cmd.Parameters.AddRange catParams
use! rdr = cmd.ExecuteReaderAsync ()
let! posts =
@@ -348,7 +348,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
ORDER BY p.published_on DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
addWebLogId cmd webLogId
- cmd.Parameters.AddWithValue ("@status", Published.Value) |> ignore
+ cmd.Parameters.AddWithValue ("@status", string Published) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
let! posts =
toList toPost rdr
@@ -369,7 +369,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
ORDER BY p.published_on DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
addWebLogId cmd webLogId
- [ cmd.Parameters.AddWithValue ("@status", Published.Value)
+ [ cmd.Parameters.AddWithValue ("@status", string Published)
cmd.Parameters.AddWithValue ("@tag", tag)
] |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
@@ -391,7 +391,7 @@ type SQLitePostData(conn: SqliteConnection, ser: JsonSerializer) =
ORDER BY p.published_on DESC
LIMIT 1"
addWebLogId cmd webLogId
- [ cmd.Parameters.AddWithValue ("@status", Published.Value)
+ [ cmd.Parameters.AddWithValue ("@status", string Published)
cmd.Parameters.AddWithValue ("@publishedOn", instantParam publishedOn)
] |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
diff --git a/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs b/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs
index 00de07b..d17d203 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs
@@ -8,12 +8,12 @@ open MyWebLog.Data
type SQLiteTagMapData (conn : SqliteConnection) =
/// Find a tag mapping by its ID for the given web log
- let findById tagMapId webLogId = backgroundTask {
- use cmd = conn.CreateCommand ()
+ let findById (tagMapId: TagMapId) webLogId = backgroundTask {
+ use cmd = conn.CreateCommand()
cmd.CommandText <- "SELECT * FROM tag_map WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", TagMapId.toString tagMapId) |> ignore
- use! rdr = cmd.ExecuteReaderAsync ()
- return Helpers.verifyWebLog webLogId (fun tm -> tm.WebLogId) Map.toTagMap rdr
+ cmd.Parameters.AddWithValue ("@id", string tagMapId) |> ignore
+ use! rdr = cmd.ExecuteReaderAsync()
+ return verifyWebLog webLogId (_.WebLogId) Map.toTagMap rdr
}
/// Delete a tag mapping for the given web log
@@ -22,7 +22,7 @@ type SQLiteTagMapData (conn : SqliteConnection) =
| Some _ ->
use cmd = conn.CreateCommand ()
cmd.CommandText <- "DELETE FROM tag_map WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", TagMapId.toString tagMapId) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string tagMapId) |> ignore
do! write cmd
return true
| None -> return false
@@ -81,7 +81,7 @@ type SQLiteTagMapData (conn : SqliteConnection) =
@id, @webLogId, @tag, @urlValue
)"
addWebLogId cmd tagMap.WebLogId
- [ cmd.Parameters.AddWithValue ("@id", TagMapId.toString tagMap.Id)
+ [ cmd.Parameters.AddWithValue ("@id", string tagMap.Id)
cmd.Parameters.AddWithValue ("@tag", tagMap.Tag)
cmd.Parameters.AddWithValue ("@urlValue", tagMap.UrlValue)
] |> ignore
diff --git a/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs b/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
index dd3d81b..ff5403b 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
@@ -27,19 +27,19 @@ type SQLiteThemeData (conn : SqliteConnection) =
}
/// Does a given theme exist?
- let exists themeId = backgroundTask {
+ let exists (themeId: ThemeId) = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT COUNT(id) FROM theme WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", ThemeId.toString themeId) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string themeId) |> ignore
let! count = count cmd
return count > 0
}
/// Find a theme by its ID
- let findById themeId = backgroundTask {
+ let findById (themeId: ThemeId) = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT * FROM theme WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", ThemeId.toString themeId) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string themeId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
if rdr.Read () then
let theme = Map.toTheme rdr
@@ -71,29 +71,28 @@ type SQLiteThemeData (conn : SqliteConnection) =
"DELETE FROM theme_asset WHERE theme_id = @id;
DELETE FROM theme_template WHERE theme_id = @id;
DELETE FROM theme WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", ThemeId.toString themeId) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string themeId) |> ignore
do! write cmd
return true
| None -> return false
}
/// Save a theme
- let save (theme : Theme) = backgroundTask {
- use cmd = conn.CreateCommand ()
+ let save (theme: Theme) = backgroundTask {
+ use cmd = conn.CreateCommand()
let! oldTheme = findById theme.Id
cmd.CommandText <-
match oldTheme with
| Some _ -> "UPDATE theme SET name = @name, version = @version WHERE id = @id"
| None -> "INSERT INTO theme VALUES (@id, @name, @version)"
- [ cmd.Parameters.AddWithValue ("@id", ThemeId.toString theme.Id)
+ [ cmd.Parameters.AddWithValue ("@id", string theme.Id)
cmd.Parameters.AddWithValue ("@name", theme.Name)
cmd.Parameters.AddWithValue ("@version", theme.Version)
] |> ignore
do! write cmd
let toDelete, toAdd =
- Utils.diffLists (oldTheme |> Option.map (fun t -> t.Templates) |> Option.defaultValue [])
- theme.Templates (fun t -> t.Name)
+ Utils.diffLists (oldTheme |> Option.map _.Templates |> Option.defaultValue []) theme.Templates _.Name
let toUpdate =
theme.Templates
|> List.filter (fun t ->
@@ -102,7 +101,7 @@ type SQLiteThemeData (conn : SqliteConnection) =
cmd.CommandText <-
"UPDATE theme_template SET template = @template WHERE theme_id = @themeId AND name = @name"
cmd.Parameters.Clear ()
- [ cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString theme.Id)
+ [ cmd.Parameters.AddWithValue ("@themeId", string theme.Id)
cmd.Parameters.Add ("@name", SqliteType.Text)
cmd.Parameters.Add ("@template", SqliteType.Text)
] |> ignore
@@ -157,10 +156,10 @@ type SQLiteThemeAssetData (conn : SqliteConnection) =
}
/// Delete all assets for the given theme
- let deleteByTheme themeId = backgroundTask {
+ let deleteByTheme (themeId: ThemeId) = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "DELETE FROM theme_asset WHERE theme_id = @themeId"
- cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString themeId) |> ignore
+ cmd.Parameters.AddWithValue ("@themeId", string themeId) |> ignore
do! write cmd
}
@@ -177,19 +176,19 @@ type SQLiteThemeAssetData (conn : SqliteConnection) =
}
/// Get theme assets for the given theme (excludes data)
- let findByTheme themeId = backgroundTask {
+ let findByTheme (themeId: ThemeId) = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT theme_id, path, updated_on FROM theme_asset WHERE theme_id = @themeId"
- cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString themeId) |> ignore
+ cmd.Parameters.AddWithValue ("@themeId", string themeId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
return toList (Map.toThemeAsset false) rdr
}
/// Get theme assets for the given theme
- let findByThemeWithData themeId = backgroundTask {
+ let findByThemeWithData (themeId: ThemeId) = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT *, ROWID FROM theme_asset WHERE theme_id = @themeId"
- cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString themeId) |> ignore
+ cmd.Parameters.AddWithValue ("@themeId", string themeId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
return toList (Map.toThemeAsset true) rdr
}
diff --git a/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs b/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs
index 3614b79..cf915ae 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteUploadData.fs
@@ -5,14 +5,14 @@ open Microsoft.Data.Sqlite
open MyWebLog
open MyWebLog.Data
-/// SQLite myWebLog web log data implementation
-type SQLiteUploadData (conn : SqliteConnection) =
+/// SQLite myWebLog web log data implementation
+type SQLiteUploadData(conn: SqliteConnection) =
/// Add parameters for uploaded file INSERT and UPDATE statements
- let addUploadParameters (cmd : SqliteCommand) (upload : Upload) =
- [ cmd.Parameters.AddWithValue ("@id", UploadId.toString upload.Id)
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString upload.WebLogId)
- cmd.Parameters.AddWithValue ("@path", upload.Path.Value)
+ let addUploadParameters (cmd: SqliteCommand) (upload: Upload) =
+ [ cmd.Parameters.AddWithValue ("@id", string upload.Id)
+ cmd.Parameters.AddWithValue ("@webLogId", string upload.WebLogId)
+ cmd.Parameters.AddWithValue ("@path", string upload.Path)
cmd.Parameters.AddWithValue ("@updatedOn", instantParam upload.UpdatedOn)
cmd.Parameters.AddWithValue ("@dataLength", upload.Data.Length)
] |> ignore
@@ -46,14 +46,14 @@ type SQLiteUploadData (conn : SqliteConnection) =
WHERE id = @id
AND web_log_id = @webLogId"
addWebLogId cmd webLogId
- cmd.Parameters.AddWithValue ("@id", UploadId.toString uploadId) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string uploadId) |> ignore
let! rdr = cmd.ExecuteReaderAsync ()
if (rdr.Read ()) then
let upload = Map.toUpload false rdr
do! rdr.CloseAsync ()
cmd.CommandText <- "DELETE FROM upload WHERE id = @id AND web_log_id = @webLogId"
do! write cmd
- return Ok upload.Path.Value
+ return Ok (string upload.Path)
else
return Error $"""Upload ID {cmd.Parameters["@id"]} not found"""
}
diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs
index 11a347c..ea2b4ea 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs
@@ -9,8 +9,8 @@ open Newtonsoft.Json
// The web log podcast insert loop is not statically compilable; this is OK
#nowarn "3511"
-/// SQLite myWebLog web log data implementation
-type SQLiteWebLogData (conn : SqliteConnection, ser : JsonSerializer) =
+/// SQLite myWebLog web log data implementation
+type SQLiteWebLogData(conn: SqliteConnection, ser: JsonSerializer) =
// SUPPORT FUNCTIONS
@@ -25,28 +25,28 @@ type SQLiteWebLogData (conn : SqliteConnection, ser : JsonSerializer) =
] |> ignore
/// Add parameters for web log INSERT or UPDATE statements
- let addWebLogParameters (cmd : SqliteCommand) (webLog : WebLog) =
- [ cmd.Parameters.AddWithValue ("@id", WebLogId.toString webLog.Id)
+ let addWebLogParameters (cmd: SqliteCommand) (webLog: WebLog) =
+ [ cmd.Parameters.AddWithValue ("@id", string webLog.Id)
cmd.Parameters.AddWithValue ("@name", webLog.Name)
cmd.Parameters.AddWithValue ("@slug", webLog.Slug)
cmd.Parameters.AddWithValue ("@subtitle", maybe webLog.Subtitle)
cmd.Parameters.AddWithValue ("@defaultPage", webLog.DefaultPage)
cmd.Parameters.AddWithValue ("@postsPerPage", webLog.PostsPerPage)
- cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString webLog.ThemeId)
+ cmd.Parameters.AddWithValue ("@themeId", string webLog.ThemeId)
cmd.Parameters.AddWithValue ("@urlBase", webLog.UrlBase)
cmd.Parameters.AddWithValue ("@timeZone", webLog.TimeZone)
cmd.Parameters.AddWithValue ("@autoHtmx", webLog.AutoHtmx)
- cmd.Parameters.AddWithValue ("@uploads", UploadDestination.toString webLog.Uploads)
+ cmd.Parameters.AddWithValue ("@uploads", string webLog.Uploads)
cmd.Parameters.AddWithValue ("@redirectRules", Utils.serialize ser webLog.RedirectRules)
] |> ignore
addWebLogRssParameters cmd webLog
/// Add parameters for custom feed INSERT or UPDATE statements
- let addCustomFeedParameters (cmd : SqliteCommand) webLogId (feed : CustomFeed) =
- [ cmd.Parameters.AddWithValue ("@id", CustomFeedId.toString feed.Id)
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString webLogId)
- cmd.Parameters.AddWithValue ("@source", CustomFeedSource.toString feed.Source)
- cmd.Parameters.AddWithValue ("@path", feed.Path.Value)
+ let addCustomFeedParameters (cmd: SqliteCommand) (webLogId: WebLogId) (feed: CustomFeed) =
+ [ cmd.Parameters.AddWithValue ("@id", string feed.Id)
+ cmd.Parameters.AddWithValue ("@webLogId", string webLogId)
+ cmd.Parameters.AddWithValue ("@source", string feed.Source)
+ cmd.Parameters.AddWithValue ("@path", string feed.Path)
cmd.Parameters.AddWithValue ("@podcast", maybe (if Option.isSome feed.Podcast then
Some (Utils.serialize ser feed.Podcast)
else None))
@@ -74,7 +74,7 @@ type SQLiteWebLogData (conn : SqliteConnection, ser : JsonSerializer) =
/// Update the custom feeds for a web log
let updateCustomFeeds (webLog : WebLog) = backgroundTask {
let! feeds = getCustomFeeds webLog
- let toDelete, toAdd = Utils.diffLists feeds webLog.Rss.CustomFeeds (fun it -> $"{CustomFeedId.toString it.Id}")
+ let toDelete, toAdd = Utils.diffLists feeds webLog.Rss.CustomFeeds string
let toId (feed : CustomFeed) = feed.Id
let toUpdate =
webLog.Rss.CustomFeeds
@@ -85,7 +85,7 @@ type SQLiteWebLogData (conn : SqliteConnection, ser : JsonSerializer) =
toDelete
|> List.map (fun it -> backgroundTask {
cmd.CommandText <- "DELETE FROM web_log_feed WHERE id = @id"
- cmd.Parameters["@id"].Value <- CustomFeedId.toString it.Id
+ cmd.Parameters["@id"].Value <- string it.Id
do! write cmd
})
|> Task.WhenAll
@@ -211,7 +211,7 @@ type SQLiteWebLogData (conn : SqliteConnection, ser : JsonSerializer) =
use cmd = conn.CreateCommand ()
cmd.CommandText <- "UPDATE web_log SET redirect_rules = @redirectRules WHERE id = @id"
cmd.Parameters.AddWithValue ("@redirectRules", Utils.serialize ser webLog.RedirectRules) |> ignore
- cmd.Parameters.AddWithValue ("@id", WebLogId.toString webLog.Id) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string webLog.Id) |> ignore
do! write cmd
}
@@ -228,7 +228,7 @@ type SQLiteWebLogData (conn : SqliteConnection, ser : JsonSerializer) =
copyright = @copyright
WHERE id = @id"
addWebLogRssParameters cmd webLog
- cmd.Parameters.AddWithValue ("@id", WebLogId.toString webLog.Id) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string webLog.Id) |> ignore
do! write cmd
do! updateCustomFeeds webLog
}
diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs
index f99bf05..20a6056 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs
@@ -4,22 +4,22 @@ open Microsoft.Data.Sqlite
open MyWebLog
open MyWebLog.Data
-/// SQLite myWebLog user data implementation
-type SQLiteWebLogUserData (conn : SqliteConnection) =
+/// SQLite myWebLog user data implementation
+type SQLiteWebLogUserData(conn: SqliteConnection) =
// SUPPORT FUNCTIONS
/// Add parameters for web log user INSERT or UPDATE statements
- let addWebLogUserParameters (cmd : SqliteCommand) (user : WebLogUser) =
- [ cmd.Parameters.AddWithValue ("@id", WebLogUserId.toString user.Id)
- cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString user.WebLogId)
+ let addWebLogUserParameters (cmd: SqliteCommand) (user: WebLogUser) =
+ [ cmd.Parameters.AddWithValue ("@id", string user.Id)
+ cmd.Parameters.AddWithValue ("@webLogId", string user.WebLogId)
cmd.Parameters.AddWithValue ("@email", user.Email)
cmd.Parameters.AddWithValue ("@firstName", user.FirstName)
cmd.Parameters.AddWithValue ("@lastName", user.LastName)
cmd.Parameters.AddWithValue ("@preferredName", user.PreferredName)
cmd.Parameters.AddWithValue ("@passwordHash", user.PasswordHash)
cmd.Parameters.AddWithValue ("@url", maybe user.Url)
- cmd.Parameters.AddWithValue ("@accessLevel", user.AccessLevel.Value)
+ cmd.Parameters.AddWithValue ("@accessLevel", string user.AccessLevel)
cmd.Parameters.AddWithValue ("@createdOn", instantParam user.CreatedOn)
cmd.Parameters.AddWithValue ("@lastSeenOn", maybeInstant user.LastSeenOn)
] |> ignore
@@ -42,12 +42,12 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
}
/// Find a user by their ID for the given web log
- let findById userId webLogId = backgroundTask {
+ let findById (userId: WebLogUserId) webLogId = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT * FROM web_log_user WHERE id = @id"
- cmd.Parameters.AddWithValue ("@id", WebLogUserId.toString userId) |> ignore
+ cmd.Parameters.AddWithValue ("@id", string userId) |> ignore
use! rdr = cmd.ExecuteReaderAsync ()
- return Helpers.verifyWebLog webLogId (fun u -> u.WebLogId) Map.toWebLogUser rdr
+ return verifyWebLog webLogId (_.WebLogId) Map.toWebLogUser rdr
}
/// Delete a user if they have no posts or pages
@@ -56,7 +56,7 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
| Some _ ->
use cmd = conn.CreateCommand ()
cmd.CommandText <- "SELECT COUNT(id) FROM page WHERE author_id = @userId"
- cmd.Parameters.AddWithValue ("@userId", WebLogUserId.toString userId) |> ignore
+ cmd.Parameters.AddWithValue ("@userId", string userId) |> ignore
let! pageCount = count cmd
cmd.CommandText <- "SELECT COUNT(id) FROM post WHERE author_id = @userId"
let! postCount = count cmd
@@ -89,16 +89,15 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
}
/// Find the names of users by their IDs for the given web log
- let findNames webLogId userIds = backgroundTask {
+ let findNames webLogId (userIds: WebLogUserId list) = backgroundTask {
use cmd = conn.CreateCommand ()
- let nameSql, nameParams = inClause "AND id" "id" WebLogUserId.toString userIds
+ let nameSql, nameParams = inClause "AND id" "id" string userIds
cmd.CommandText <- $"SELECT * FROM web_log_user WHERE web_log_id = @webLogId {nameSql}"
addWebLogId cmd webLogId
cmd.Parameters.AddRange nameParams
use! rdr = cmd.ExecuteReaderAsync ()
return
- toList Map.toWebLogUser rdr
- |> List.map (fun u -> { Name = WebLogUserId.toString u.Id; Value = WebLogUser.displayName u })
+ toList Map.toWebLogUser rdr |> List.map (fun u -> { Name = string u.Id; Value = WebLogUser.displayName u })
}
/// Restore users from a backup
@@ -108,7 +107,7 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
}
/// Set a user's last seen date/time to now
- let setLastSeen userId webLogId = backgroundTask {
+ let setLastSeen (userId: WebLogUserId) webLogId = backgroundTask {
use cmd = conn.CreateCommand ()
cmd.CommandText <-
"UPDATE web_log_user
@@ -116,7 +115,7 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
WHERE id = @id
AND web_log_id = @webLogId"
addWebLogId cmd webLogId
- [ cmd.Parameters.AddWithValue ("@id", WebLogUserId.toString userId)
+ [ cmd.Parameters.AddWithValue ("@id", string userId)
cmd.Parameters.AddWithValue ("@lastSeenOn", instantParam (Noda.now ()))
] |> ignore
let! _ = cmd.ExecuteNonQueryAsync ()
diff --git a/src/MyWebLog.Data/SQLiteData.fs b/src/MyWebLog.Data/SQLiteData.fs
index c25d9c2..e30aafd 100644
--- a/src/MyWebLog.Data/SQLiteData.fs
+++ b/src/MyWebLog.Data/SQLiteData.fs
@@ -203,7 +203,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger, ser : JsonS
|> List.iter (fun (feedId, podcast) ->
cmd.CommandText <- "UPDATE web_log_feed SET podcast = @podcast WHERE id = @id"
[ cmd.Parameters.AddWithValue ("@podcast", Utils.serialize ser podcast)
- cmd.Parameters.AddWithValue ("@id", CustomFeedId.toString feedId) ] |> ignore
+ cmd.Parameters.AddWithValue ("@id", string feedId) ] |> ignore
let _ = cmd.ExecuteNonQuery ()
cmd.Parameters.Clear ())
cmd.CommandText <- "SELECT * FROM post_episode"
@@ -241,7 +241,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger, ser : JsonS
|> List.iter (fun (postId, episode) ->
cmd.CommandText <- "UPDATE post SET episode = @episode WHERE id = @id"
[ cmd.Parameters.AddWithValue ("@episode", Utils.serialize ser episode)
- cmd.Parameters.AddWithValue ("@id", postId.Value) ] |> ignore
+ cmd.Parameters.AddWithValue ("@id", string postId) ] |> ignore
let _ = cmd.ExecuteNonQuery ()
cmd.Parameters.Clear ())
diff --git a/src/MyWebLog.Data/Utils.fs b/src/MyWebLog.Data/Utils.fs
index 285a5f2..2af59a7 100644
--- a/src/MyWebLog.Data/Utils.fs
+++ b/src/MyWebLog.Data/Utils.fs
@@ -12,7 +12,7 @@ let currentDbVersion = "v2.1"
let rec orderByHierarchy (cats : Category list) parentId slugBase parentNames = seq {
for cat in cats |> List.filter (fun c -> c.ParentId = parentId) do
let fullSlug = (match slugBase with Some it -> $"{it}/" | None -> "") + cat.Slug
- { Id = cat.Id.Value
+ { Id = string cat.Id
Slug = fullSlug
Name = cat.Name
Description = cat.Description
@@ -29,16 +29,16 @@ let diffLists<'T, 'U when 'U: equality> oldItems newItems (f: 'T -> 'U) =
List.filter (diff newItems) oldItems, List.filter (diff oldItems) newItems
/// Find meta items added and removed
-let diffMetaItems (oldItems : MetaItem list) newItems =
+let diffMetaItems (oldItems: MetaItem list) newItems =
diffLists oldItems newItems (fun item -> $"{item.Name}|{item.Value}")
/// Find the permalinks added and removed
-let diffPermalinks oldLinks newLinks =
- diffLists oldLinks newLinks (fun (it: Permalink) -> it.Value)
+let diffPermalinks (oldLinks: Permalink list) newLinks =
+ diffLists oldLinks newLinks string
/// Find the revisions added and removed
-let diffRevisions oldRevs newRevs =
- diffLists oldRevs newRevs (fun (rev: Revision) -> $"{rev.AsOf.ToUnixTimeTicks()}|{rev.Text.Value}")
+let diffRevisions (oldRevs: Revision list) newRevs =
+ diffLists oldRevs newRevs (fun rev -> $"{rev.AsOf.ToUnixTimeTicks()}|{rev.Text}")
open MyWebLog.Converters
open Newtonsoft.Json
diff --git a/src/MyWebLog.Domain/DataTypes.fs b/src/MyWebLog.Domain/DataTypes.fs
index ad0c0d1..01c6a39 100644
--- a/src/MyWebLog.Domain/DataTypes.fs
+++ b/src/MyWebLog.Domain/DataTypes.fs
@@ -32,7 +32,7 @@ module Category =
/// An empty category
let empty = {
Id = CategoryId.Empty
- WebLogId = WebLogId.empty
+ WebLogId = WebLogId.Empty
Name = ""
Slug = ""
Description = None
@@ -137,8 +137,8 @@ module Page =
/// An empty page
let empty = {
Id = PageId.Empty
- WebLogId = WebLogId.empty
- AuthorId = WebLogUserId.empty
+ WebLogId = WebLogId.Empty
+ AuthorId = WebLogUserId.Empty
Title = ""
Permalink = Permalink.Empty
PublishedOn = Noda.epoch
@@ -210,8 +210,8 @@ module Post =
/// An empty post
let empty = {
Id = PostId.Empty
- WebLogId = WebLogId.empty
- AuthorId = WebLogUserId.empty
+ WebLogId = WebLogId.Empty
+ AuthorId = WebLogUserId.Empty
Status = Draft
Title = ""
Permalink = Permalink.Empty
@@ -248,8 +248,8 @@ module TagMap =
/// An empty tag mapping
let empty = {
- Id = TagMapId.empty
- WebLogId = WebLogId.empty
+ Id = TagMapId.Empty
+ WebLogId = WebLogId.Empty
Tag = ""
UrlValue = ""
}
@@ -328,8 +328,8 @@ module Upload =
/// An empty upload
let empty = {
- Id = UploadId.empty
- WebLogId = WebLogId.empty
+ Id = UploadId.Empty
+ WebLogId = WebLogId.Empty
Path = Permalink.Empty
UpdatedOn = Noda.epoch
Data = [||]
@@ -384,7 +384,7 @@ module WebLog =
/// An empty web log
let empty = {
- Id = WebLogId.empty
+ Id = WebLogId.Empty
Name = ""
Slug = ""
Subtitle = None
@@ -393,7 +393,7 @@ module WebLog =
ThemeId = ThemeId "default"
UrlBase = ""
TimeZone = ""
- Rss = RssOptions.empty
+ Rss = RssOptions.Empty
AutoHtmx = false
Uploads = Database
RedirectRules = []
@@ -407,12 +407,12 @@ module WebLog =
/// Generate an absolute URL for the given link
let absoluteUrl webLog (permalink: Permalink) =
- $"{webLog.UrlBase}/{permalink.Value}"
+ $"{webLog.UrlBase}/{permalink}"
/// Generate a relative URL for the given link
let relativeUrl webLog (permalink: Permalink) =
let _, leadPath = hostAndPath webLog
- $"{leadPath}/{permalink.Value}"
+ $"{leadPath}/{permalink}"
/// Convert an Instant (UTC reference) to the web log's local date/time
let localTime webLog (date: Instant) =
@@ -463,8 +463,8 @@ module WebLogUser =
/// An empty web log user
let empty = {
- Id = WebLogUserId.empty
- WebLogId = WebLogId.empty
+ Id = WebLogUserId.Empty
+ WebLogId = WebLogId.Empty
Email = ""
FirstName = ""
LastName = ""
diff --git a/src/MyWebLog.Domain/SupportTypes.fs b/src/MyWebLog.Domain/SupportTypes.fs
index ed25389..ee3c01c 100644
--- a/src/MyWebLog.Domain/SupportTypes.fs
+++ b/src/MyWebLog.Domain/SupportTypes.fs
@@ -54,16 +54,16 @@ type AccessLevel =
| Administrator
/// Parse an access level from its string representation
- static member Parse =
- function
+ static member Parse level =
+ match level with
| "Author" -> Author
| "Editor" -> Editor
| "WebLogAdmin" -> WebLogAdmin
| "Administrator" -> Administrator
- | it -> invalidArg "level" $"{it} is not a valid access level"
+ | _ -> invalidArg (nameof level) $"{level} is not a valid access level"
/// The string representation of this access level
- member this.Value =
+ override this.ToString() =
match this with
| Author -> "Author"
| Editor -> "Editor"
@@ -96,7 +96,7 @@ type CategoryId =
newId >> CategoryId
/// The string representation of this category ID
- member this.Value =
+ override this.ToString() =
match this with CategoryId it -> it
@@ -113,7 +113,7 @@ type CommentId =
newId >> CommentId
/// The string representation of this comment ID
- member this.Value =
+ override this.ToString() =
match this with CommentId it -> it
@@ -128,15 +128,15 @@ type CommentStatus =
| Spam
/// Parse a string into a comment status
- static member Parse =
- function
+ static member Parse status =
+ match status with
| "Approved" -> Approved
| "Pending" -> Pending
| "Spam" -> Spam
- | it -> invalidArg "status" $"{it} is not a valid comment status"
+ | _ -> invalidArg (nameof status) $"{status} is not a valid comment status"
/// Convert a comment status to a string
- member this.Value =
+ override this.ToString() =
match this with Approved -> "Approved" | Pending -> "Pending" | Spam -> "Spam"
@@ -148,15 +148,15 @@ type ExplicitRating =
| Clean
/// Parse a string into an explicit rating
- static member Parse =
- function
+ static member Parse rating =
+ match rating with
| "yes" -> Yes
| "no" -> No
| "clean" -> Clean
- | it -> invalidArg "rating" $"{it} is not a valid explicit rating"
+ | _ -> invalidArg (nameof rating) $"{rating} is not a valid explicit rating"
/// The string value of this rating
- member this.Value =
+ override this.ToString() =
match this with Yes -> "yes" | No -> "no" | Clean -> "clean"
@@ -289,11 +289,11 @@ type MarkupText =
| Html of string
/// Parse a string into a MarkupText instance
- static member Parse(it: string) =
- match it with
- | text when text.StartsWith "Markdown: " -> Markdown text[10..]
- | text when text.StartsWith "HTML: " -> Html text[6..]
- | text -> invalidOp $"Cannot derive type of text ({text})"
+ static member Parse(text: string) =
+ match text with
+ | _ when text.StartsWith "Markdown: " -> Markdown text[10..]
+ | _ when text.StartsWith "HTML: " -> Html text[6..]
+ | _ -> invalidArg (nameof text) $"Cannot derive type of text ({text})"
/// The source type for the markup text
member this.SourceType =
@@ -304,7 +304,8 @@ type MarkupText =
match this with Markdown text -> text | Html text -> text
/// The string representation of the markup text
- member this.Value = $"{this.SourceType}: {this.Text}"
+ override this.ToString() =
+ $"{this.SourceType}: {this.Text}"
/// The HTML representation of the markup text
member this.AsHtml() =
@@ -315,10 +316,10 @@ type MarkupText =
[]
type MetaItem = {
/// The name of the metadata value
- Name : string
+ Name: string
/// The metadata value
- Value : string
+ Value: string
} with
/// An empty metadata item
@@ -330,10 +331,10 @@ type MetaItem = {
[]
type Revision = {
/// When this revision was saved
- AsOf : Instant
+ AsOf: Instant
/// The text of the revision
- Text : MarkupText
+ Text: MarkupText
} with
/// An empty revision
@@ -350,7 +351,7 @@ type Permalink =
static member Empty = Permalink ""
/// The string value of this permalink
- member this.Value =
+ override this.ToString() =
match this with Permalink it -> it
@@ -367,7 +368,7 @@ type PageId =
newId >> PageId
/// The string value of this page ID
- member this.Value =
+ override this.ToString() =
match this with PageId it -> it
@@ -383,8 +384,8 @@ type PodcastMedium =
| Blog
/// Parse a string into a podcast medium
- static member Parse =
- function
+ static member Parse medium =
+ match medium with
| "podcast" -> Podcast
| "music" -> Music
| "video" -> Video
@@ -392,10 +393,10 @@ type PodcastMedium =
| "audiobook" -> Audiobook
| "newsletter" -> Newsletter
| "blog" -> Blog
- | it -> invalidArg "medium" $"{it} is not a valid podcast medium"
+ | _ -> invalidArg (nameof medium) $"{medium} is not a valid podcast medium"
/// The string value of this podcast medium
- member this.Value =
+ override this.ToString() =
match this with
| Podcast -> "podcast"
| Music -> "music"
@@ -415,14 +416,14 @@ type PostStatus =
| Published
/// Parse a string into a post status
- static member Parse =
- function
+ static member Parse status =
+ match status with
| "Draft" -> Draft
| "Published" -> Published
- | it -> invalidArg "status" $"{it} is not a valid post status"
+ | _ -> invalidArg (nameof status) $"{status} is not a valid post status"
/// The string representation of this post status
- member this.Value =
+ override this.ToString() =
match this with Draft -> "Draft" | Published -> "Published"
@@ -439,7 +440,7 @@ type PostId =
newId >> PostId
/// Convert a post ID to a string
- member this.Value =
+ override this.ToString() =
match this with PostId it -> it
@@ -465,19 +466,20 @@ type RedirectRule = {
/// An identifier for a custom feed
-type CustomFeedId = CustomFeedId of string
+[]
+type CustomFeedId =
+ | CustomFeedId of string
-/// Functions to support custom feed IDs
-module CustomFeedId =
-
/// An empty custom feed ID
- let empty = CustomFeedId ""
-
- /// Convert a custom feed ID to a string
- let toString = function CustomFeedId pi -> pi
+ static member Empty = CustomFeedId ""
/// Create a new custom feed ID
- let create = newId >> CustomFeedId
+ static member Create =
+ newId >> CustomFeedId
+
+ /// Convert a custom feed ID to a string
+ override this.ToString() =
+ match this with CustomFeedId it -> it
/// The source for a custom feed
@@ -486,99 +488,94 @@ type CustomFeedSource =
| Category of CategoryId
/// A feed based on a particular tag
| Tag of string
-
-/// Functions to support feed sources
-module CustomFeedSource =
- /// Create a string version of a feed source
- let toString : CustomFeedSource -> string =
- function
- | Category (CategoryId catId) -> $"category:{catId}"
- | Tag tag -> $"tag:{tag}"
/// Parse a feed source from its string version
- let parse : string -> CustomFeedSource =
+ static member Parse(source: string) =
let value (it : string) = it.Split(":").[1]
- function
- | source when source.StartsWith "category:" -> (value >> CategoryId >> Category) source
- | source when source.StartsWith "tag:" -> (value >> Tag) source
- | source -> invalidArg "feedSource" $"{source} is not a valid feed source"
+ match source with
+ | _ when source.StartsWith "category:" -> (value >> CategoryId >> Category) source
+ | _ when source.StartsWith "tag:" -> (value >> Tag) source
+ | _ -> invalidArg (nameof source) $"{source} is not a valid feed source"
+
+ /// Create a string version of a feed source
+ override this.ToString() =
+ match this with | Category (CategoryId catId) -> $"category:{catId}" | Tag tag -> $"tag:{tag}"
/// Options for a feed that describes a podcast
+[]
type PodcastOptions = {
/// The title of the podcast
- Title : string
+ Title: string
/// A subtitle for the podcast
- Subtitle : string option
+ Subtitle: string option
/// The number of items in the podcast feed
- ItemsInFeed : int
+ ItemsInFeed: int
/// A summary of the podcast (iTunes field)
- Summary : string
+ Summary: string
/// The display name of the podcast author (iTunes field)
- DisplayedAuthor : string
+ DisplayedAuthor: string
/// The e-mail address of the user who registered the podcast at iTunes
- Email : string
+ Email: string
/// The link to the image for the podcast
- ImageUrl : Permalink
+ ImageUrl: Permalink
/// The category from Apple Podcasts (iTunes) under which this podcast is categorized
- AppleCategory : string
+ AppleCategory: string
/// A further refinement of the categorization of this podcast (Apple Podcasts/iTunes field / values)
- AppleSubcategory : string option
+ AppleSubcategory: string option
/// The explictness rating (iTunes field)
- Explicit : ExplicitRating
+ Explicit: ExplicitRating
/// The default media type for files in this podcast
- DefaultMediaType : string option
+ DefaultMediaType: string option
/// The base URL for relative URL media files for this podcast (optional; defaults to web log base)
- MediaBaseUrl : string option
+ MediaBaseUrl: string option
/// A GUID for this podcast
- PodcastGuid : Guid option
+ PodcastGuid: Guid option
/// A URL at which information on supporting the podcast may be found (supports permalinks)
- FundingUrl : string option
+ FundingUrl: string option
/// The text to be displayed in the funding item within the feed
- FundingText : string option
+ FundingText: string option
/// The medium (what the podcast IS, not what it is ABOUT)
- Medium : PodcastMedium option
+ Medium: PodcastMedium option
}
/// A custom feed
+[]
type CustomFeed = {
/// The ID of the custom feed
- Id : CustomFeedId
+ Id: CustomFeedId
/// The source for the custom feed
- Source : CustomFeedSource
+ Source: CustomFeedSource
/// The path for the custom feed
- Path : Permalink
+ Path: Permalink
/// Podcast options, if the feed defines a podcast
- Podcast : PodcastOptions option
-}
-
-/// Functions to support custom feeds
-module CustomFeed =
+ Podcast: PodcastOptions option
+} with
/// An empty custom feed
- let empty = {
- Id = CustomFeedId ""
- Source = Category (CategoryId "")
- Path = Permalink ""
+ static member Empty = {
+ Id = CustomFeedId.Empty
+ Source = Category CategoryId.Empty
+ Path = Permalink.Empty
Podcast = None
}
@@ -587,32 +584,29 @@ module CustomFeed =
[]
type RssOptions = {
/// Whether the site feed of posts is enabled
- IsFeedEnabled : bool
+ IsFeedEnabled: bool
/// The name of the file generated for the site feed
- FeedName : string
+ FeedName: string
/// Override the "posts per page" setting for the site feed
- ItemsInFeed : int option
+ ItemsInFeed: int option
/// Whether feeds are enabled for all categories
- IsCategoryEnabled : bool
+ IsCategoryEnabled: bool
/// Whether feeds are enabled for all tags
- IsTagEnabled : bool
+ IsTagEnabled: bool
/// A copyright string to be placed in all feeds
- Copyright : string option
+ Copyright: string option
/// Custom feeds for this web log
CustomFeeds: CustomFeed list
-}
-
-/// Functions to support RSS options
-module RssOptions =
+} with
/// An empty set of RSS options
- let empty = {
+ static member Empty = {
IsFeedEnabled = true
FeedName = "feed.xml"
ItemsInFeed = None
@@ -624,126 +618,126 @@ module RssOptions =
/// An identifier for a tag mapping
-type TagMapId = TagMapId of string
+[]
+type TagMapId =
+ | TagMapId of string
-/// Functions to support tag mapping IDs
-module TagMapId =
-
/// An empty tag mapping ID
- let empty = TagMapId ""
-
- /// Convert a tag mapping ID to a string
- let toString = function TagMapId tmi -> tmi
+ static member Empty = TagMapId ""
/// Create a new tag mapping ID
- let create = newId >> TagMapId
+ static member Create =
+ newId >> TagMapId
+
+ /// Convert a tag mapping ID to a string
+ override this.ToString() =
+ match this with TagMapId it -> it
/// An identifier for a theme (represents its path)
-type ThemeId = ThemeId of string
-
-/// Functions to support theme IDs
-module ThemeId =
- let toString = function ThemeId ti -> ti
+[]
+type ThemeId =
+ | ThemeId of string
+
+ /// The string representation of a theme ID
+ override this.ToString() =
+ match this with ThemeId it -> it
/// An identifier for a theme asset
-type ThemeAssetId = ThemeAssetId of ThemeId * string
+[]
+type ThemeAssetId =
+ | ThemeAssetId of ThemeId * string
-/// Functions to support theme asset IDs
-module ThemeAssetId =
+ /// Convert a string into a theme asset ID
+ static member Parse(it : string) =
+ let themeIdx = it.IndexOf "/"
+ ThemeAssetId(ThemeId it[..(themeIdx - 1)], it[(themeIdx + 1)..])
/// Convert a theme asset ID into a path string
- let toString = function ThemeAssetId (ThemeId theme, asset) -> $"{theme}/{asset}"
-
- /// Convert a string into a theme asset ID
- let ofString (it : string) =
- let themeIdx = it.IndexOf "/"
- ThemeAssetId (ThemeId it[..(themeIdx - 1)], it[(themeIdx + 1)..])
+ override this.ToString() =
+ match this with ThemeAssetId (ThemeId theme, asset) -> $"{theme}/{asset}"
/// A template for a theme
+[]
type ThemeTemplate = {
/// The name of the template
- Name : string
+ Name: string
/// The text of the template
- Text : string
-}
-
-/// Functions to support theme templates
-module ThemeTemplate =
+ Text: string
+} with
/// An empty theme template
- let empty =
+ static member Empty =
{ Name = ""; Text = "" }
/// Where uploads should be placed
+[]
type UploadDestination =
| Database
| Disk
-/// Functions to support upload destinations
-module UploadDestination =
-
- /// Convert an upload destination to its string representation
- let toString = function Database -> "Database" | Disk -> "Disk"
-
/// Parse an upload destination from its string representation
- let parse value =
- match value with
+ static member Parse destination =
+ match destination with
| "Database" -> Database
- | "Disk" -> Disk
- | it -> invalidArg "destination" $"{it} is not a valid upload destination"
+ | "Disk" -> Disk
+ | _ -> invalidArg (nameof destination) $"{destination} is not a valid upload destination"
+
+ /// The string representation of an upload destination
+ override this.ToString() =
+ match this with Database -> "Database" | Disk -> "Disk"
/// An identifier for an upload
-type UploadId = UploadId of string
+[]
+type UploadId =
+ | UploadId of string
-/// Functions to support upload IDs
-module UploadId =
-
/// An empty upload ID
- let empty = UploadId ""
-
- /// Convert an upload ID to a string
- let toString = function UploadId ui -> ui
+ static member Empty = UploadId ""
/// Create a new upload ID
- let create = newId >> UploadId
+ static member Create =
+ newId >> UploadId
+
+ /// The string representation of an upload ID
+ override this.ToString() =
+ match this with UploadId it -> it
/// An identifier for a web log
-type WebLogId = WebLogId of string
+[]
+type WebLogId =
+ | WebLogId of string
-/// Functions to support web log IDs
-module WebLogId =
-
/// An empty web log ID
- let empty = WebLogId ""
-
- /// Convert a web log ID to a string
- let toString = function WebLogId wli -> wli
+ static member Empty = WebLogId ""
/// Create a new web log ID
- let create = newId >> WebLogId
-
+ static member Create =
+ newId >> WebLogId
+
+ /// Convert a web log ID to a string
+ override this.ToString() =
+ match this with WebLogId it -> it
/// An identifier for a web log user
-type WebLogUserId = WebLogUserId of string
-
-/// Functions to support web log user IDs
-module WebLogUserId =
+[]
+type WebLogUserId =
+ | WebLogUserId of string
/// An empty web log user ID
- let empty = WebLogUserId ""
-
- /// Convert a web log user ID to a string
- let toString = function WebLogUserId wli -> wli
+ static member Empty = WebLogUserId ""
/// Create a new web log user ID
- let create = newId >> WebLogUserId
-
-
+ static member Create =
+ newId >> WebLogUserId
+
+ /// The string representation of a web log user ID
+ override this.ToString() =
+ match this with WebLogUserId it -> it
diff --git a/src/MyWebLog.Domain/ViewModels.fs b/src/MyWebLog.Domain/ViewModels.fs
index 2f9a176..2005de8 100644
--- a/src/MyWebLog.Domain/ViewModels.fs
+++ b/src/MyWebLog.Domain/ViewModels.fs
@@ -73,30 +73,30 @@ type DisplayCategory = {
/// A display version of a custom feed definition
type DisplayCustomFeed = {
/// The ID of the custom feed
- Id : string
+ Id: string
/// The source of the custom feed
- Source : string
+ Source: string
/// The relative path at which the custom feed is served
- Path : string
+ Path: string
/// Whether this custom feed is for a podcast
- IsPodcast : bool
+ IsPodcast: bool
}
/// Support functions for custom feed displays
module DisplayCustomFeed =
/// Create a display version from a custom feed
- let fromFeed (cats: DisplayCategory[]) (feed: CustomFeed) : DisplayCustomFeed =
+ let fromFeed (cats: DisplayCategory array) (feed: CustomFeed) : DisplayCustomFeed =
let source =
match feed.Source with
| Category (CategoryId catId) -> $"Category: {(cats |> Array.find (fun cat -> cat.Id = catId)).Name}"
| Tag tag -> $"Tag: {tag}"
- { Id = CustomFeedId.toString feed.Id
+ { Id = string feed.Id
Source = source
- Path = feed.Path.Value
+ Path = string feed.Path
IsPodcast = Option.isSome feed.Podcast
}
@@ -137,14 +137,14 @@ type DisplayPage =
/// Create a minimal display page (no text or metadata) from a database page
static member FromPageMinimal webLog (page: Page) = {
- Id = page.Id.Value
- AuthorId = WebLogUserId.toString page.AuthorId
+ Id = string page.Id
+ AuthorId = string page.AuthorId
Title = page.Title
- Permalink = page.Permalink.Value
+ Permalink = string page.Permalink
PublishedOn = WebLog.localTime webLog page.PublishedOn
UpdatedOn = WebLog.localTime webLog page.UpdatedOn
IsInPageList = page.IsInPageList
- IsDefault = page.Id.Value = webLog.DefaultPage
+ IsDefault = string page.Id = webLog.DefaultPage
Text = ""
Metadata = []
}
@@ -152,14 +152,14 @@ type DisplayPage =
/// Create a display page from a database page
static member FromPage webLog (page : Page) =
let _, extra = WebLog.hostAndPath webLog
- { Id = page.Id.Value
- AuthorId = WebLogUserId.toString page.AuthorId
+ { Id = string page.Id
+ AuthorId = string page.AuthorId
Title = page.Title
- Permalink = page.Permalink.Value
+ Permalink = string page.Permalink
PublishedOn = WebLog.localTime webLog page.PublishedOn
UpdatedOn = WebLog.localTime webLog page.UpdatedOn
IsInPageList = page.IsInPageList
- IsDefault = page.Id.Value = webLog.DefaultPage
+ IsDefault = string page.Id = webLog.DefaultPage
Text = addBaseToRelativeUrls extra page.Text
Metadata = page.Metadata
}
@@ -195,35 +195,35 @@ open System.IO
[]
type DisplayTheme = {
/// The ID / path slug of the theme
- Id : string
+ Id: string
/// The name of the theme
- Name : string
+ Name: string
/// The version of the theme
- Version : string
+ Version: string
/// How many templates are contained in the theme
- TemplateCount : int
+ TemplateCount: int
/// Whether the theme is in use by any web logs
- IsInUse : bool
+ IsInUse: bool
/// Whether the theme .zip file exists on the filesystem
- IsOnDisk : bool
+ IsOnDisk: bool
}
/// Functions to support displaying themes
module DisplayTheme =
/// Create a display theme from a theme
- let fromTheme inUseFunc (theme : Theme) =
- { Id = ThemeId.toString theme.Id
+ let fromTheme inUseFunc (theme: Theme) =
+ { Id = string theme.Id
Name = theme.Name
Version = theme.Version
TemplateCount = List.length theme.Templates
IsInUse = inUseFunc theme.Id
- IsOnDisk = File.Exists $"{ThemeId.toString theme.Id}-theme.zip"
+ IsOnDisk = File.Exists $"{theme.Id}-theme.zip"
}
@@ -231,33 +231,33 @@ module DisplayTheme =
[]
type DisplayUpload = {
/// The ID of the uploaded file
- Id : string
+ Id: string
/// The name of the uploaded file
- Name : string
+ Name: string
/// The path at which the file is served
- Path : string
+ Path: string
/// The date/time the file was updated
- UpdatedOn : DateTime option
+ UpdatedOn: DateTime option
/// The source for this file (created from UploadDestination DU)
- Source : string
+ Source: string
}
/// Functions to support displaying uploads
module DisplayUpload =
/// Create a display uploaded file
- let fromUpload webLog source (upload : Upload) =
- let path = upload.Path.Value
+ let fromUpload webLog (source: UploadDestination) (upload: Upload) =
+ let path = string upload.Path
let name = Path.GetFileName path
- { Id = UploadId.toString upload.Id
+ { Id = string upload.Id
Name = name
- Path = path.Replace (name, "")
+ Path = path.Replace(name, "")
UpdatedOn = Some (WebLog.localTime webLog upload.UpdatedOn)
- Source = UploadDestination.toString source
+ Source = string source
}
@@ -265,45 +265,45 @@ module DisplayUpload =
[]
type DisplayUser = {
/// The ID of the user
- Id : string
+ Id: string
/// The user name (e-mail address)
- Email : string
+ Email: string
/// The user's first name
- FirstName : string
+ FirstName: string
/// The user's last name
- LastName : string
+ LastName: string
/// The user's preferred name
- PreferredName : string
+ PreferredName: string
/// The URL of the user's personal site
- Url : string
+ Url: string
/// The user's access level
- AccessLevel : string
+ AccessLevel: string
/// When the user was created
- CreatedOn : DateTime
+ CreatedOn: DateTime
/// When the user last logged on
- LastSeenOn : Nullable
+ LastSeenOn: Nullable
}
/// Functions to support displaying a user's information
module DisplayUser =
/// Construct a displayed user from a web log user
- let fromUser webLog (user : WebLogUser) =
- { Id = WebLogUserId.toString user.Id
+ let fromUser webLog (user: WebLogUser) =
+ { Id = string user.Id
Email = user.Email
FirstName = user.FirstName
LastName = user.LastName
PreferredName = user.PreferredName
Url = defaultArg user.Url ""
- AccessLevel = user.AccessLevel.Value
+ AccessLevel = string user.AccessLevel
CreatedOn = WebLog.localTime webLog user.CreatedOn
LastSeenOn = user.LastSeenOn |> Option.map (WebLog.localTime webLog) |> Option.toNullable
}
@@ -311,30 +311,30 @@ module DisplayUser =
/// View model for editing categories
[]
-type EditCategoryModel =
- { /// The ID of the category being edited
- CategoryId : string
-
- /// The name of the category
- Name : string
-
- /// The category's URL slug
- Slug : string
-
- /// A description of the category (optional)
- Description : string
-
- /// The ID of the category for which this is a subcategory (optional)
- ParentId : string
- }
+type EditCategoryModel = {
+ /// The ID of the category being edited
+ CategoryId: string
+
+ /// The name of the category
+ Name: string
+
+ /// The category's URL slug
+ Slug: string
+
+ /// A description of the category (optional)
+ Description: string
+
+ /// The ID of the category for which this is a subcategory (optional)
+ ParentId: string
+} with
/// Create an edit model from an existing category
- static member fromCategory (cat : Category) =
- { CategoryId = cat.Id.Value
+ static member fromCategory (cat: Category) =
+ { CategoryId = string cat.Id
Name = cat.Name
Slug = cat.Slug
Description = defaultArg cat.Description ""
- ParentId = cat.ParentId |> Option.map _.Value |> Option.defaultValue ""
+ ParentId = cat.ParentId |> Option.map string |> Option.defaultValue ""
}
/// Is this a new category?
@@ -437,10 +437,10 @@ type EditCustomFeedModel =
static member fromFeed (feed: CustomFeed) =
let rss =
{ EditCustomFeedModel.empty with
- Id = CustomFeedId.toString feed.Id
+ Id = string feed.Id
SourceType = match feed.Source with Category _ -> "category" | Tag _ -> "tag"
SourceValue = match feed.Source with Category (CategoryId catId) -> catId | Tag tag -> tag
- Path = feed.Path.Value
+ Path = string feed.Path
}
match feed.Podcast with
| Some p ->
@@ -452,16 +452,16 @@ type EditCustomFeedModel =
Summary = p.Summary
DisplayedAuthor = p.DisplayedAuthor
Email = p.Email
- ImageUrl = p.ImageUrl.Value
+ ImageUrl = string p.ImageUrl
AppleCategory = p.AppleCategory
AppleSubcategory = defaultArg p.AppleSubcategory ""
- Explicit = p.Explicit.Value
+ Explicit = string p.Explicit
DefaultMediaType = defaultArg p.DefaultMediaType ""
MediaBaseUrl = defaultArg p.MediaBaseUrl ""
FundingUrl = defaultArg p.FundingUrl ""
FundingText = defaultArg p.FundingText ""
PodcastGuid = p.PodcastGuid |> Option.map _.ToString().ToLowerInvariant() |> Option.defaultValue ""
- Medium = p.Medium |> Option.map _.Value |> Option.defaultValue ""
+ Medium = p.Medium |> Option.map string |> Option.defaultValue ""
}
| None -> rss
@@ -562,9 +562,9 @@ type EditPageModel = {
| Some rev -> rev
| None -> Revision.Empty
let page = if page.Metadata |> List.isEmpty then { page with Metadata = [ MetaItem.Empty ] } else page
- { PageId = page.Id.Value
+ { PageId = string page.Id
Title = page.Title
- Permalink = page.Permalink.Value
+ Permalink = string page.Permalink
Template = defaultArg page.Template ""
IsShownInPageList = page.IsInPageList
Source = latest.Text.SourceType
@@ -580,7 +580,7 @@ type EditPageModel = {
member this.UpdatePage (page: Page) now =
let revision = { AsOf = now; Text = MarkupText.Parse $"{this.Source}: {this.Text}" }
// Detect a permalink change, and add the prior one to the prior list
- match page.Permalink.Value with
+ match string page.Permalink with
| "" -> page
| link when link = this.Permalink -> page
| _ -> { page with PriorPermalinks = page.Permalink :: page.PriorPermalinks }
@@ -715,15 +715,15 @@ type EditPostModel = {
| None -> Revision.Empty
let post = if post.Metadata |> List.isEmpty then { post with Metadata = [ MetaItem.Empty ] } else post
let episode = defaultArg post.Episode Episode.Empty
- { PostId = post.Id.Value
+ { PostId = string post.Id
Title = post.Title
- Permalink = post.Permalink.Value
+ Permalink = string post.Permalink
Source = latest.Text.SourceType
Text = latest.Text.Text
Tags = String.Join (", ", post.Tags)
Template = defaultArg post.Template ""
- CategoryIds = post.CategoryIds |> List.map _.Value |> Array.ofList
- Status = post.Status.Value
+ CategoryIds = post.CategoryIds |> List.map string |> Array.ofList
+ Status = string post.Status
DoPublish = false
MetaNames = post.Metadata |> List.map _.Name |> Array.ofList
MetaValues = post.Metadata |> List.map _.Value |> Array.ofList
@@ -737,7 +737,7 @@ type EditPostModel = {
MediaType = defaultArg episode.MediaType ""
ImageUrl = defaultArg episode.ImageUrl ""
Subtitle = defaultArg episode.Subtitle ""
- Explicit = defaultArg (episode.Explicit |> Option.map _.Value) ""
+ Explicit = defaultArg (episode.Explicit |> Option.map string) ""
ChapterFile = defaultArg episode.ChapterFile ""
ChapterType = defaultArg episode.ChapterType ""
TranscriptUrl = defaultArg episode.TranscriptUrl ""
@@ -757,7 +757,7 @@ type EditPostModel = {
member this.UpdatePost (post: Post) now =
let revision = { AsOf = now; Text = MarkupText.Parse $"{this.Source}: {this.Text}" }
// Detect a permalink change, and add the prior one to the prior list
- match post.Permalink.Value with
+ match string post.Permalink with
| "" -> post
| link when link = this.Permalink -> post
| _ -> { post with PriorPermalinks = post.Permalink :: post.PriorPermalinks }
@@ -916,7 +916,7 @@ type EditTagMapModel =
/// Create an edit model from the tag mapping
static member fromMapping (tagMap : TagMap) : EditTagMapModel =
- { Id = TagMapId.toString tagMap.Id
+ { Id = string tagMap.Id
Tag = tagMap.Tag
UrlValue = tagMap.UrlValue
}
@@ -924,39 +924,39 @@ type EditTagMapModel =
/// View model to display a user's information
[]
-type EditUserModel =
- { /// The ID of the user
- Id : string
+type EditUserModel = {
+ /// The ID of the user
+ Id: string
- /// The user's access level
- AccessLevel : string
-
- /// The user name (e-mail address)
- Email : string
+ /// The user's access level
+ AccessLevel: string
+
+ /// The user name (e-mail address)
+ Email: string
- /// The URL of the user's personal site
- Url : string
+ /// The URL of the user's personal site
+ Url: string
- /// The user's first name
- FirstName : string
+ /// The user's first name
+ FirstName: string
- /// The user's last name
- LastName : string
+ /// The user's last name
+ LastName: string
- /// The user's preferred name
- PreferredName : string
-
- /// The user's password
- Password : string
-
- /// Confirmation of the user's password
- PasswordConfirm : string
- }
+ /// The user's preferred name
+ PreferredName: string
+
+ /// The user's password
+ Password: string
+
+ /// Confirmation of the user's password
+ PasswordConfirm: string
+} with
/// Construct a displayed user from a web log user
- static member fromUser (user : WebLogUser) =
- { Id = WebLogUserId.toString user.Id
- AccessLevel = user.AccessLevel.Value
+ static member fromUser (user: WebLogUser) =
+ { Id = string user.Id
+ AccessLevel = string user.AccessLevel
Url = defaultArg user.Url ""
Email = user.Email
FirstName = user.FirstName
@@ -1020,20 +1020,20 @@ type ManagePermalinksModel = {
/// Create a permalink model from a page
static member fromPage (pg: Page) =
- { Id = pg.Id.Value
+ { Id = string pg.Id
Entity = "page"
CurrentTitle = pg.Title
- CurrentPermalink = pg.Permalink.Value
- Prior = pg.PriorPermalinks |> List.map _.Value |> Array.ofList
+ CurrentPermalink = string pg.Permalink
+ Prior = pg.PriorPermalinks |> List.map string |> Array.ofList
}
/// Create a permalink model from a post
static member fromPost (post: Post) =
- { Id = post.Id.Value
+ { Id = string post.Id
Entity = "post"
CurrentTitle = post.Title
- CurrentPermalink = post.Permalink.Value
- Prior = post.PriorPermalinks |> List.map _.Value |> Array.ofList
+ CurrentPermalink = string post.Permalink
+ Prior = post.PriorPermalinks |> List.map string |> Array.ofList
}
@@ -1055,7 +1055,7 @@ type ManageRevisionsModel =
/// Create a revision model from a page
static member fromPage webLog (pg: Page) =
- { Id = pg.Id.Value
+ { Id = string pg.Id
Entity = "page"
CurrentTitle = pg.Title
Revisions = pg.Revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
@@ -1063,7 +1063,7 @@ type ManageRevisionsModel =
/// Create a revision model from a post
static member fromPost webLog (post: Post) =
- { Id = post.Id.Value
+ { Id = string post.Id
Entity = "post"
CurrentTitle = post.Title
Revisions = post.Revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
@@ -1114,15 +1114,15 @@ type PostListItem = {
static member fromPost (webLog: WebLog) (post: Post) =
let _, extra = WebLog.hostAndPath webLog
let inTZ = WebLog.localTime webLog
- { Id = post.Id.Value
- AuthorId = WebLogUserId.toString post.AuthorId
- Status = post.Status.Value
+ { Id = string post.Id
+ AuthorId = string post.AuthorId
+ Status = string post.Status
Title = post.Title
- Permalink = post.Permalink.Value
+ Permalink = string post.Permalink
PublishedOn = post.PublishedOn |> Option.map inTZ |> Option.toNullable
UpdatedOn = inTZ post.UpdatedOn
Text = addBaseToRelativeUrls extra post.Text
- CategoryIds = post.CategoryIds |> List.map _.Value
+ CategoryIds = post.CategoryIds |> List.map string
Tags = post.Tags
Episode = post.Episode
Metadata = post.Metadata
@@ -1156,46 +1156,46 @@ type PostDisplay =
/// View model for editing web log settings
[]
-type SettingsModel =
- { /// The name of the web log
- Name : string
+type SettingsModel = {
+ /// The name of the web log
+ Name: string
- /// The slug of the web log
- Slug : string
-
- /// The subtitle of the web log
- Subtitle : string
+ /// The slug of the web log
+ Slug: string
+
+ /// The subtitle of the web log
+ Subtitle: string
- /// The default page
- DefaultPage : string
+ /// The default page
+ DefaultPage: string
- /// How many posts should appear on index pages
- PostsPerPage : int
+ /// How many posts should appear on index pages
+ PostsPerPage: int
- /// The time zone in which dates/times should be displayed
- TimeZone : string
-
- /// The theme to use to display the web log
- ThemeId : string
-
- /// Whether to automatically load htmx
- AutoHtmx : bool
-
- /// The default location for uploads
- Uploads : string
- }
+ /// The time zone in which dates/times should be displayed
+ TimeZone: string
+
+ /// The theme to use to display the web log
+ ThemeId: string
+
+ /// Whether to automatically load htmx
+ AutoHtmx: bool
+
+ /// The default location for uploads
+ Uploads: string
+} with
/// Create a settings model from a web log
- static member fromWebLog (webLog : WebLog) =
+ static member fromWebLog (webLog: WebLog) =
{ Name = webLog.Name
Slug = webLog.Slug
Subtitle = defaultArg webLog.Subtitle ""
DefaultPage = webLog.DefaultPage
PostsPerPage = webLog.PostsPerPage
TimeZone = webLog.TimeZone
- ThemeId = ThemeId.toString webLog.ThemeId
+ ThemeId = string webLog.ThemeId
AutoHtmx = webLog.AutoHtmx
- Uploads = UploadDestination.toString webLog.Uploads
+ Uploads = string webLog.Uploads
}
/// Update a web log with settings from the form
@@ -1209,7 +1209,7 @@ type SettingsModel =
TimeZone = this.TimeZone
ThemeId = ThemeId this.ThemeId
AutoHtmx = this.AutoHtmx
- Uploads = UploadDestination.parse this.Uploads
+ Uploads = UploadDestination.Parse this.Uploads
}
diff --git a/src/MyWebLog/Caches.fs b/src/MyWebLog/Caches.fs
index 05bda8f..74b09d9 100644
--- a/src/MyWebLog/Caches.fs
+++ b/src/MyWebLog/Caches.fs
@@ -194,8 +194,8 @@ module TemplateCache =
let private hasInclude = Regex ("""{% include_template \"(.*)\" %}""", RegexOptions.None, TimeSpan.FromSeconds 2)
/// Get a template for the given theme and template name
- let get (themeId : ThemeId) (templateName : string) (data : IData) = backgroundTask {
- let templatePath = $"{ThemeId.toString themeId}/{templateName}"
+ let get (themeId: ThemeId) (templateName: string) (data: IData) = backgroundTask {
+ let templatePath = $"{themeId}/{templateName}"
match _cache.ContainsKey templatePath with
| true -> return Ok _cache[templatePath]
| false ->
@@ -215,7 +215,7 @@ module TemplateCache =
if childNotFound = "" then child.Groups[1].Value
else $"{childNotFound}; {child.Groups[1].Value}"
""
- text <- text.Replace (child.Value, childText)
+ text <- text.Replace(child.Value, childText)
if childNotFound <> "" then
let s = if childNotFound.IndexOf ";" >= 0 then "s" else ""
return Error $"Could not find the child template{s} {childNotFound} required by {templateName}"
@@ -223,8 +223,8 @@ module TemplateCache =
_cache[templatePath] <- Template.Parse (text, SyntaxCompatibility.DotLiquid22)
return Ok _cache[templatePath]
| None ->
- return Error $"Theme ID {ThemeId.toString themeId} does not have a template named {templateName}"
- | None -> return Result.Error $"Theme ID {ThemeId.toString themeId} does not exist"
+ return Error $"Theme ID {themeId} does not have a template named {templateName}"
+ | None -> return Error $"Theme ID {themeId} does not exist"
}
/// Get all theme/template names currently cached
@@ -232,16 +232,16 @@ module TemplateCache =
_cache.Keys |> Seq.sort |> Seq.toList
/// Invalidate all template cache entries for the given theme ID
- let invalidateTheme (themeId : ThemeId) =
- let keyPrefix = ThemeId.toString themeId
+ let invalidateTheme (themeId: ThemeId) =
+ let keyPrefix = string themeId
_cache.Keys
- |> Seq.filter (fun key -> key.StartsWith keyPrefix)
+ |> Seq.filter _.StartsWith(keyPrefix)
|> List.ofSeq
|> List.iter (fun key -> match _cache.TryRemove key with _, _ -> ())
/// Remove all entries from the template cache
let empty () =
- _cache.Clear ()
+ _cache.Clear()
/// A cache of asset names by themes
diff --git a/src/MyWebLog/DotLiquidBespoke.fs b/src/MyWebLog/DotLiquidBespoke.fs
index 45006b7..2718d43 100644
--- a/src/MyWebLog/DotLiquidBespoke.fs
+++ b/src/MyWebLog/DotLiquidBespoke.fs
@@ -95,9 +95,9 @@ type NavLinkFilter () =
/// A filter to generate a link for theme asset (image, stylesheet, script, etc.)
-type ThemeAssetFilter () =
- static member ThemeAsset (ctx : Context, asset : string) =
- WebLog.relativeUrl ctx.WebLog (Permalink $"themes/{ThemeId.toString ctx.WebLog.ThemeId}/{asset}")
+type ThemeAssetFilter() =
+ static member ThemeAsset(ctx: Context, asset: string) =
+ WebLog.relativeUrl ctx.WebLog (Permalink $"themes/{ctx.WebLog.ThemeId}/{asset}")
/// Create various items in the page header based on the state of the page being generated
diff --git a/src/MyWebLog/Handlers/Admin.fs b/src/MyWebLog/Handlers/Admin.fs
index 0e9af33..42bed16 100644
--- a/src/MyWebLog/Handlers/Admin.fs
+++ b/src/MyWebLog/Handlers/Admin.fs
@@ -37,7 +37,7 @@ module Dashboard =
let admin : HttpHandler = requireAccess Administrator >=> fun next ctx -> task {
match! TemplateCache.get adminTheme "theme-list-body" ctx.Data with
| Ok bodyTemplate ->
- let! themes = ctx.Data.Theme.All ()
+ let! themes = ctx.Data.Theme.All()
let cachedTemplates = TemplateCache.allNames ()
let! hash =
hashForPage "myWebLog Administration"
@@ -50,10 +50,10 @@ module Dashboard =
themes
|> Seq.ofList
|> Seq.map (fun it -> [|
- ThemeId.toString it.Id
+ string it.Id
it.Name
cachedTemplates
- |> List.filter (fun n -> n.StartsWith (ThemeId.toString it.Id))
+ |> List.filter _.StartsWith(string it.Id)
|> List.length
|> string
|])
@@ -61,8 +61,8 @@ module Dashboard =
|> addToHash "web_logs" (
WebLogCache.all ()
|> Seq.ofList
- |> Seq.sortBy (fun it -> it.Name)
- |> Seq.map (fun it -> [| WebLogId.toString it.Id; it.Name; it.UrlBase |])
+ |> Seq.sortBy _.Name
+ |> Seq.map (fun it -> [| string it.Id; it.Name; it.UrlBase |])
|> Array.ofSeq)
|> addViewContext ctx
return!
@@ -317,7 +317,7 @@ module TagMapping =
addToHash "mappings" mappings hash
|> addToHash "mapping_ids" (
mappings
- |> List.map (fun it -> { Name = it.Tag; Value = TagMapId.toString it.Id }))
+ |> List.map (fun it -> { Name = it.Tag; Value = string it.Id }))
}
// GET /admin/settings/tag-mappings
@@ -348,13 +348,13 @@ module TagMapping =
// POST /admin/settings/tag-mapping/save
let save : HttpHandler = fun next ctx -> task {
let data = ctx.Data
- let! model = ctx.BindFormAsync ()
+ let! model = ctx.BindFormAsync()
let tagMap =
- if model.IsNew then someTask { TagMap.empty with Id = TagMapId.create (); WebLogId = ctx.WebLog.Id }
+ if model.IsNew then someTask { TagMap.empty with Id = TagMapId.Create(); WebLogId = ctx.WebLog.Id }
else data.TagMap.FindById (TagMapId model.Id) ctx.WebLog.Id
match! tagMap with
| Some tm ->
- do! data.TagMap.Save { tm with Tag = model.Tag.ToLower (); UrlValue = model.UrlValue.ToLower () }
+ do! data.TagMap.Save { tm with Tag = model.Tag.ToLower(); UrlValue = model.UrlValue.ToLower() }
do! addMessage ctx { UserMessage.success with Message = "Tag mapping saved successfully" }
return! all next ctx
| None -> return! Error.notFound next ctx
@@ -395,17 +395,17 @@ module Theme =
|> adminBareView "theme-upload" next ctx
/// Update the name and version for a theme based on the version.txt file, if present
- let private updateNameAndVersion (theme : Theme) (zip : ZipArchive) = backgroundTask {
+ let private updateNameAndVersion (theme: Theme) (zip: ZipArchive) = backgroundTask {
let now () = DateTime.UtcNow.ToString "yyyyMMdd.HHmm"
match zip.Entries |> Seq.filter (fun it -> it.FullName = "version.txt") |> Seq.tryHead with
| Some versionItem ->
- use versionFile = new StreamReader(versionItem.Open ())
- let! versionText = versionFile.ReadToEndAsync ()
+ use versionFile = new StreamReader(versionItem.Open())
+ let! versionText = versionFile.ReadToEndAsync()
let parts = versionText.Trim().Replace("\r", "").Split "\n"
- let displayName = if parts[0] > "" then parts[0] else ThemeId.toString theme.Id
+ let displayName = if parts[0] > "" then parts[0] else string theme.Id
let version = if parts.Length > 1 && parts[1] > "" then parts[1] else now ()
return { theme with Name = displayName; Version = version }
- | None -> return { theme with Name = ThemeId.toString theme.Id; Version = now () }
+ | None -> return { theme with Name = string theme.Id; Version = now () }
}
/// Update the theme with all templates from the ZIP archive
@@ -476,16 +476,16 @@ module Theme =
let data = ctx.Data
let! exists = data.Theme.Exists themeId
let isNew = not exists
- let! model = ctx.BindFormAsync ()
+ let! model = ctx.BindFormAsync()
if isNew || model.DoOverwrite then
// Load the theme to the database
- use stream = new MemoryStream ()
+ use stream = new MemoryStream()
do! themeFile.CopyToAsync stream
let! _ = loadFromZip themeId stream data
do! ThemeAssetCache.refreshTheme themeId data
TemplateCache.invalidateTheme themeId
// Save the .zip file
- use file = new FileStream ($"{ThemeId.toString themeId}-theme.zip", FileMode.Create)
+ use file = new FileStream($"{themeId}-theme.zip", FileMode.Create)
do! themeFile.CopyToAsync file
do! addMessage ctx
{ UserMessage.success with
@@ -556,18 +556,18 @@ module WebLog =
KeyValuePair.Create("posts", "- First Page of Posts -")
yield! allPages
|> List.sortBy _.Title.ToLower()
- |> List.map (fun p -> KeyValuePair.Create(p.Id.Value, p.Title))
+ |> List.map (fun p -> KeyValuePair.Create(string p.Id, p.Title))
}
|> Array.ofSeq)
|> addToHash "themes" (
themes
|> Seq.ofList
|> Seq.map (fun it ->
- KeyValuePair.Create (ThemeId.toString it.Id, $"{it.Name} (v{it.Version})"))
+ KeyValuePair.Create(string it.Id, $"{it.Name} (v{it.Version})"))
|> Array.ofSeq)
|> addToHash "upload_values" [|
- KeyValuePair.Create (UploadDestination.toString Database, "Database")
- KeyValuePair.Create (UploadDestination.toString Disk, "Disk")
+ KeyValuePair.Create(string Database, "Database")
+ KeyValuePair.Create(string Disk, "Disk")
|]
|> addToHash "users" (users |> List.map (DisplayUser.fromUser ctx.WebLog) |> Array.ofList)
|> addToHash "rss_model" (EditRssModel.fromRssOptions ctx.WebLog.Rss)
diff --git a/src/MyWebLog/Handlers/Feed.fs b/src/MyWebLog/Handlers/Feed.fs
index 1d8dcda..605b038 100644
--- a/src/MyWebLog/Handlers/Feed.fs
+++ b/src/MyWebLog/Handlers/Feed.fs
@@ -37,7 +37,7 @@ let deriveFeedType (ctx : HttpContext) feedPath : (FeedType * int) option =
| false ->
// Category and tag feeds are handled by defined routes; check for custom feed
match webLog.Rss.CustomFeeds
- |> List.tryFind (fun it -> feedPath.EndsWith it.Path.Value) with
+ |> List.tryFind (fun it -> feedPath.EndsWith(string it.Path)) with
| Some feed ->
debug (fun () -> "Found custom feed")
Some (Custom (feed, feedPath), feed.Podcast |> Option.map _.ItemsInFeed |> Option.defaultValue postCount)
@@ -48,7 +48,7 @@ let deriveFeedType (ctx : HttpContext) feedPath : (FeedType * int) option =
/// Determine the function to retrieve posts for the given feed
let private getFeedPosts ctx feedType =
let childIds (catId: CategoryId) =
- let cat = CategoryCache.get ctx |> Array.find (fun c -> c.Id = catId.Value)
+ let cat = CategoryCache.get ctx |> Array.find (fun c -> c.Id = string catId)
getCategoryIds cat.Slug ctx
let data = ctx.Data
match feedType with
@@ -86,51 +86,50 @@ module private Namespace =
let rawVoice = "http://www.rawvoice.com/rawvoiceRssModule/"
/// Create a feed item from the given post
-let private toFeedItem webLog (authors : MetaItem list) (cats : DisplayCategory[]) (tagMaps : TagMap list)
- (post : Post) =
+let private toFeedItem webLog (authors: MetaItem list) (cats: DisplayCategory array) (tagMaps: TagMap list)
+ (post: Post) =
let plainText =
let endingP = post.Text.IndexOf "
"
stripHtml <| if endingP >= 0 then post.Text[..(endingP - 1)] else post.Text
- let item = SyndicationItem (
+ let item = SyndicationItem(
Id = WebLog.absoluteUrl webLog post.Permalink,
Title = TextSyndicationContent.CreateHtmlContent post.Title,
- PublishDate = post.PublishedOn.Value.ToDateTimeOffset (),
- LastUpdatedTime = post.UpdatedOn.ToDateTimeOffset (),
+ PublishDate = post.PublishedOn.Value.ToDateTimeOffset(),
+ LastUpdatedTime = post.UpdatedOn.ToDateTimeOffset(),
Content = TextSyndicationContent.CreatePlaintextContent plainText)
item.AddPermalink (Uri item.Id)
- let xmlDoc = XmlDocument ()
+ let xmlDoc = XmlDocument()
let encoded =
let txt =
post.Text
.Replace("src=\"/", $"src=\"{webLog.UrlBase}/")
- .Replace ("href=\"/", $"href=\"{webLog.UrlBase}/")
- let it = xmlDoc.CreateElement ("content", "encoded", Namespace.content)
- let _ = it.AppendChild (xmlDoc.CreateCDataSection txt)
+ .Replace("href=\"/", $"href=\"{webLog.UrlBase}/")
+ let it = xmlDoc.CreateElement("content", "encoded", Namespace.content)
+ let _ = it.AppendChild(xmlDoc.CreateCDataSection txt)
it
item.ElementExtensions.Add encoded
- item.Authors.Add (SyndicationPerson (
- Name = (authors |> List.find (fun a -> a.Name = WebLogUserId.toString post.AuthorId)).Value))
+ item.Authors.Add(SyndicationPerson(Name = (authors |> List.find (fun a -> a.Name = string post.AuthorId)).Value))
[ post.CategoryIds
|> List.map (fun catId ->
- let cat = cats |> Array.find (fun c -> c.Id = catId.Value)
- SyndicationCategory (cat.Name, WebLog.absoluteUrl webLog (Permalink $"category/{cat.Slug}/"), cat.Name))
+ let cat = cats |> Array.find (fun c -> c.Id = string catId)
+ SyndicationCategory(cat.Name, WebLog.absoluteUrl webLog (Permalink $"category/{cat.Slug}/"), cat.Name))
post.Tags
|> List.map (fun tag ->
let urlTag =
match tagMaps |> List.tryFind (fun tm -> tm.Tag = tag) with
| Some tm -> tm.UrlValue
| None -> tag.Replace (" ", "+")
- SyndicationCategory (tag, WebLog.absoluteUrl webLog (Permalink $"tag/{urlTag}/"), $"{tag} (tag)"))
+ SyndicationCategory(tag, WebLog.absoluteUrl webLog (Permalink $"tag/{urlTag}/"), $"{tag} (tag)"))
]
|> List.concat
|> List.iter item.Categories.Add
item
/// Convert non-absolute URLs to an absolute URL for this web log
-let toAbsolute webLog (link : string) =
+let toAbsolute webLog (link: string) =
if link.StartsWith "http" then link else WebLog.absoluteUrl webLog (Permalink link)
/// Add episode information to a podcast feed item
@@ -141,8 +140,8 @@ let private addEpisode webLog (podcast : PodcastOptions) (episode : Episode) (po
| link when Option.isSome podcast.MediaBaseUrl -> $"{podcast.MediaBaseUrl.Value}{link}"
| link -> WebLog.absoluteUrl webLog (Permalink link)
let epMediaType = [ episode.MediaType; podcast.DefaultMediaType ] |> List.tryFind Option.isSome |> Option.flatten
- let epImageUrl = defaultArg episode.ImageUrl podcast.ImageUrl.Value |> toAbsolute webLog
- let epExplicit = (defaultArg episode.Explicit podcast.Explicit).Value
+ let epImageUrl = defaultArg episode.ImageUrl (string podcast.ImageUrl) |> toAbsolute webLog
+ let epExplicit = string (defaultArg episode.Explicit podcast.Explicit)
let xmlDoc = XmlDocument()
let enclosure =
@@ -298,7 +297,7 @@ let private addPodcast webLog (rssFeed : SyndicationFeed) (feed : CustomFeed) =
rssFeed.ElementExtensions.Add rawVoice
rssFeed.ElementExtensions.Add("summary", Namespace.iTunes, podcast.Summary)
rssFeed.ElementExtensions.Add("author", Namespace.iTunes, podcast.DisplayedAuthor)
- rssFeed.ElementExtensions.Add("explicit", Namespace.iTunes, podcast.Explicit.Value)
+ rssFeed.ElementExtensions.Add("explicit", Namespace.iTunes, string podcast.Explicit)
podcast.Subtitle |> Option.iter (fun sub -> rssFeed.ElementExtensions.Add ("subtitle", Namespace.iTunes, sub))
podcast.FundingUrl
|> Option.iter (fun url ->
@@ -309,7 +308,7 @@ let private addPodcast webLog (rssFeed : SyndicationFeed) (feed : CustomFeed) =
podcast.PodcastGuid
|> Option.iter (fun guid ->
rssFeed.ElementExtensions.Add("guid", Namespace.podcast, guid.ToString().ToLowerInvariant()))
- podcast.Medium |> Option.iter (fun med -> rssFeed.ElementExtensions.Add("medium", Namespace.podcast, med.Value))
+ podcast.Medium |> Option.iter (fun med -> rssFeed.ElementExtensions.Add("medium", Namespace.podcast, string med))
/// Get the feed's self reference and non-feed link
let private selfAndLink webLog feedType ctx =
@@ -368,7 +367,7 @@ let createFeed (feedType : FeedType) posts : HttpHandler = fun next ctx -> backg
match podcast, post.Episode with
| Some feed, Some episode -> addEpisode webLog (Option.get feed.Podcast) episode post item
| Some _, _ ->
- warn "Feed" ctx $"[{webLog.Name} {self.Value}] \"{stripHtml post.Title}\" has no media"
+ warn "Feed" ctx $"[{webLog.Name} {self}] \"{stripHtml post.Title}\" has no media"
item
| _ -> item
@@ -427,7 +426,7 @@ let saveSettings : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> t
let editCustomFeed feedId : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx ->
let customFeed =
match feedId with
- | "new" -> Some { CustomFeed.empty with Id = CustomFeedId "new" }
+ | "new" -> Some { CustomFeed.Empty with Id = CustomFeedId "new" }
| _ -> ctx.WebLog.Rss.CustomFeeds |> List.tryFind (fun f -> f.Id = CustomFeedId feedId)
match customFeed with
| Some f ->
@@ -436,13 +435,13 @@ let editCustomFeed feedId : HttpHandler = requireAccess WebLogAdmin >=> fun next
|> addToHash ViewContext.Model (EditCustomFeedModel.fromFeed f)
|> addToHash "medium_values" [|
KeyValuePair.Create("", "– Unspecified –")
- KeyValuePair.Create(Podcast.Value, "Podcast")
- KeyValuePair.Create(Music.Value, "Music")
- KeyValuePair.Create(Video.Value, "Video")
- KeyValuePair.Create(Film.Value, "Film")
- KeyValuePair.Create(Audiobook.Value, "Audiobook")
- KeyValuePair.Create(Newsletter.Value, "Newsletter")
- KeyValuePair.Create(Blog.Value, "Blog")
+ KeyValuePair.Create(string Podcast, "Podcast")
+ KeyValuePair.Create(string Music, "Music")
+ KeyValuePair.Create(string Video, "Video")
+ KeyValuePair.Create(string Film, "Film")
+ KeyValuePair.Create(string Audiobook, "Audiobook")
+ KeyValuePair.Create(string Newsletter, "Newsletter")
+ KeyValuePair.Create(string Blog, "Blog")
|]
|> adminView "custom-feed-edit" next ctx
| None -> Error.notFound next ctx
@@ -455,8 +454,8 @@ let saveCustomFeed : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx ->
let! model = ctx.BindFormAsync ()
let theFeed =
match model.Id with
- | "new" -> Some { CustomFeed.empty with Id = CustomFeedId.create () }
- | _ -> webLog.Rss.CustomFeeds |> List.tryFind (fun it -> CustomFeedId.toString it.Id = model.Id)
+ | "new" -> Some { CustomFeed.Empty with Id = CustomFeedId.Create() }
+ | _ -> webLog.Rss.CustomFeeds |> List.tryFind (fun it -> string it.Id = model.Id)
match theFeed with
| Some feed ->
let feeds = model.UpdateFeed feed :: (webLog.Rss.CustomFeeds |> List.filter (fun it -> it.Id <> feed.Id))
@@ -467,7 +466,7 @@ let saveCustomFeed : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx ->
UserMessage.success with
Message = $"""Successfully {if model.Id = "new" then "add" else "sav"}ed custom feed"""
}
- return! redirectToGet $"admin/settings/rss/{CustomFeedId.toString feed.Id}/edit" next ctx
+ return! redirectToGet $"admin/settings/rss/{feed.Id}/edit" next ctx
| None -> return! Error.notFound next ctx
| None -> return! Error.notFound next ctx
}
diff --git a/src/MyWebLog/Handlers/Helpers.fs b/src/MyWebLog/Handlers/Helpers.fs
index b1f4bd3..a2a9ded 100644
--- a/src/MyWebLog/Handlers/Helpers.fs
+++ b/src/MyWebLog/Handlers/Helpers.fs
@@ -352,8 +352,8 @@ let requireAccess level : HttpHandler = fun next ctx -> task {
| Some userLevel ->
do! addMessage ctx
{ UserMessage.warning with
- Message = $"The page you tried to access requires {level.Value} privileges"
- Detail = Some $"Your account only has {userLevel.Value} privileges"
+ Message = $"The page you tried to access requires {level} privileges"
+ Detail = Some $"Your account only has {userLevel} privileges"
}
return! Error.notAuthorized next ctx
| None ->
diff --git a/src/MyWebLog/Handlers/Page.fs b/src/MyWebLog/Handlers/Page.fs
index 1eece85..1c442f5 100644
--- a/src/MyWebLog/Handlers/Page.fs
+++ b/src/MyWebLog/Handlers/Page.fs
@@ -193,7 +193,7 @@ let save : HttpHandler = requireAccess Author >=> fun next ctx -> task {
do! (if model.IsNew then data.Page.Add else data.Page.Update) updatedPage
if updateList then do! PageListCache.update ctx
do! addMessage ctx { UserMessage.success with Message = "Page saved successfully" }
- return! redirectToGet $"admin/page/{page.Id.Value}/edit" next ctx
+ return! redirectToGet $"admin/page/{page.Id}/edit" next ctx
| Some _ -> return! Error.notAuthorized next ctx
| None -> return! Error.notFound next ctx
}
diff --git a/src/MyWebLog/Handlers/Post.fs b/src/MyWebLog/Handlers/Post.fs
index d9e87cd..ee8b3db 100644
--- a/src/MyWebLog/Handlers/Post.fs
+++ b/src/MyWebLog/Handlers/Post.fs
@@ -58,7 +58,7 @@ let preparePostList webLog posts listType (url: string) pageNbr perPage (data: I
| _ -> Task.FromResult (None, None)
let newerLink =
match listType, pageNbr with
- | SinglePost, _ -> newerPost |> Option.map _.Permalink.Value
+ | SinglePost, _ -> newerPost |> Option.map (fun it -> string it.Permalink)
| _, 1 -> None
| PostList, 2 when webLog.DefaultPage = "posts" -> Some ""
| PostList, _ -> relUrl $"page/{pageNbr - 1}"
@@ -70,7 +70,7 @@ let preparePostList webLog posts listType (url: string) pageNbr perPage (data: I
| AdminList, _ -> relUrl $"admin/posts/page/{pageNbr - 1}"
let olderLink =
match listType, List.length posts > perPage with
- | SinglePost, _ -> olderPost |> Option.map _.Permalink.Value
+ | SinglePost, _ -> olderPost |> Option.map (fun it -> string it.Permalink)
| _, false -> None
| PostList, true -> relUrl $"page/{pageNbr + 1}"
| CategoryList, true -> relUrl $"category/{url}/page/{pageNbr + 1}"
@@ -243,9 +243,9 @@ let edit postId : HttpHandler = requireAccess Author >=> fun next ctx -> task {
|> addToHash "templates" templates
|> addToHash "explicit_values" [|
KeyValuePair.Create("", "– Default –")
- KeyValuePair.Create(Yes.Value, "Yes")
- KeyValuePair.Create(No.Value, "No")
- KeyValuePair.Create(Clean.Value, "Clean")
+ KeyValuePair.Create(string Yes, "Yes")
+ KeyValuePair.Create(string No, "No")
+ KeyValuePair.Create(string Clean, "Clean")
|]
|> adminView "post-edit" next ctx
| Some _ -> return! Error.notAuthorized next ctx
@@ -410,7 +410,7 @@ let save : HttpHandler = requireAccess Author >=> fun next ctx -> task {
|> List.length = List.length priorCats) then
do! CategoryCache.update ctx
do! addMessage ctx { UserMessage.success with Message = "Post saved successfully" }
- return! redirectToGet $"admin/post/{post.Id.Value}/edit" next ctx
+ return! redirectToGet $"admin/post/{post.Id}/edit" next ctx
| Some _ -> return! Error.notAuthorized next ctx
| None -> return! Error.notFound next ctx
}
diff --git a/src/MyWebLog/Handlers/Routes.fs b/src/MyWebLog/Handlers/Routes.fs
index c128864..72582ad 100644
--- a/src/MyWebLog/Handlers/Routes.fs
+++ b/src/MyWebLog/Handlers/Routes.fs
@@ -88,13 +88,13 @@ module CatchAll =
module Asset =
// GET /theme/{theme}/{**path}
- let serve (urlParts : string seq) : HttpHandler = fun next ctx -> task {
+ let serve (urlParts: string seq) : HttpHandler = fun next ctx -> task {
let path = urlParts |> Seq.skip 1 |> Seq.head
- match! ctx.Data.ThemeAsset.FindById (ThemeAssetId.ofString path) with
+ match! ctx.Data.ThemeAsset.FindById(ThemeAssetId.Parse path) with
| Some asset ->
match Upload.checkModified asset.UpdatedOn ctx with
| Some threeOhFour -> return! threeOhFour next ctx
- | None -> return! Upload.sendFile (asset.UpdatedOn.ToDateTimeUtc ()) path asset.Data next ctx
+ | None -> return! Upload.sendFile (asset.UpdatedOn.ToDateTimeUtc()) path asset.Data next ctx
| None -> return! Error.notFound next ctx
}
diff --git a/src/MyWebLog/Handlers/Upload.fs b/src/MyWebLog/Handlers/Upload.fs
index c1c840d..f192f76 100644
--- a/src/MyWebLog/Handlers/Upload.fs
+++ b/src/MyWebLog/Handlers/Upload.fs
@@ -107,7 +107,7 @@ let list : HttpHandler = requireAccess Author >=> fun next ctx -> task {
Name = name
Path = file.Replace($"{path}{slash}", "").Replace(name, "").Replace (slash, '/')
UpdatedOn = create
- Source = UploadDestination.toString Disk
+ Source = string Disk
})
|> List.ofSeq
with
@@ -131,7 +131,7 @@ let list : HttpHandler = requireAccess Author >=> fun next ctx -> task {
let showNew : HttpHandler = requireAccess Author >=> fun next ctx ->
hashForPage "Upload a File"
|> withAntiCsrf ctx
- |> addToHash "destination" (UploadDestination.toString ctx.WebLog.Uploads)
+ |> addToHash "destination" (string ctx.WebLog.Uploads)
|> adminView "upload-new" next ctx
@@ -144,29 +144,29 @@ let save : HttpHandler = requireAccess Author >=> fun next ctx -> task {
if ctx.Request.HasFormContentType && ctx.Request.Form.Files.Count > 0 then
let upload = Seq.head ctx.Request.Form.Files
let fileName = String.Concat (makeSlug (Path.GetFileNameWithoutExtension upload.FileName),
- Path.GetExtension(upload.FileName).ToLowerInvariant ())
+ Path.GetExtension(upload.FileName).ToLowerInvariant())
let now = Noda.now ()
let localNow = WebLog.localTime ctx.WebLog now
let year = localNow.ToString "yyyy"
let month = localNow.ToString "MM"
- let! form = ctx.BindFormAsync ()
+ let! form = ctx.BindFormAsync()
- match UploadDestination.parse form.Destination with
+ match UploadDestination.Parse form.Destination with
| Database ->
- use stream = new MemoryStream ()
+ use stream = new MemoryStream()
do! upload.CopyToAsync stream
let file =
- { Id = UploadId.create ()
+ { Id = UploadId.Create()
WebLogId = ctx.WebLog.Id
Path = Permalink $"{year}/{month}/{fileName}"
UpdatedOn = now
- Data = stream.ToArray ()
+ Data = stream.ToArray()
}
do! ctx.Data.Upload.Add file
| Disk ->
- let fullPath = Path.Combine (uploadDir, ctx.WebLog.Slug, year, month)
+ let fullPath = Path.Combine(uploadDir, ctx.WebLog.Slug, year, month)
let _ = Directory.CreateDirectory fullPath
- use stream = new FileStream (Path.Combine (fullPath, fileName), FileMode.Create)
+ use stream = new FileStream(Path.Combine(fullPath, fileName), FileMode.Create)
do! upload.CopyToAsync stream
do! addMessage ctx { UserMessage.success with Message = $"File uploaded to {form.Destination} successfully" }
diff --git a/src/MyWebLog/Handlers/User.fs b/src/MyWebLog/Handlers/User.fs
index 389fe56..f9a039d 100644
--- a/src/MyWebLog/Handlers/User.fs
+++ b/src/MyWebLog/Handlers/User.fs
@@ -48,22 +48,22 @@ open Microsoft.AspNetCore.Authentication.Cookies
// POST /user/log-on
let doLogOn : HttpHandler = fun next ctx -> task {
- let! model = ctx.BindFormAsync ()
+ let! model = ctx.BindFormAsync()
let data = ctx.Data
let! tryUser = data.WebLogUser.FindByEmail model.EmailAddress ctx.WebLog.Id
match! verifyPassword tryUser model.Password ctx with
| Ok _ ->
let user = tryUser.Value
let claims = seq {
- Claim (ClaimTypes.NameIdentifier, WebLogUserId.toString user.Id)
- Claim (ClaimTypes.Name, $"{user.FirstName} {user.LastName}")
- Claim (ClaimTypes.GivenName, user.PreferredName)
- Claim (ClaimTypes.Role, user.AccessLevel.Value)
+ Claim(ClaimTypes.NameIdentifier, string user.Id)
+ Claim(ClaimTypes.Name, $"{user.FirstName} {user.LastName}")
+ Claim(ClaimTypes.GivenName, user.PreferredName)
+ Claim(ClaimTypes.Role, string user.AccessLevel)
}
- let identity = ClaimsIdentity (claims, CookieAuthenticationDefaults.AuthenticationScheme)
+ let identity = ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme)
- do! ctx.SignInAsync (identity.AuthenticationType, ClaimsPrincipal identity,
- AuthenticationProperties (IssuedUtc = DateTimeOffset.UtcNow))
+ do! ctx.SignInAsync(identity.AuthenticationType, ClaimsPrincipal identity,
+ AuthenticationProperties(IssuedUtc = DateTimeOffset.UtcNow))
do! data.WebLogUser.SetLastSeen user.Id user.WebLogId
do! addMessage ctx
{ UserMessage.success with
@@ -110,10 +110,10 @@ let private showEdit (model : EditUserModel) : HttpHandler = fun next ctx ->
|> withAntiCsrf ctx
|> addToHash ViewContext.Model model
|> addToHash "access_levels" [|
- KeyValuePair.Create(Author.Value, "Author")
- KeyValuePair.Create(Editor.Value, "Editor")
- KeyValuePair.Create(WebLogAdmin.Value, "Web Log Admin")
- if ctx.HasAccessLevel Administrator then KeyValuePair.Create(Administrator.Value, "Administrator")
+ KeyValuePair.Create(string Author, "Author")
+ KeyValuePair.Create(string Editor, "Editor")
+ KeyValuePair.Create(string WebLogAdmin, "Web Log Admin")
+ if ctx.HasAccessLevel Administrator then KeyValuePair.Create(string Administrator, "Administrator")
|]
|> adminBareView "user-edit" next ctx
@@ -159,7 +159,7 @@ let private showMyInfo (model : EditMyInfoModel) (user : WebLogUser) : HttpHandl
hashForPage "Edit Your Information"
|> withAntiCsrf ctx
|> addToHash ViewContext.Model model
- |> addToHash "access_level" (user.AccessLevel.Value)
+ |> addToHash "access_level" (string user.AccessLevel)
|> addToHash "created_on" (WebLog.localTime ctx.WebLog user.CreatedOn)
|> addToHash "last_seen_on" (WebLog.localTime ctx.WebLog
(defaultArg user.LastSeenOn (Instant.FromUnixTimeSeconds 0)))
@@ -208,7 +208,7 @@ let save : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> task {
let tryUser =
if model.IsNew then
{ WebLogUser.empty with
- Id = WebLogUserId.create ()
+ Id = WebLogUserId.Create()
WebLogId = ctx.WebLog.Id
CreatedOn = Noda.now ()
} |> someTask
diff --git a/src/MyWebLog/Maintenance.fs b/src/MyWebLog/Maintenance.fs
index 8d0f68f..685c9dc 100644
--- a/src/MyWebLog/Maintenance.fs
+++ b/src/MyWebLog/Maintenance.fs
@@ -21,8 +21,8 @@ let private doCreateWebLog (args : string[]) (sp : IServiceProvider) = task {
| false, _ -> raise <| TimeZoneNotFoundException $"Cannot find IANA timezone for {local}"
// Create the web log
- let webLogId = WebLogId.create ()
- let userId = WebLogUserId.create ()
+ let webLogId = WebLogId.Create()
+ let userId = WebLogUserId.Create()
let homePageId = PageId.Create()
let slug = Handlers.Upload.makeSlug args[2]
@@ -37,7 +37,7 @@ let private doCreateWebLog (args : string[]) (sp : IServiceProvider) = task {
Name = args[2]
Slug = slug
UrlBase = args[1]
- DefaultPage = homePageId.Value
+ DefaultPage = string homePageId
TimeZone = timeZone
}
@@ -110,8 +110,8 @@ let private importPriorPermalinks urlBase file (sp : IServiceProvider) = task {
let! withLinks = data.Post.FindFullById post.Id post.WebLogId
let! _ = data.Post.UpdatePriorPermalinks post.Id post.WebLogId
(old :: withLinks.Value.PriorPermalinks)
- printfn $"{old.Value} -> {current.Value}"
- | None -> eprintfn $"Cannot find current post for {current.Value}"
+ printfn $"{old} -> {current}"
+ | None -> eprintfn $"Cannot find current post for {current}"
printfn "Done!"
| None -> eprintfn $"No web log found at {urlBase}"
}
@@ -144,7 +144,7 @@ let loadTheme (args : string[]) (sp : IServiceProvider) = task {
let! theme = Handlers.Admin.Theme.loadFromZip themeId copy data
let fac = sp.GetRequiredService ()
let log = fac.CreateLogger "MyWebLog.Themes"
- log.LogInformation $"{theme.Name} v{theme.Version} ({ThemeId.toString theme.Id}) loaded"
+ log.LogInformation $"{theme.Name} v{theme.Version} ({theme.Id}) loaded"
| Error message -> eprintfn $"{message}"
else
eprintfn "Usage: myWebLog load-theme [theme-zip-file-name]"
@@ -333,13 +333,13 @@ module Backup =
return { archive with WebLog = { archive.WebLog with UrlBase = defaultArg newUrlBase webLog.UrlBase } }
| Some _ ->
// Err'body gets new IDs...
- let newWebLogId = WebLogId.create ()
- let newCatIds = archive.Categories |> List.map (fun cat -> cat.Id, CategoryId.Create ()) |> dict
- let newMapIds = archive.TagMappings |> List.map (fun tm -> tm.Id, TagMapId.create ()) |> dict
- let newPageIds = archive.Pages |> List.map (fun page -> page.Id, PageId.Create ()) |> dict
- let newPostIds = archive.Posts |> List.map (fun post -> post.Id, PostId.Create ()) |> dict
- let newUserIds = archive.Users |> List.map (fun user -> user.Id, WebLogUserId.create ()) |> dict
- let newUpIds = archive.Uploads |> List.map (fun up -> up.Id, UploadId.create ()) |> dict
+ let newWebLogId = WebLogId.Create()
+ let newCatIds = archive.Categories |> List.map (fun cat -> cat.Id, CategoryId.Create() ) |> dict
+ let newMapIds = archive.TagMappings |> List.map (fun tm -> tm.Id, TagMapId.Create() ) |> dict
+ let newPageIds = archive.Pages |> List.map (fun page -> page.Id, PageId.Create() ) |> dict
+ let newPostIds = archive.Posts |> List.map (fun post -> post.Id, PostId.Create() ) |> dict
+ let newUserIds = archive.Users |> List.map (fun user -> user.Id, WebLogUserId.Create()) |> dict
+ let newUpIds = archive.Uploads |> List.map (fun up -> up.Id, UploadId.Create() ) |> dict
return
{ archive with
WebLog = { archive.WebLog with Id = newWebLogId; UrlBase = Option.get newUrlBase }
@@ -481,7 +481,7 @@ let private doUserUpgrade urlBase email (data : IData) = task {
| WebLogAdmin ->
do! data.WebLogUser.Update { user with AccessLevel = Administrator }
printfn $"{email} is now an Administrator user"
- | other -> eprintfn $"ERROR: {email} is an {other.Value}, not a WebLogAdmin"
+ | other -> eprintfn $"ERROR: {email} is an {other}, not a WebLogAdmin"
| None -> eprintfn $"ERROR: no user {email} found at {urlBase}"
| None -> eprintfn $"ERROR: no web log found for {urlBase}"
}
diff --git a/src/MyWebLog/Program.fs b/src/MyWebLog/Program.fs
index a48fc2e..450b383 100644
--- a/src/MyWebLog/Program.fs
+++ b/src/MyWebLog/Program.fs
@@ -15,7 +15,7 @@ type WebLogMiddleware (next : RequestDelegate, log : ILogger)
let path = $"{ctx.Request.Scheme}://{ctx.Request.Host.Value}{ctx.Request.Path.Value}"
match WebLogCache.tryGet path with
| Some webLog ->
- if isDebug then log.LogDebug $"Resolved web log {WebLogId.toString webLog.Id} for {path}"
+ if isDebug then log.LogDebug $"Resolved web log {webLog.Id} for {path}"
ctx.Items["webLog"] <- webLog
if PageListCache.exists ctx then () else do! PageListCache.update ctx
if CategoryCache.exists ctx then () else do! CategoryCache.update ctx