mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-06 20:48:40 +00:00
Compare commits
7 Commits
WoofWare.M
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
669eccbdef | ||
|
1bb87e55da | ||
|
4901e7cdf4 | ||
|
68bd4bc1fd | ||
|
8da0fd01fe | ||
|
18c7a2e920 | ||
|
f371ee59fe |
@@ -3,7 +3,7 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"fantomas": {
|
"fantomas": {
|
||||||
"version": "6.3.7",
|
"version": "6.3.9",
|
||||||
"commands": [
|
"commands": [
|
||||||
"fantomas"
|
"fantomas"
|
||||||
]
|
]
|
||||||
|
14
.github/workflows/assert-contents.sh
vendored
Normal file
14
.github/workflows/assert-contents.sh
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Unzipping version from NuGet"
|
||||||
|
ls from-nuget.nupkg
|
||||||
|
mkdir from-nuget && cp from-nuget.nupkg from-nuget/zip.zip && cd from-nuget && unzip zip.zip && rm zip.zip && cd - || exit 1
|
||||||
|
|
||||||
|
echo "Unzipping version from local build"
|
||||||
|
ls packed/
|
||||||
|
mkdir from-local && cp packed/*.nupkg from-local/zip.zip && cd from-local && unzip zip.zip && rm zip.zip && cd - || exit 1
|
||||||
|
|
||||||
|
cd from-local && find . -type f -exec sha256sum {} \; | sort > ../from-local.txt && cd .. || exit 1
|
||||||
|
cd from-nuget && find . -type f -and -not -name '.signature.p7s' -exec sha256sum {} \; | sort > ../from-nuget.txt && cd .. || exit 1
|
||||||
|
|
||||||
|
diff from-local.txt from-nuget.txt
|
119
.github/workflows/dotnet.yaml
vendored
119
.github/workflows/dotnet.yaml
vendored
@@ -221,11 +221,53 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- run: echo "All required checks complete."
|
- run: echo "All required checks complete."
|
||||||
|
|
||||||
nuget-publish:
|
attestation-attribute:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [all-required-checks-complete]
|
||||||
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Download NuGet artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nuget-package-attribute
|
||||||
|
path: packed
|
||||||
|
- name: Attest Build Provenance
|
||||||
|
uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0
|
||||||
|
with:
|
||||||
|
subject-path: "packed/*.nupkg"
|
||||||
|
|
||||||
|
attestation-plugin:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [all-required-checks-complete]
|
||||||
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Download NuGet artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nuget-package-plugin
|
||||||
|
path: packed
|
||||||
|
- name: Attest Build Provenance
|
||||||
|
uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0
|
||||||
|
with:
|
||||||
|
subject-path: "packed/*.nupkg"
|
||||||
|
|
||||||
|
nuget-publish-attribute:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
needs: [all-required-checks-complete]
|
needs: [all-required-checks-complete]
|
||||||
environment: main-deploy
|
environment: main-deploy
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
@@ -233,20 +275,73 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Download NuGet artifact (plugin)
|
- name: Download NuGet artifact
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: nuget-package-plugin
|
|
||||||
path: packed-plugin
|
|
||||||
- name: Publish to NuGet (plugin)
|
|
||||||
run: nix develop --command dotnet nuget push "packed-plugin/WoofWare.Myriad.Plugins.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
|
||||||
- name: Download NuGet artifact (attribute)
|
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nuget-package-attribute
|
name: nuget-package-attribute
|
||||||
path: packed-attribute
|
path: packed
|
||||||
- name: Publish to NuGet (attribute)
|
- name: Publish to NuGet
|
||||||
run: nix develop --command dotnet nuget push "packed-attribute/WoofWare.Myriad.Plugins.Attributes.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
id: publish-success
|
||||||
|
env:
|
||||||
|
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||||
|
run: 'nix develop --command bash ./.github/workflows/nuget-push.sh "packed/WoofWare.Myriad.Plugins.Attributes.*.nupkg"'
|
||||||
|
- name: Wait for availability
|
||||||
|
if: steps.publish-success.outputs.result == 'published'
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ steps.publish-success.outputs.version }}
|
||||||
|
run: 'echo "$PACKAGE_VERSION" && while ! curl -L --fail -o from-nuget.nupkg "https://www.nuget.org/api/v2/package/WoofWare.Myriad.Plugins.Attributes/$PACKAGE_VERSION" ; do sleep 10; done'
|
||||||
|
# Astonishingly, NuGet.org considers it to be "more secure" to tamper with my package after upload (https://devblogs.microsoft.com/nuget/introducing-repository-signatures/).
|
||||||
|
# So we have to *re-attest* it after it's uploaded. Mind-blowing.
|
||||||
|
- name: Assert package contents
|
||||||
|
if: steps.publish-success.outputs.result == 'published'
|
||||||
|
run: 'bash ./.github/workflows/assert-contents.sh'
|
||||||
|
- name: Attest Build Provenance
|
||||||
|
if: steps.publish-success.outputs.result == 'published'
|
||||||
|
uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0
|
||||||
|
with:
|
||||||
|
subject-path: "from-nuget.nupkg"
|
||||||
|
|
||||||
|
nuget-publish-plugin:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
|
needs: [all-required-checks-complete]
|
||||||
|
environment: main-deploy
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Nix
|
||||||
|
uses: cachix/install-nix-action@V27
|
||||||
|
with:
|
||||||
|
extra_nix_config: |
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download NuGet artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nuget-package-plugin
|
||||||
|
path: packed
|
||||||
|
- name: Publish to NuGet
|
||||||
|
id: publish-success
|
||||||
|
env:
|
||||||
|
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||||
|
run: 'nix develop --command bash ./.github/workflows/nuget-push.sh "packed/WoofWare.Myriad.Plugins.*.nupkg"'
|
||||||
|
- name: Wait for availability
|
||||||
|
if: steps.publish-success.outputs.result == 'published'
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ steps.publish-success.outputs.version }}
|
||||||
|
run: 'echo "$PACKAGE_VERSION" && while ! curl -L --fail -o from-nuget.nupkg "https://www.nuget.org/api/v2/package/WoofWare.Myriad.Plugins/$PACKAGE_VERSION" ; do sleep 10; done'
|
||||||
|
# Astonishingly, NuGet.org considers it to be "more secure" to tamper with my package after upload (https://devblogs.microsoft.com/nuget/introducing-repository-signatures/).
|
||||||
|
# So we have to *re-attest* it after it's uploaded. Mind-blowing.
|
||||||
|
- name: Assert package contents
|
||||||
|
if: steps.publish-success.outputs.result == 'published'
|
||||||
|
run: 'bash ./.github/workflows/assert-contents.sh'
|
||||||
|
- name: Attest Build Provenance
|
||||||
|
if: steps.publish-success.outputs.result == 'published'
|
||||||
|
uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0
|
||||||
|
with:
|
||||||
|
subject-path: "from-nuget.nupkg"
|
||||||
|
|
||||||
github-release-plugin:
|
github-release-plugin:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
24
.github/workflows/nuget-push.sh
vendored
Normal file
24
.github/workflows/nuget-push.sh
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SOURCE_NUPKG=$(find . -type f -name '*.nupkg')
|
||||||
|
|
||||||
|
PACKAGE_VERSION=$(basename "$SOURCE_NUPKG" | rev | cut -d '.' -f 2-4 | rev)
|
||||||
|
|
||||||
|
echo "version=$PACKAGE_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
tmp=$(mktemp)
|
||||||
|
|
||||||
|
if ! dotnet nuget push "$SOURCE_NUPKG" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json > "$tmp" ; then
|
||||||
|
cat "$tmp"
|
||||||
|
if grep 'already exists and cannot be modified' "$tmp" ; then
|
||||||
|
echo "result=skipped" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Unexpected failure to upload"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat "$tmp"
|
||||||
|
|
||||||
|
echo "result=published" >> "$GITHUB_OUTPUT"
|
@@ -4,6 +4,33 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
|
||||||
|
/// Module containing JSON serializing methods for the InternalTypeNotExtensionSerial type
|
||||||
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
|
module internal InternalTypeNotExtensionSerial =
|
||||||
|
/// Serialize to a JSON node
|
||||||
|
let toJsonNode (input : InternalTypeNotExtensionSerial) : System.Text.Json.Nodes.JsonNode =
|
||||||
|
let node = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
do node.Add ((Literals.something), System.Text.Json.Nodes.JsonValue.Create<string> input.InternalThing2)
|
||||||
|
node :> _
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
|
||||||
|
/// Module containing JSON serializing extension members for the InternalTypeExtension type
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal InternalTypeExtensionJsonSerializeExtension =
|
||||||
|
/// Extension methods for JSON parsing
|
||||||
|
type InternalTypeExtension with
|
||||||
|
|
||||||
|
/// Serialize to a JSON node
|
||||||
|
static member toJsonNode (input : InternalTypeExtension) : System.Text.Json.Nodes.JsonNode =
|
||||||
|
let node = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
do node.Add ((Literals.something), System.Text.Json.Nodes.JsonValue.Create<string> input.ExternalThing)
|
||||||
|
node :> _
|
||||||
|
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
@@ -119,6 +146,53 @@ module JsonRecordType =
|
|||||||
}
|
}
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
/// Module containing JSON parsing methods for the InternalTypeNotExtension type
|
||||||
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
|
module internal InternalTypeNotExtension =
|
||||||
|
/// Parse from a JSON node.
|
||||||
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InternalTypeNotExtension =
|
||||||
|
let arg_0 =
|
||||||
|
(match node.[(Literals.something)] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ((Literals.something))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<string> ()
|
||||||
|
|
||||||
|
{
|
||||||
|
InternalThing = arg_0
|
||||||
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
/// Module containing JSON parsing extension members for the InternalTypeExtension type
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal InternalTypeExtensionJsonParseExtension =
|
||||||
|
/// Extension methods for JSON parsing
|
||||||
|
type InternalTypeExtension with
|
||||||
|
|
||||||
|
/// Parse from a JSON node.
|
||||||
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : InternalTypeExtension =
|
||||||
|
let arg_0 =
|
||||||
|
(match node.[(Literals.something)] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ((Literals.something))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<string> ()
|
||||||
|
|
||||||
|
{
|
||||||
|
ExternalThing = arg_0
|
||||||
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing extension members for the ToGetExtensionMethod type
|
/// Module containing JSON parsing extension members for the ToGetExtensionMethod type
|
||||||
[<AutoOpen>]
|
[<AutoOpen>]
|
||||||
module ToGetExtensionMethodJsonParseExtension =
|
module ToGetExtensionMethodJsonParseExtension =
|
||||||
|
@@ -19,9 +19,9 @@ type internal PublicTypeMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PublicTypeMock =
|
static member Empty : PublicTypeMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPublicType with
|
interface IPublicType with
|
||||||
@@ -44,9 +44,9 @@ type public PublicTypeInternalFalseMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PublicTypeInternalFalseMock =
|
static member Empty : PublicTypeInternalFalseMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPublicTypeInternalFalse with
|
interface IPublicTypeInternalFalse with
|
||||||
@@ -68,8 +68,8 @@ type internal InternalTypeMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : InternalTypeMock =
|
static member Empty : InternalTypeMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InternalType with
|
interface InternalType with
|
||||||
@@ -90,8 +90,8 @@ type private PrivateTypeMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PrivateTypeMock =
|
static member Empty : PrivateTypeMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PrivateType with
|
interface PrivateType with
|
||||||
@@ -112,8 +112,8 @@ type private PrivateTypeInternalFalseMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PrivateTypeInternalFalseMock =
|
static member Empty : PrivateTypeInternalFalseMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PrivateTypeInternalFalse with
|
interface PrivateTypeInternalFalse with
|
||||||
@@ -133,7 +133,7 @@ type internal VeryPublicTypeMock<'a, 'b> =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty () : VeryPublicTypeMock<'a, 'b> =
|
static member Empty () : VeryPublicTypeMock<'a, 'b> =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VeryPublicType<'a, 'b> with
|
interface VeryPublicType<'a, 'b> with
|
||||||
@@ -157,12 +157,12 @@ type internal CurriedMock<'a> =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty () : CurriedMock<'a> =
|
static member Empty () : CurriedMock<'a> =
|
||||||
{
|
{
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||||
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4"))
|
||||||
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5"))
|
||||||
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem6"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Curried<'a> with
|
interface Curried<'a> with
|
||||||
@@ -196,8 +196,8 @@ type internal TypeWithInterfaceMock =
|
|||||||
static member Empty : TypeWithInterfaceMock =
|
static member Empty : TypeWithInterfaceMock =
|
||||||
{
|
{
|
||||||
Dispose = (fun () -> ())
|
Dispose = (fun () -> ())
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TypeWithInterface with
|
interface TypeWithInterface with
|
||||||
|
@@ -29,6 +29,28 @@ type JsonRecordType =
|
|||||||
F : int[]
|
F : int[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
|
type internal InternalTypeNotExtension =
|
||||||
|
{
|
||||||
|
[<JsonPropertyName(Literals.something)>]
|
||||||
|
InternalThing : string
|
||||||
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonSerialize>]
|
||||||
|
type internal InternalTypeNotExtensionSerial =
|
||||||
|
{
|
||||||
|
[<JsonPropertyName(Literals.something)>]
|
||||||
|
InternalThing2 : string
|
||||||
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonSerialize true>]
|
||||||
|
type internal InternalTypeExtension =
|
||||||
|
{
|
||||||
|
[<JsonPropertyName(Literals.something)>]
|
||||||
|
ExternalThing : string
|
||||||
|
}
|
||||||
|
|
||||||
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
||||||
type ToGetExtensionMethod =
|
type ToGetExtensionMethod =
|
||||||
{
|
{
|
||||||
|
@@ -10,19 +10,10 @@
|
|||||||
<WarnOn>FS3388,FS3559</WarnOn>
|
<WarnOn>FS3388,FS3559</WarnOn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.133" PrivateAssets="all"/>
|
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.139" PrivateAssets="all"/>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
|
||||||
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
|
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!--
|
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">
|
||||||
SourceLink doesn't support F# deterministic builds out of the box,
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
so tell SourceLink that our source root is going to be remapped.
|
</PropertyGroup>
|
||||||
-->
|
|
||||||
<Target Name="MapSourceRoot" BeforeTargets="_GenerateSourceLinkFile" Condition="'$(SourceRootMappedPathsFeatureSupported)' != 'true'">
|
|
||||||
<ItemGroup>
|
|
||||||
<SourceRoot Update="@(SourceRoot)">
|
|
||||||
<MappedPath>Z:\CheckoutRoot\WoofWare.Myriad\</MappedPath>
|
|
||||||
</SourceRoot>
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
19
README.md
19
README.md
@@ -8,23 +8,20 @@
|
|||||||
|
|
||||||
Some helpers in [Myriad](https://github.com/MoiraeSoftware/myriad/) which might be useful.
|
Some helpers in [Myriad](https://github.com/MoiraeSoftware/myriad/) which might be useful.
|
||||||
|
|
||||||
These are currently somewhat experimental, and I personally am their primary customer.
|
Currently implemented:
|
||||||
The `RemoveOptions` generator in particular is extremely half-baked.
|
|
||||||
|
* `JsonParse` (to stamp out `jsonParse : JsonNode -> 'T` methods).
|
||||||
|
* `JsonSerialize` (to stamp out `toJsonNode : 'T -> JsonNode` methods).
|
||||||
|
* `HttpClient` (to stamp out a [RestEase](https://github.com/canton7/RestEase)-style HTTP client).
|
||||||
|
* `GenerateMock` (to stamp out a record type corresponding to an interface, like a compile-time [Foq](https://github.com/fsprojects/Foq)).
|
||||||
|
* `CreateCatamorphism` (to stamp out a non-stack-overflowing [catamorphism](https://fsharpforfunandprofit.com/posts/recursive-types-and-folds/) for a discriminated union).
|
||||||
|
* `RemoveOptions` (to strip `option` modifiers from a type) - this one is particularly half-baked!
|
||||||
|
|
||||||
If you would like to ensure that your particular use-case remains unbroken, please do contribute tests to this repository.
|
If you would like to ensure that your particular use-case remains unbroken, please do contribute tests to this repository.
|
||||||
The `ConsumePlugin` assembly contains a number of invocations of these source generators,
|
The `ConsumePlugin` assembly contains a number of invocations of these source generators,
|
||||||
so you just need to add copies of your types to that assembly to ensure that I will at least notice if I break the build;
|
so you just need to add copies of your types to that assembly to ensure that I will at least notice if I break the build;
|
||||||
and if you add tests to `WoofWare.Myriad.Plugins.Test` then I will also notice if I break the runtime semantics of the generated code.
|
and if you add tests to `WoofWare.Myriad.Plugins.Test` then I will also notice if I break the runtime semantics of the generated code.
|
||||||
|
|
||||||
Currently implemented:
|
|
||||||
|
|
||||||
* `JsonParse` (to stamp out `jsonParse : JsonNode -> 'T` methods);
|
|
||||||
* `JsonSerialize` (to stamp out `toJsonNode : 'T -> JsonNode` methods);
|
|
||||||
* `RemoveOptions` (to strip `option` modifiers from a type).
|
|
||||||
* `HttpClient` (to stamp out a [RestEase](https://github.com/canton7/RestEase)-style HTTP client).
|
|
||||||
* `GenerateMock` (to stamp out a record type corresponding to an interface).
|
|
||||||
* `CreateCatamorphism` (to stamp out a non-stack-overflowing [catamorphism](https://fsharpforfunandprofit.com/posts/recursive-types-and-folds/) for a discriminated union).
|
|
||||||
|
|
||||||
## `JsonParse`
|
## `JsonParse`
|
||||||
|
|
||||||
Takes records like this:
|
Takes records like this:
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ApiSurface" Version="4.0.40" />
|
<PackageReference Include="ApiSurface" Version="4.0.41" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
||||||
<PackageReference Include="NUnit" Version="4.1.0"/>
|
<PackageReference Include="NUnit" Version="4.1.0"/>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ApiSurface" Version="4.0.40"/>
|
<PackageReference Include="ApiSurface" Version="4.0.41"/>
|
||||||
<PackageReference Include="FsCheck" Version="2.16.6"/>
|
<PackageReference Include="FsCheck" Version="2.16.6"/>
|
||||||
<PackageReference Include="FsUnit" Version="6.0.0"/>
|
<PackageReference Include="FsUnit" Version="6.0.0"/>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
||||||
|
@@ -43,9 +43,14 @@ module internal InterfaceMockGenerator =
|
|||||||
)
|
)
|
||||||
|> Set.ofSeq
|
|> Set.ofSeq
|
||||||
|
|
||||||
let failwithFun =
|
let failwithFun (SynField (_, _, idOpt, _, _, _, _, _, _)) =
|
||||||
|
let failString =
|
||||||
|
match idOpt with
|
||||||
|
| None -> SynExpr.CreateConst "Unimplemented mock function"
|
||||||
|
| Some ident -> SynExpr.CreateConst $"Unimplemented mock function: %s{ident.idText}"
|
||||||
|
|
||||||
SynExpr.createLongIdent [ "System" ; "NotImplementedException" ]
|
SynExpr.createLongIdent [ "System" ; "NotImplementedException" ]
|
||||||
|> SynExpr.applyTo (SynExpr.CreateConst "Unimplemented mock function")
|
|> SynExpr.applyTo failString
|
||||||
|> SynExpr.paren
|
|> SynExpr.paren
|
||||||
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||||
|> SynExpr.createLambda "_"
|
|> SynExpr.createLambda "_"
|
||||||
@@ -72,7 +77,7 @@ module internal InterfaceMockGenerator =
|
|||||||
|
|
||||||
let nonExtras =
|
let nonExtras =
|
||||||
fields
|
fields
|
||||||
|> List.map (fun field -> (SynLongIdent.createI (getName field), true), Some failwithFun)
|
|> List.map (fun field -> (SynLongIdent.createI (getName field), true), Some (failwithFun field))
|
||||||
|
|
||||||
extras @ nonExtras
|
extras @ nonExtras
|
||||||
|
|
||||||
|
@@ -478,7 +478,7 @@ module internal JsonParseGenerator =
|
|||||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||||
typeDefn
|
typeDefn
|
||||||
|
|
||||||
let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, _access, _)) =
|
let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, access, _)) =
|
||||||
synComponentInfo
|
synComponentInfo
|
||||||
|
|
||||||
let attributes =
|
let attributes =
|
||||||
@@ -517,6 +517,7 @@ module internal JsonParseGenerator =
|
|||||||
let info =
|
let info =
|
||||||
SynComponentInfo.createLong moduleName
|
SynComponentInfo.createLong moduleName
|
||||||
|> SynComponentInfo.withDocString xmlDoc
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
|
|> SynComponentInfo.setAccessibility access
|
||||||
|> SynComponentInfo.addAttributes attributes
|
|> SynComponentInfo.addAttributes attributes
|
||||||
|
|
||||||
let decl =
|
let decl =
|
||||||
|
@@ -323,7 +323,7 @@ module internal JsonSerializeGenerator =
|
|||||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||||
typeDefn
|
typeDefn
|
||||||
|
|
||||||
let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, _access, _)) =
|
let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, access, _)) =
|
||||||
synComponentInfo
|
synComponentInfo
|
||||||
|
|
||||||
let attributes =
|
let attributes =
|
||||||
@@ -362,6 +362,7 @@ module internal JsonSerializeGenerator =
|
|||||||
let info =
|
let info =
|
||||||
SynComponentInfo.createLong moduleName
|
SynComponentInfo.createLong moduleName
|
||||||
|> SynComponentInfo.addAttributes attributes
|
|> SynComponentInfo.addAttributes attributes
|
||||||
|
|> SynComponentInfo.setAccessibility access
|
||||||
|> SynComponentInfo.withDocString xmlDoc
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
|
|
||||||
let decls =
|
let decls =
|
||||||
|
@@ -4,10 +4,11 @@
|
|||||||
"^refs/heads/main$"
|
"^refs/heads/main$"
|
||||||
],
|
],
|
||||||
"pathFilters": [
|
"pathFilters": [
|
||||||
":/",
|
"./",
|
||||||
":^WoofWare.Myriad.Plugins.Test/",
|
":/WoofWare.Myriad.Plugins.Attributes",
|
||||||
":^WoofWare.Myriad.Plugins.Attributes/Test/",
|
"^:/WoofWare.Myriad.Plugins.Attributes/WoofWare.Myriad.Plugins.Attributes.Test",
|
||||||
":^/.github/",
|
":/global.json",
|
||||||
":^/CHANGELOG.md"
|
":/README.md",
|
||||||
|
":/Directory.Build.props"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
27
nix/deps.nix
27
nix/deps.nix
@@ -3,13 +3,13 @@
|
|||||||
{fetchNuGet}: [
|
{fetchNuGet}: [
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "ApiSurface";
|
pname = "ApiSurface";
|
||||||
version = "4.0.40";
|
version = "4.0.41";
|
||||||
sha256 = "1c9z0b6minlripwrjmv4yd5w8zj4lcpak4x41izh7ygx8kgmbvx0";
|
sha256 = "03kfa5ngmgkik9lc58sp8s9rrh9g40hhgjnrv662ks0d0y2i9i89";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "fantomas";
|
pname = "fantomas";
|
||||||
version = "6.3.7";
|
version = "6.3.9";
|
||||||
sha256 = "1z1a5bw7vwz6g8nvfgkvx66jnm4hmvn62vbyq0as60nw0jlvaidl";
|
sha256 = "1b34iiiff02bbzjv03zyna8xmrgs6y87zdvp5i5k58fcqpjw44sx";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Fantomas.Core";
|
pname = "Fantomas.Core";
|
||||||
@@ -76,11 +76,6 @@
|
|||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "02src68hd3213sd1a2ms1my7i92knfmdxclvv90il9cky2zsq8kw";
|
sha256 = "02src68hd3213sd1a2ms1my7i92knfmdxclvv90il9cky2zsq8kw";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.Build.Tasks.Git";
|
|
||||||
version = "8.0.0";
|
|
||||||
sha256 = "0055f69q3hbagqp8gl3nk0vfn4qyqyxsxyy7pd0g7wm3z28byzmx";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.CodeCoverage";
|
pname = "Microsoft.CodeCoverage";
|
||||||
version = "17.10.0";
|
version = "17.10.0";
|
||||||
@@ -156,16 +151,6 @@
|
|||||||
version = "1.1.3";
|
version = "1.1.3";
|
||||||
sha256 = "05smkcyxir59rgrmp7d6327vvrlacdgldfxhmyr1azclvga1zfsq";
|
sha256 = "05smkcyxir59rgrmp7d6327vvrlacdgldfxhmyr1azclvga1zfsq";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.SourceLink.Common";
|
|
||||||
version = "8.0.0";
|
|
||||||
sha256 = "0xrr8yd34ij7dqnyddkp2awfmf9qn3c89xmw2f3npaa4wnajmx81";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.SourceLink.GitHub";
|
|
||||||
version = "8.0.0";
|
|
||||||
sha256 = "1gdx7n45wwia3yvang3ls92sk3wrymqcx9p349j8wba2lyjf9m44";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.TestPlatform.ObjectModel";
|
pname = "Microsoft.TestPlatform.ObjectModel";
|
||||||
version = "17.10.0";
|
version = "17.10.0";
|
||||||
@@ -188,8 +173,8 @@
|
|||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Nerdbank.GitVersioning";
|
pname = "Nerdbank.GitVersioning";
|
||||||
version = "3.6.133";
|
version = "3.6.139";
|
||||||
sha256 = "1cdw8krvsnx0n34f7fm5hiiy7bs6h3asvncqcikc0g46l50w2j80";
|
sha256 = "0npcryhq3r0c2zi940jk39h13mzc4hyg7z8gm6jdmxi1aqv1vh8c";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NETStandard.Library";
|
pname = "NETStandard.Library";
|
||||||
|
Reference in New Issue
Block a user