mirror of https://github.com/Squidex/squidex.git
75 changed files with 4231 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||
<configuration> |
|||
<packageSources> |
|||
<add key="Qooroo" value="https://www.myget.org/F/qooroo/api/v2" /> |
|||
</packageSources> |
|||
</configuration> |
|||
@ -0,0 +1,29 @@ |
|||
{ |
|||
// Controls if the editor shows reference information for the modes that support it |
|||
"editor.referenceInfos": false, |
|||
|
|||
// When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents. |
|||
"editor.detectIndentation": false, |
|||
|
|||
// Typescript version from local package to be consistent |
|||
"typescript.tsdk": "node_modules/typescript/lib", |
|||
|
|||
// Configure glob patterns for excluding files and folders. |
|||
"files.exclude": { |
|||
"_test-output": true, |
|||
"**/node_modules": true, |
|||
"**/artifacts": true, |
|||
"**/build": true, |
|||
"**/out": true, |
|||
"**/obj": true, |
|||
"**/bin": true, |
|||
"**/*.lock.json": true, |
|||
"**/*.bat": true, |
|||
"**/*.sln": true, |
|||
"**/*.sln.DotSettings": true, |
|||
"**/*.user": true, |
|||
"**/*.xproj": true, |
|||
"**/*.gitattributes": true, |
|||
".vs:": true |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio 14 |
|||
VisualStudioVersion = 14.0.25420.1 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{24A3171D-2905-49C9-8A49-A473799014E8}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4B5539DB-F68E-4DBA-B22A-72B9FE7FE2D8}" |
|||
ProjectSection(SolutionItems) = preProject |
|||
global.json = global.json |
|||
EndProjectSection |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot", "src\PinkParrot\PinkParrot.xproj", "{61F6BBCE-A080-4400-B194-70E2F5D2096E}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_infrastructure", "pinkparrot_infrastructure", "{8CF53B92-5EB1-461D-98F8-70DA9B603FBF}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_core", "pinkparrot_core", "{4C6B06C2-6D77-4E0E-AE32-D7050236433A}" |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Core.Tests", "src\pinkparrot_core\PinkParrot.Core.Tests\PinkParrot.Core.Tests.xproj", "{4A27B9DE-F553-4A82-B866-A29EF8A5A0AF}" |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Core", "src\pinkparrot_core\PinkParrot.Core\PinkParrot.Core.xproj", "{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}" |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Infrastructure.Tests", "src\pinkparrot_infrastructure\PinkParrot.Infrastructure.Tests\PinkParrot.Infrastructure.Tests.xproj", "{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}" |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Infrastructure", "src\pinkparrot_infrastructure\PinkParrot.Infrastructure\PinkParrot.Infrastructure.xproj", "{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_events", "pinkparrot_events", "{6AE39761-FD74-45CD-99CF-73D3D2E5D064}" |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Events", "src\pinkparrot_events\PinkParrot.Events\PinkParrot.Events.xproj", "{25F66C64-058A-4D44-BC0C-F12A054F9A91}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_write", "pinkparrot_write", "{4AED438F-684F-4FAE-B016-21CF2EAEA79F}" |
|||
EndProject |
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Write", "src\pinkparrot_write\PinkParrot.Write\PinkParrot.Write.xproj", "{A85201C6-6AF8-4B63-8365-08F741050438}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{61F6BBCE-A080-4400-B194-70E2F5D2096E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{61F6BBCE-A080-4400-B194-70E2F5D2096E}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{61F6BBCE-A080-4400-B194-70E2F5D2096E}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{61F6BBCE-A080-4400-B194-70E2F5D2096E}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{4A27B9DE-F553-4A82-B866-A29EF8A5A0AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{4A27B9DE-F553-4A82-B866-A29EF8A5A0AF}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{4A27B9DE-F553-4A82-B866-A29EF8A5A0AF}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{4A27B9DE-F553-4A82-B866-A29EF8A5A0AF}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{25F66C64-058A-4D44-BC0C-F12A054F9A91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{25F66C64-058A-4D44-BC0C-F12A054F9A91}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{25F66C64-058A-4D44-BC0C-F12A054F9A91}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{25F66C64-058A-4D44-BC0C-F12A054F9A91}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{A85201C6-6AF8-4B63-8365-08F741050438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{A85201C6-6AF8-4B63-8365-08F741050438}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{A85201C6-6AF8-4B63-8365-08F741050438}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{A85201C6-6AF8-4B63-8365-08F741050438}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{61F6BBCE-A080-4400-B194-70E2F5D2096E} = {24A3171D-2905-49C9-8A49-A473799014E8} |
|||
{4A27B9DE-F553-4A82-B866-A29EF8A5A0AF} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A} |
|||
{47F3C27E-698B-4EDF-A7E8-D7F4232AFBB0} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A} |
|||
{840C02B1-48F8-4C8A-8862-8A3FDEFDE8D5} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} |
|||
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} |
|||
{25F66C64-058A-4D44-BC0C-F12A054F9A91} = {6AE39761-FD74-45CD-99CF-73D3D2E5D064} |
|||
{A85201C6-6AF8-4B63-8365-08F741050438} = {4AED438F-684F-4FAE-B016-21CF2EAEA79F} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,84 @@ |
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002A_002A_002Ejs/@EntryIndexedValue">False</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002A_002A_002Ejs/@EntryIndexRemoved">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexedValue">False</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002A_002Fapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexedValue">False</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002A_002Fapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexRemoved">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecshtml/@EntryIndexedValue">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ed_002Ets/@EntryIndexedValue">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ejs/@EntryIndexedValue">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexRemoved">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ets/@EntryIndexedValue">False</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ets/@EntryIndexRemoved">True</s:Boolean> |
|||
|
|||
|
|||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=A2569FB7_002D99E7_002D48B4_002DB97F_002DE48B6F57E492_002Fd_003Awwwroot_002Fd_003Anode_005Fmodules/@EntryIndexedValue">ExplicitlyExcluded</s:String> |
|||
|
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertMethodToExpressionBody/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertPropertyToExpressionBody/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoProperty/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoPropertyWhenPossible/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
|
|||
|
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=Html_002ETagNotResolved/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MissingHasOwnPropertyInForeach/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">SUGGESTION</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FElsewhere/@EntryIndexedValue">SUGGESTION</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">SUGGESTION</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TsResolvedFromInaccessibleModule/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/TypeScriptInspections/Level/@EntryValue">TypeScript16</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Namespaces/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Namespaces"><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Typescript/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Typescript"><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs></Profile></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue"></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/QUOTE_STYLE/@EntryValue">SingleQuoted</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">==========================================================================
 |
|||
$FILENAME$
 |
|||
PinkParrot Headless CMS
 |
|||
==========================================================================
 |
|||
Copyright (c) PinkParrot Group
 |
|||
All rights reserved.
 |
|||
==========================================================================</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue"><Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
|||
<s:Boolean x:Key="/Default/CodeStyle/TypeScriptCodeStyle/ExplicitPublicModifier/@EntryValue">True</s:Boolean> |
|||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"projects": [ "src" ], |
|||
"sdk": { |
|||
"version": "1.0.0-preview2-003121" |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
|
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>61f6bbce-a080-4400-b194-70e2f5d2096e</ProjectGuid> |
|||
<RootNamespace>PinkParrot</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<DnxInvisibleContent Include="bower.json" /> |
|||
<DnxInvisibleContent Include=".bowerrc" /> |
|||
</ItemGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,28 @@ |
|||
// ==========================================================================
|
|||
// Program.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.IO; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
|
|||
namespace PinkParrot |
|||
{ |
|||
public class Program |
|||
{ |
|||
public static void Main(string[] args) |
|||
{ |
|||
var host = new WebHostBuilder() |
|||
.UseKestrel() |
|||
.UseContentRoot(Directory.GetCurrentDirectory()) |
|||
.UseIISIntegration() |
|||
.UseStartup<Startup>() |
|||
.Build(); |
|||
|
|||
host.Run(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,187 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<title>Welcome to ASP.NET Core</title> |
|||
<style> |
|||
html { |
|||
background: #f1f1f1; |
|||
height: 100%; |
|||
} |
|||
|
|||
body { |
|||
background: #fff; |
|||
color: #505050; |
|||
font: 14px 'Segoe UI', tahoma, arial, helvetica, sans-serif; |
|||
margin: 1%; |
|||
min-height: 95.5%; |
|||
border: 1px solid silver; |
|||
position: relative; |
|||
} |
|||
|
|||
#header { |
|||
padding: 0; |
|||
} |
|||
|
|||
#header h1 { |
|||
font-size: 44px; |
|||
font-weight: normal; |
|||
margin: 0; |
|||
padding: 10px 30px 10px 30px; |
|||
} |
|||
|
|||
#header span { |
|||
margin: 0; |
|||
padding: 0 30px; |
|||
display: block; |
|||
} |
|||
|
|||
#header p { |
|||
font-size: 20px; |
|||
color: #fff; |
|||
background: #007acc; |
|||
padding: 0 30px; |
|||
line-height: 50px; |
|||
margin-top: 25px; |
|||
|
|||
} |
|||
|
|||
#header p a { |
|||
color: #fff; |
|||
text-decoration: underline; |
|||
font-weight: bold; |
|||
padding-right: 35px; |
|||
background: no-repeat right bottom url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAMAAAAcqPc3AAAANlBMVEUAAAAAeswfitI9mthXp91us+KCvuaTx+mjz+2x1u+83PLH4vTR5/ba7Pjj8Pns9fv1+v3////wy3dWAAAAAXRSTlMAQObYZgAAAHxJREFUeNp9kVcSwCAIRMHUYoH7XzaxOxJ9P8oyQ1uIqNPwh3s2aLmIM2YtqrLcQIeQEylhuCeUOlhgve5yoBCfWmlnlgkN4H8ykbpaE7gR03AbUHiwoOxUH9Xp+ubd41p1HF3mBPrfC87BHeTdaB3ceeKL9HGpcvX9zu6+DdMWT9KQPvYAAAAASUVORK5CYII=); |
|||
} |
|||
|
|||
#main { |
|||
padding: 5px 30px; |
|||
clear: both; |
|||
} |
|||
|
|||
.section { |
|||
width: 21.7%; |
|||
float: left; |
|||
margin: 0 0 0 4%; |
|||
} |
|||
|
|||
.section h2 { |
|||
font-size: 13px; |
|||
text-transform: uppercase; |
|||
margin: 0; |
|||
border-bottom: 1px solid silver; |
|||
padding-bottom: 12px; |
|||
margin-bottom: 8px; |
|||
} |
|||
|
|||
.section.first { |
|||
margin-left: 0; |
|||
} |
|||
|
|||
.section.first h2 { |
|||
font-size: 24px; |
|||
text-transform: none; |
|||
margin-bottom: 25px; |
|||
border: none; |
|||
} |
|||
|
|||
.section.first li { |
|||
border-top: 1px solid silver; |
|||
padding: 8px 0; |
|||
} |
|||
|
|||
.section.last { |
|||
margin-right: 0; |
|||
} |
|||
|
|||
ul { |
|||
list-style: none; |
|||
padding: 0; |
|||
margin: 0; |
|||
line-height: 20px; |
|||
} |
|||
|
|||
li { |
|||
padding: 4px 0; |
|||
} |
|||
|
|||
a { |
|||
color: #267cb2; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
a:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
#footer { |
|||
clear: both; |
|||
padding-top: 50px; |
|||
} |
|||
|
|||
#footer p { |
|||
position: absolute; |
|||
bottom: 10px; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div id="header"> |
|||
<h1>Welcome to ASP.NET Core</h1> |
|||
<span> |
|||
We've made some big updates in this release, so it’s <b>important</b> that you spend |
|||
a few minutes to learn what’s new. |
|||
</span> |
|||
<p>You've created a new ASP.NET Core project. <a href="http://go.microsoft.com/fwlink/?LinkId=518016">Learn what's new</a></p> |
|||
</div> |
|||
|
|||
<div id="main"> |
|||
<div class="section first"> |
|||
<h2>This application consists of:</h2> |
|||
<ul> |
|||
<li>Sample pages using ASP.NET Core MVC</li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side libraries</li> |
|||
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section"> |
|||
<h2>How to</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699562">Add an appsetting in config and access it in app.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699318">Add client packages using Bower.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section"> |
|||
<h2>Overview</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section last"> |
|||
<h2>Run & Deploy</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517851">Run your app</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517853">Run tools such as EF migrations and more</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a></li> |
|||
</ul> |
|||
</div> |
|||
|
|||
<div id="footer"> |
|||
<p>We would love to hear your <a href="http://go.microsoft.com/fwlink/?LinkId=518015">feedback</a></p> |
|||
</div> |
|||
</div> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,27 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "http://localhost:65351/", |
|||
"sslPort": 0 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"PinkParrot": { |
|||
"commandName": "Project", |
|||
"launchBrowser": true, |
|||
"launchUrl": "http://localhost:5000", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
// ==========================================================================
|
|||
// Startup.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace PinkParrot |
|||
{ |
|||
public class Startup |
|||
{ |
|||
// This method gets called by the runtime. Use this method to add services to the container.
|
|||
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
|
|||
public void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
} |
|||
|
|||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
|||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) |
|||
{ |
|||
loggerFactory.AddConsole(); |
|||
|
|||
if (env.IsDevelopment()) |
|||
{ |
|||
app.UseDeveloperExceptionPage(); |
|||
} |
|||
|
|||
app.Run(async (context) => |
|||
{ |
|||
await context.Response.WriteAsync("Hello World!"); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
{ |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"version": "1.0.0", |
|||
"type": "platform" |
|||
}, |
|||
"Microsoft.AspNetCore.Diagnostics": "1.0.0", |
|||
|
|||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", |
|||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0", |
|||
"Microsoft.Extensions.Logging.Console": "1.0.0" |
|||
}, |
|||
|
|||
"tools": { |
|||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"imports": [ |
|||
"dotnet5.6", |
|||
"portable-net45+win8" |
|||
] |
|||
} |
|||
}, |
|||
|
|||
"buildOptions": { |
|||
"emitEntryPoint": true, |
|||
"preserveCompilationContext": true |
|||
}, |
|||
|
|||
"runtimeOptions": { |
|||
"configProperties": { |
|||
"System.GC.Server": true |
|||
} |
|||
}, |
|||
|
|||
"publishOptions": { |
|||
"include": [ |
|||
"wwwroot", |
|||
"web.config" |
|||
] |
|||
}, |
|||
|
|||
"scripts": { |
|||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
|
|||
<!-- |
|||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380 |
|||
--> |
|||
|
|||
<system.webServer> |
|||
<handlers> |
|||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/> |
|||
</handlers> |
|||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/> |
|||
</system.webServer> |
|||
</configuration> |
|||
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>4a27b9de-f553-4a82-b866-a29ef8a5a0af</ProjectGuid> |
|||
<RootNamespace>PinkParrot.Core.Tests</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,29 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
"testRunner": "xunit", |
|||
"dependencies": { |
|||
"dotnet-test-xunit": "2.2.0-preview2-build1029", |
|||
"PinkParrot.Core": "1.0.0-*", |
|||
"xunit": "2.2.0-beta2-build3300" |
|||
}, |
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"buildOptions": { |
|||
"copyToOutput": { |
|||
"include": [ |
|||
"xunit.runner.json" |
|||
] |
|||
} |
|||
}, |
|||
"tooling": { |
|||
"defaultNamespace": "PinkParrot.Core.Tests" |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
{ |
|||
"diagnosticMessages": false, |
|||
"methodDisplay": "classAndMethod", |
|||
"parallelizeTestCollections": true |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>47f3c27e-698b-4edf-a7e8-d7f4232afbb0</ProjectGuid> |
|||
<RootNamespace>PinkParrot.Core</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,200 @@ |
|||
// ==========================================================================
|
|||
// ModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Threading.Tasks; |
|||
using PinkParrot.Infrastructure; |
|||
using PinkParrot.Infrastructure.Tasks; |
|||
|
|||
// ReSharper disable ConvertIfStatementToReturnStatement
|
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public abstract class ModelField |
|||
{ |
|||
private readonly Guid id; |
|||
private string name; |
|||
private string hint; |
|||
private string displayName; |
|||
private bool isRequired; |
|||
private bool isDisabled; |
|||
private bool isHidden; |
|||
|
|||
public Guid Id |
|||
{ |
|||
get { return id; } |
|||
} |
|||
|
|||
public string Name |
|||
{ |
|||
get { return name; } |
|||
} |
|||
|
|||
public string Hint |
|||
{ |
|||
get { return hint; } |
|||
} |
|||
|
|||
public string DisplayName |
|||
{ |
|||
get { return displayName; } |
|||
} |
|||
|
|||
public bool IsRequired |
|||
{ |
|||
get { return isRequired; } |
|||
} |
|||
|
|||
public bool IsHidden |
|||
{ |
|||
get { return isHidden; } |
|||
} |
|||
|
|||
public bool IsDisabled |
|||
{ |
|||
get { return isDisabled; } |
|||
} |
|||
|
|||
protected ModelField(Guid id, string name) |
|||
{ |
|||
Guard.NotEmpty(id, nameof(id)); |
|||
Guard.ValidSlug(name, nameof(name)); |
|||
|
|||
this.id = id; |
|||
|
|||
this.name = name; |
|||
} |
|||
|
|||
public ModelField Configure(PropertiesBag settings, ICollection<string> errors) |
|||
{ |
|||
var clone = Clone(); |
|||
|
|||
if (settings.Contains("Name")) |
|||
{ |
|||
clone.name = settings["Name"].ToString(); |
|||
|
|||
if (!clone.name.IsSlug()) |
|||
{ |
|||
errors.Add("Field name must be a slug"); |
|||
} |
|||
} |
|||
|
|||
if (settings.Contains("Hint")) |
|||
{ |
|||
clone.hint = settings["Hint"].ToString()?.Trim() ?? string.Empty; |
|||
} |
|||
|
|||
if (settings.Contains("DisplayName")) |
|||
{ |
|||
clone.displayName = settings["DisplayName"].ToString()?.Trim() ?? string.Empty; |
|||
} |
|||
|
|||
if (settings.Contains("IsRequired")) |
|||
{ |
|||
try |
|||
{ |
|||
clone.isRequired = settings["IsRequired"].ToBoolean(CultureInfo.InvariantCulture); |
|||
} |
|||
catch (InvalidCastException) |
|||
{ |
|||
errors.Add("IsRequired is not a valid boolean"); |
|||
} |
|||
} |
|||
|
|||
clone.ConfigureCore(settings, errors); |
|||
|
|||
return clone; |
|||
} |
|||
|
|||
protected virtual void ConfigureCore(PropertiesBag settings, ICollection<string> errors) |
|||
{ |
|||
} |
|||
|
|||
public Task ValidateAsync(PropertyValue property, ICollection<string> errors) |
|||
{ |
|||
Guard.NotNull(property, nameof(property)); |
|||
|
|||
if (isRequired && property.RawValue == null) |
|||
{ |
|||
errors.Add("<Field> is required"); |
|||
} |
|||
|
|||
if (property.RawValue == null) |
|||
{ |
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
return ValidateCoreAsync(property, errors); |
|||
} |
|||
|
|||
protected virtual Task ValidateCoreAsync(PropertyValue property, ICollection<string> errors) |
|||
{ |
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public ModelField Hide() |
|||
{ |
|||
if (isHidden) |
|||
{ |
|||
throw new DomainValidationException($"The field '{name} is already hidden."); |
|||
} |
|||
|
|||
var clone = Clone(); |
|||
|
|||
clone.isHidden = true; |
|||
|
|||
return Clone(); |
|||
} |
|||
|
|||
public ModelField Show() |
|||
{ |
|||
if (!isHidden) |
|||
{ |
|||
throw new DomainValidationException($"The field '{name} is already visible."); |
|||
} |
|||
|
|||
var clone = Clone(); |
|||
|
|||
clone.isHidden = false; |
|||
|
|||
return Clone(); |
|||
} |
|||
|
|||
public ModelField Disable() |
|||
{ |
|||
if (isDisabled) |
|||
{ |
|||
throw new DomainValidationException($"The field '{name} is already disabled."); |
|||
} |
|||
|
|||
var clone = Clone(); |
|||
|
|||
clone.isDisabled = true; |
|||
|
|||
return clone; |
|||
} |
|||
|
|||
public ModelField Enable() |
|||
{ |
|||
if (!isDisabled) |
|||
{ |
|||
throw new DomainValidationException($"The field '{name} is already enabled."); |
|||
} |
|||
|
|||
var clone = Clone(); |
|||
|
|||
clone.isDisabled = false; |
|||
|
|||
return clone; |
|||
} |
|||
|
|||
protected abstract ModelField Clone(); |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public class ModelFieldFactory |
|||
{ |
|||
public virtual ModelField CreateField(Guid id, string type, string fieldName) |
|||
{ |
|||
return new NumberField(id, fieldName); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,177 @@ |
|||
// ==========================================================================
|
|||
// ModelSchema.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public sealed class ModelSchema |
|||
{ |
|||
private readonly ModelSchemaMetadata metadata; |
|||
private readonly ImmutableDictionary<Guid, ModelField> fields; |
|||
private readonly Dictionary<string, ModelField> fieldsByName; |
|||
|
|||
public ModelSchema(ModelSchemaMetadata metadata, ImmutableDictionary<Guid, ModelField> fields) |
|||
{ |
|||
Guard.NotNull(fields, nameof(fields)); |
|||
Guard.NotNull(metadata, nameof(metadata)); |
|||
|
|||
this.fields = fields; |
|||
|
|||
this.metadata = metadata; |
|||
|
|||
fieldsByName = fields.Values.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); |
|||
} |
|||
|
|||
public static ModelSchema Create(string name) |
|||
{ |
|||
if (!name.IsSlug()) |
|||
{ |
|||
throw new DomainValidationException("Cannot create the schema.", $"'{name}' is not a valid slug."); |
|||
} |
|||
|
|||
return new ModelSchema(new ModelSchemaMetadata(name), ImmutableDictionary<Guid, ModelField>.Empty); |
|||
} |
|||
|
|||
public IReadOnlyDictionary<Guid, ModelField> Fields |
|||
{ |
|||
get { return fields; } |
|||
} |
|||
|
|||
public ModelSchemaMetadata Metadata |
|||
{ |
|||
get { return metadata; } |
|||
} |
|||
|
|||
public ModelSchema Update(ModelSchemaMetadata newMetadata) |
|||
{ |
|||
Guard.NotNull(newMetadata, nameof(newMetadata)); |
|||
|
|||
return new ModelSchema(newMetadata, fields); |
|||
} |
|||
|
|||
public ModelSchema AddField(Guid id, string type, string fieldName, ModelFieldFactory factory) |
|||
{ |
|||
var field = factory.CreateField(id, type, fieldName); |
|||
|
|||
return SetField(field); |
|||
} |
|||
|
|||
public ModelSchema SetField(Guid fieldId, PropertiesBag settings) |
|||
{ |
|||
Guard.NotNull(settings, nameof(settings)); |
|||
|
|||
return UpdateField(fieldId, field => |
|||
{ |
|||
var errors = new List<string>(); |
|||
|
|||
var newField = field.Configure(settings, errors); |
|||
|
|||
if (errors.Any()) |
|||
{ |
|||
throw new DomainValidationException($"Cannot update field with id '{fieldId}', becase the settings are invalid.", errors); |
|||
} |
|||
|
|||
return newField; |
|||
}); |
|||
} |
|||
|
|||
public ModelSchema DisableField(Guid fieldId) |
|||
{ |
|||
return UpdateField(fieldId, field => field.Disable()); |
|||
} |
|||
|
|||
public ModelSchema EnableField(Guid fieldId) |
|||
{ |
|||
return UpdateField(fieldId, field => field.Enable()); |
|||
} |
|||
|
|||
public ModelSchema HideField(Guid fieldId) |
|||
{ |
|||
return UpdateField(fieldId, field => field.Show()); |
|||
} |
|||
|
|||
public ModelSchema ShowField(Guid fieldId) |
|||
{ |
|||
return UpdateField(fieldId, field => field.Show()); |
|||
} |
|||
|
|||
public ModelSchema SetField(ModelField field) |
|||
{ |
|||
Guard.NotNull(field, nameof(field)); |
|||
|
|||
if (fields.Values.Any(f => f.Name == field.Name && f.Id != field.Id)) |
|||
{ |
|||
throw new DomainValidationException($"A field with name '{field.Name}' already exists."); |
|||
} |
|||
|
|||
return new ModelSchema(metadata, fields.SetItem(field.Id, field)); |
|||
} |
|||
|
|||
public ModelSchema DeleteField(Guid fieldId) |
|||
{ |
|||
Guard.NotEmpty(fieldId, nameof(fieldId)); |
|||
|
|||
if (!fields.ContainsKey(fieldId)) |
|||
{ |
|||
throw new DomainValidationException($"A field with id {fieldId} does not exist."); |
|||
} |
|||
|
|||
return new ModelSchema(metadata, fields.Remove(fieldId)); |
|||
} |
|||
|
|||
private ModelSchema UpdateField(Guid fieldId, Func<ModelField, ModelField> updater) |
|||
{ |
|||
ModelField field; |
|||
|
|||
if (!fields.TryGetValue(fieldId, out field)) |
|||
{ |
|||
throw new DomainValidationException($"Cannot update field with id '{fieldId}'.", "Field does not exist."); |
|||
} |
|||
|
|||
var newField = updater(field); |
|||
|
|||
return SetField(newField); |
|||
} |
|||
|
|||
public async Task ValidateAsync(PropertiesBag data) |
|||
{ |
|||
Guard.NotNull(data, nameof(data)); |
|||
|
|||
var errors = new List<string>(); |
|||
|
|||
foreach (var kvp in data.Properties) |
|||
{ |
|||
ModelField field; |
|||
|
|||
if (fieldsByName.TryGetValue(kvp.Key, out field)) |
|||
{ |
|||
var newErrors = new List<string>(); |
|||
|
|||
await field.ValidateAsync(kvp.Value, newErrors); |
|||
|
|||
errors.AddRange(newErrors.Select(e => e.Replace("<Field>", "'" + field.Name + "'"))); |
|||
} |
|||
else |
|||
{ |
|||
errors.Add($"'{kvp.Key}' is not a known field"); |
|||
} |
|||
} |
|||
|
|||
if (errors.Any()) |
|||
{ |
|||
throw new DomainValidationException("The data is not valid.", errors); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaMetadata.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public sealed class ModelSchemaMetadata |
|||
{ |
|||
private string name; |
|||
private string displayName; |
|||
private string hint; |
|||
private string itemTitle; |
|||
|
|||
public string Name |
|||
{ |
|||
get { return name; } |
|||
} |
|||
|
|||
public string DisplayName |
|||
{ |
|||
get { return displayName; } |
|||
} |
|||
|
|||
public string Hint |
|||
{ |
|||
get { return hint; } |
|||
} |
|||
|
|||
public string ItemTitle |
|||
{ |
|||
get { return itemTitle; } |
|||
} |
|||
|
|||
public ModelSchemaMetadata(string name) |
|||
{ |
|||
Guard.ValidSlug(name, nameof(name)); |
|||
|
|||
this.name = name; |
|||
} |
|||
|
|||
public ModelSchemaMetadata Configure(string newName, PropertiesBag properties) |
|||
{ |
|||
Guard.NotNull(properties, nameof(properties)); |
|||
|
|||
var clone = (ModelSchemaMetadata) MemberwiseClone(); |
|||
|
|||
if (newName != null) |
|||
{ |
|||
if (!newName.IsSlug()) |
|||
{ |
|||
throw new DomainValidationException("Cannot update the schema.", $"'{newName}' is not a valid slug."); |
|||
} |
|||
|
|||
clone.name = newName; |
|||
} |
|||
|
|||
if (properties.Contains("Hint")) |
|||
{ |
|||
clone.hint = properties["Hint"].ToString()?.Trim(); |
|||
} |
|||
|
|||
if (properties.Contains("DisplayName")) |
|||
{ |
|||
clone.displayName = properties["DisplayName"].ToString()?.Trim(); |
|||
} |
|||
|
|||
if (properties.Contains("ItemTitle")) |
|||
{ |
|||
clone.itemTitle = properties["ItemTitle"].ToString()?.Trim(); |
|||
} |
|||
|
|||
return clone; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
// ==========================================================================
|
|||
// NumberField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Threading.Tasks; |
|||
using PinkParrot.Infrastructure; |
|||
using PinkParrot.Infrastructure.Tasks; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public sealed class NumberField : ModelField |
|||
{ |
|||
private double? maxValue; |
|||
private double? minValue; |
|||
|
|||
public double? MaxValue |
|||
{ |
|||
get { return maxValue; } |
|||
} |
|||
|
|||
public double? MinValue |
|||
{ |
|||
get { return minValue; } |
|||
} |
|||
|
|||
public NumberField(Guid id, string name) |
|||
: base(id, name) |
|||
{ |
|||
} |
|||
|
|||
protected override void ConfigureCore(PropertiesBag settings, ICollection<string> errors) |
|||
{ |
|||
maxValue = ParseNumber("MaxValue", settings, errors); |
|||
minValue = ParseNumber("MinValue", settings, errors); |
|||
|
|||
if (maxValue.HasValue && minValue.HasValue && minValue.Value > maxValue.Value) |
|||
{ |
|||
errors.Add("MinValue cannot be larger than max value"); |
|||
} |
|||
} |
|||
|
|||
private static double? ParseNumber(string key, PropertiesBag settings, ICollection<string> errors) |
|||
{ |
|||
try |
|||
{ |
|||
if (settings.Contains(key)) |
|||
{ |
|||
return settings[key].ToNullableDouble(CultureInfo.InvariantCulture); |
|||
} |
|||
} |
|||
catch (InvalidCastException) |
|||
{ |
|||
errors.Add($"'{key}' is not a valid number"); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
protected override Task ValidateCoreAsync(PropertyValue property, ICollection<string> errors) |
|||
{ |
|||
try |
|||
{ |
|||
var value = property.ToDouble(CultureInfo.InvariantCulture); |
|||
|
|||
if (MinValue.HasValue && value < MinValue.Value) |
|||
{ |
|||
errors.Add($"<Field> must be greater than {MinValue}"); |
|||
} |
|||
|
|||
if (MaxValue.HasValue && value > MaxValue.Value) |
|||
{ |
|||
errors.Add($"<Field> must be less than {MaxValue}"); |
|||
} |
|||
} |
|||
catch (InvalidCastException) |
|||
{ |
|||
errors.Add("<Field> is not a valid number"); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
protected override ModelField Clone() |
|||
{ |
|||
return (ModelField)MemberwiseClone(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
|
|||
"dependencies": { |
|||
"EventStore.ClientAPI.DotNetCore": "1.0.0", |
|||
"NETStandard.Library": "1.6.0", |
|||
"NodaTime": "2.0.0-alpha20160729", |
|||
"PinkParrot.Infrastructure": "1.0.0-*", |
|||
"protobuf-net": "2.1.0" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
|
|||
"tooling": { |
|||
"defaultNamespace": "PinkParrot.Core" |
|||
} |
|||
} |
|||
@ -0,0 +1,234 @@ |
|||
## Ignore Visual Studio temporary files, build results, and |
|||
## files generated by popular Visual Studio add-ons. |
|||
|
|||
# User-specific files |
|||
*.suo |
|||
*.user |
|||
*.userosscache |
|||
*.sln.docstates |
|||
|
|||
# User-specific files (MonoDevelop/Xamarin Studio) |
|||
*.userprefs |
|||
|
|||
# Build results |
|||
[Dd]ebug/ |
|||
[Dd]ebugPublic/ |
|||
[Rr]elease/ |
|||
[Rr]eleases/ |
|||
x64/ |
|||
x86/ |
|||
build/ |
|||
bld/ |
|||
[Bb]in/ |
|||
[Oo]bj/ |
|||
|
|||
# Visual Studio 2015 cache/options directory |
|||
.vs/ |
|||
# Uncomment if you have tasks that create the project's static files in wwwroot |
|||
#wwwroot/ |
|||
|
|||
# MSTest test Results |
|||
[Tt]est[Rr]esult*/ |
|||
[Bb]uild[Ll]og.* |
|||
|
|||
# NUNIT |
|||
*.VisualState.xml |
|||
TestResult.xml |
|||
|
|||
# Build Results of an ATL Project |
|||
[Dd]ebugPS/ |
|||
[Rr]eleasePS/ |
|||
dlldata.c |
|||
|
|||
# DNX |
|||
project.lock.json |
|||
artifacts/ |
|||
|
|||
*_i.c |
|||
*_p.c |
|||
*_i.h |
|||
*.ilk |
|||
*.meta |
|||
*.obj |
|||
*.pch |
|||
*.pdb |
|||
*.pgc |
|||
*.pgd |
|||
*.rsp |
|||
*.sbr |
|||
*.tlb |
|||
*.tli |
|||
*.tlh |
|||
*.tmp |
|||
*.tmp_proj |
|||
*.log |
|||
*.vspscc |
|||
*.vssscc |
|||
.builds |
|||
*.pidb |
|||
*.svclog |
|||
*.scc |
|||
|
|||
# Chutzpah Test files |
|||
_Chutzpah* |
|||
|
|||
# Visual C++ cache files |
|||
ipch/ |
|||
*.aps |
|||
*.ncb |
|||
*.opendb |
|||
*.opensdf |
|||
*.sdf |
|||
*.cachefile |
|||
|
|||
# Visual Studio profiler |
|||
*.psess |
|||
*.vsp |
|||
*.vspx |
|||
*.sap |
|||
|
|||
# TFS 2012 Local Workspace |
|||
$tf/ |
|||
|
|||
# Guidance Automation Toolkit |
|||
*.gpState |
|||
|
|||
# ReSharper is a .NET coding add-in |
|||
_ReSharper*/ |
|||
*.[Rr]e[Ss]harper |
|||
*.DotSettings.user |
|||
|
|||
# JustCode is a .NET coding add-in |
|||
.JustCode |
|||
|
|||
# TeamCity is a build add-in |
|||
_TeamCity* |
|||
|
|||
# DotCover is a Code Coverage Tool |
|||
*.dotCover |
|||
|
|||
# NCrunch |
|||
_NCrunch_* |
|||
.*crunch*.local.xml |
|||
nCrunchTemp_* |
|||
|
|||
# MightyMoose |
|||
*.mm.* |
|||
AutoTest.Net/ |
|||
|
|||
# Web workbench (sass) |
|||
.sass-cache/ |
|||
|
|||
# Installshield output folder |
|||
[Ee]xpress/ |
|||
|
|||
# DocProject is a documentation generator add-in |
|||
DocProject/buildhelp/ |
|||
DocProject/Help/*.HxT |
|||
DocProject/Help/*.HxC |
|||
DocProject/Help/*.hhc |
|||
DocProject/Help/*.hhk |
|||
DocProject/Help/*.hhp |
|||
DocProject/Help/Html2 |
|||
DocProject/Help/html |
|||
|
|||
# Click-Once directory |
|||
publish/ |
|||
|
|||
# Publish Web Output |
|||
*.[Pp]ublish.xml |
|||
*.azurePubxml |
|||
# TODO: Comment the next line if you want to checkin your web deploy settings |
|||
# but database connection strings (with potential passwords) will be unencrypted |
|||
*.pubxml |
|||
*.publishproj |
|||
|
|||
# NuGet Packages |
|||
*.nupkg |
|||
# The packages folder can be ignored because of Package Restore |
|||
**/packages/* |
|||
# except build/, which is used as an MSBuild target. |
|||
!**/packages/build/ |
|||
# Uncomment if necessary however generally it will be regenerated when needed |
|||
#!**/packages/repositories.config |
|||
|
|||
# Microsoft Azure Build Output |
|||
csx/ |
|||
*.build.csdef |
|||
|
|||
# Microsoft Azure Emulator |
|||
ecf/ |
|||
rcf/ |
|||
|
|||
# Microsoft Azure ApplicationInsights config file |
|||
ApplicationInsights.config |
|||
|
|||
# Windows Store app package directory |
|||
AppPackages/ |
|||
BundleArtifacts/ |
|||
|
|||
# Visual Studio cache files |
|||
# files ending in .cache can be ignored |
|||
*.[Cc]ache |
|||
# but keep track of directories ending in .cache |
|||
!*.[Cc]ache/ |
|||
|
|||
# Others |
|||
ClientBin/ |
|||
~$* |
|||
*~ |
|||
*.dbmdl |
|||
*.dbproj.schemaview |
|||
*.pfx |
|||
*.publishsettings |
|||
node_modules/ |
|||
orleans.codegen.cs |
|||
|
|||
# RIA/Silverlight projects |
|||
Generated_Code/ |
|||
|
|||
# Backup & report files from converting an old project file |
|||
# to a newer Visual Studio version. Backup files are not needed, |
|||
# because we have git ;-) |
|||
_UpgradeReport_Files/ |
|||
Backup*/ |
|||
UpgradeLog*.XML |
|||
UpgradeLog*.htm |
|||
|
|||
# SQL Server files |
|||
*.mdf |
|||
*.ldf |
|||
|
|||
# Business Intelligence projects |
|||
*.rdl.data |
|||
*.bim.layout |
|||
*.bim_*.settings |
|||
|
|||
# Microsoft Fakes |
|||
FakesAssemblies/ |
|||
|
|||
# GhostDoc plugin setting file |
|||
*.GhostDoc.xml |
|||
|
|||
# Node.js Tools for Visual Studio |
|||
.ntvs_analysis.dat |
|||
|
|||
# Visual Studio 6 build log |
|||
*.plg |
|||
|
|||
# Visual Studio 6 workspace options file |
|||
*.opt |
|||
|
|||
# Visual Studio LightSwitch build output |
|||
**/*.HTMLClient/GeneratedArtifacts |
|||
**/*.DesktopClient/GeneratedArtifacts |
|||
**/*.DesktopClient/ModelManifest.xml |
|||
**/*.Server/GeneratedArtifacts |
|||
**/*.Server/ModelManifest.xml |
|||
_Pvt_Extensions |
|||
|
|||
# Paket dependency manager |
|||
.paket/paket.exe |
|||
|
|||
# FAKE - F# Make |
|||
.fake/ |
|||
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>25f66c64-058a-4d44-bc0c-f12a054f9a91</ProjectGuid> |
|||
<RootNamespace>PinkParrot.Events</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldAdded.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldAdded : IEvent |
|||
{ |
|||
public Guid FieldId { get; set; } |
|||
|
|||
public string FieldType; |
|||
|
|||
public string FieldName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldDeleted.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldDeleted : IEvent |
|||
{ |
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldDisabled.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldDisabled : IEvent |
|||
{ |
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldEnabled.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldEnabled : IEvent |
|||
{ |
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldHidden.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldHidden : IEvent |
|||
{ |
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldShown.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldShown : IEvent |
|||
{ |
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldUpdated.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelFieldUpdated : IEvent |
|||
{ |
|||
public Guid FieldId { get; set; } |
|||
|
|||
public PropertiesBag Settings { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaCreated.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelSchemaCreated : IEvent |
|||
{ |
|||
public string Name; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaDeleted.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelSchemaDeleted : IEvent |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaUpdated.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using PinkParrot.Infrastructure; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
|
|||
namespace PinkParrot.Events.Schema |
|||
{ |
|||
public class ModelSchemaUpdated : IEvent |
|||
{ |
|||
public string NewName; |
|||
|
|||
public PropertiesBag Settings { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
|
|||
"dependencies": { |
|||
"NETStandard.Library": "1.6.0", |
|||
"NodaTime": "2.0.0-alpha20160729", |
|||
"PinkParrot.Infrastructure": "1.0.0-*" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
|
|||
"tooling": { |
|||
"defaultNamespace": "PinkParrot.Events" |
|||
} |
|||
} |
|||
@ -0,0 +1,169 @@ |
|||
// ==========================================================================
|
|||
// CollectionExtensionsTest.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public class CollectionExtensionTest |
|||
{ |
|||
private readonly Dictionary<int, int> valueDictionary = new Dictionary<int, int>(); |
|||
private readonly Dictionary<int, List<int>> listDictionary = new Dictionary<int, List<int>>(); |
|||
|
|||
[Fact] |
|||
public void GetOrDefault_should_return_value_if_key_exists() |
|||
{ |
|||
valueDictionary[12] = 34; |
|||
|
|||
Assert.Equal(34, valueDictionary.GetOrDefault(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrDefault_should_return_default_and_not_add_it_if_key_not_exists() |
|||
{ |
|||
Assert.Equal(0, valueDictionary.GetOrDefault(12)); |
|||
Assert.False(valueDictionary.ContainsKey(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrAddDefault_should_return_value_if_key_exists() |
|||
{ |
|||
valueDictionary[12] = 34; |
|||
|
|||
Assert.Equal(34, valueDictionary.GetOrAddDefault(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrAddDefault_should_return_default_and_add_it_if_key_not_exists() |
|||
{ |
|||
Assert.Equal(0, valueDictionary.GetOrAddDefault(12)); |
|||
Assert.Equal(0, valueDictionary[12]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrCreate_should_return_value_if_key_exists() |
|||
{ |
|||
valueDictionary[12] = 34; |
|||
|
|||
Assert.Equal(34, valueDictionary.GetOrCreate(12, x => 34)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrCreate_should_return_default_but_not_add_it_if_key_not_exists() |
|||
{ |
|||
Assert.Equal(24, valueDictionary.GetOrCreate(12, x => 24)); |
|||
Assert.False(valueDictionary.ContainsKey(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrAdd_should_return_value_if_key_exists() |
|||
{ |
|||
valueDictionary[12] = 34; |
|||
|
|||
Assert.Equal(34, valueDictionary.GetOrAdd(12, x => 34)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrAdd_should_return_default_and_add_it_if_key_not_exists() |
|||
{ |
|||
Assert.Equal(24, valueDictionary.GetOrAdd(12, x => 24)); |
|||
Assert.Equal(24, valueDictionary[12]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrNew_should_return_value_if_key_exists() |
|||
{ |
|||
var list = new List<int>(); |
|||
listDictionary[12] = list; |
|||
|
|||
Assert.Equal(list, listDictionary.GetOrNew(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrNew_should_return_default_but_not_add_it_if_key_not_exists() |
|||
{ |
|||
var list = new List<int>(); |
|||
|
|||
Assert.Equal(list, listDictionary.GetOrNew(12)); |
|||
Assert.False(listDictionary.ContainsKey(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrAddNew_should_return_value_if_key_exists() |
|||
{ |
|||
var list = new List<int>(); |
|||
listDictionary[12] = list; |
|||
|
|||
Assert.Equal(list, listDictionary.GetOrAddNew(12)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetOrAddNew_should_return_default_but_not_add_it_if_key_not_exists() |
|||
{ |
|||
var list = new List<int>(); |
|||
|
|||
Assert.Equal(list, listDictionary.GetOrAddNew(12)); |
|||
Assert.Equal(list, listDictionary[12]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SequentialHashCode_should_return_same_hash_codes_for_list_with_same_order() |
|||
{ |
|||
var collection1 = new[] { 3, 5, 6 }; |
|||
var collection2 = new[] { 3, 5, 6 }; |
|||
|
|||
Assert.Equal(collection2.SequentialHashCode(), collection1.SequentialHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SequentialHashCode_should_return_different_hash_codes_for_list_with_different_items() |
|||
{ |
|||
var collection1 = new[] { 3, 5, 6 }; |
|||
var collection2 = new[] { 3, 4, 1 }; |
|||
|
|||
Assert.NotEqual(collection2.SequentialHashCode(), collection1.SequentialHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SequentialHashCode_should_return_different_hash_codes_for_list_with_different_order() |
|||
{ |
|||
var collection1 = new[] { 3, 5, 6 }; |
|||
var collection2 = new[] { 6, 5, 3 }; |
|||
|
|||
Assert.NotEqual(collection2.SequentialHashCode(), collection1.SequentialHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OrderedHashCode_should_return_same_hash_codes_for_list_with_same_order() |
|||
{ |
|||
var collection1 = new[] { 3, 5, 6 }; |
|||
var collection2 = new[] { 3, 5, 6 }; |
|||
|
|||
Assert.Equal(collection2.OrderedHashCode(), collection1.OrderedHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OrderedHashCode_should_return_different_hash_codes_for_list_with_different_items() |
|||
{ |
|||
var collection1 = new[] { 3, 5, 6 }; |
|||
var collection2 = new[] { 3, 4, 1 }; |
|||
|
|||
Assert.NotEqual(collection2.OrderedHashCode(), collection1.OrderedHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OrderedHashCode_should_return_same_hash_codes_for_list_with_different_order() |
|||
{ |
|||
var collection1 = new[] { 3, 5, 6 }; |
|||
var collection2 = new[] { 6, 5, 3 }; |
|||
|
|||
Assert.Equal(collection2.OrderedHashCode(), collection1.OrderedHashCode()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
// ==========================================================================
|
|||
// EnumExtensionsTest.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public sealed class EnumExtensionsTest |
|||
{ |
|||
[Fact] |
|||
public void Should_return_true_if_enum_is_valid() |
|||
{ |
|||
Assert.True(DateTimeKind.Local.IsEnumValue()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_false_if_enum_is_not_valid() |
|||
{ |
|||
Assert.False(((DateTimeKind)13).IsEnumValue()); |
|||
Assert.False(123.IsEnumValue()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,128 @@ |
|||
// ==========================================================================
|
|||
// GuardTests.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public class GuardTest |
|||
{ |
|||
[Theory] |
|||
[InlineData("")] |
|||
[InlineData(" ")] |
|||
public void Should_throw_when_target_is_null_for_empty_string(string invalidString) |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => Guard.NotNullOrEmpty(invalidString, "parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_if_target_string_is_valid() |
|||
{ |
|||
Guard.NotNullOrEmpty("value", "parameter"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_if_target_is_not_null() |
|||
{ |
|||
Guard.NotNull("value", "parameter"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_if_enum_is_valid() |
|||
{ |
|||
Guard.Enum(DateTimeKind.Local, "Parameter"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_if_enum_is_not_valid() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => Guard.Enum((DateTimeKind)13, "Parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_when_guid_is_not_empty() |
|||
{ |
|||
Guard.NotEmpty(Guid.NewGuid(), "parameter"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_guid_is_empty() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => Guard.NotEmpty(Guid.Empty, "parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_target_is_null() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => Guard.NotNull(null, "parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_target_is_null_for_null_string() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => Guard.NotNullOrEmpty(null, "parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_when_target_has_correct_type() |
|||
{ |
|||
Guard.HasType<int>(123, "parameter"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_target_has_wrong_type() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => Guard.HasType<int>("value", "parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_checking_for_null_and_target_is_null() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => Guard.HasType<int>(null, "parameter")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_when_target_is_not_default_value() |
|||
{ |
|||
Guard.NotDefault(Guid.NewGuid(), "parameter"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_when_value_has_default() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => Guard.NotDefault(Guid.Empty, "parameter")); |
|||
Assert.Throws<ArgumentException>(() => Guard.NotDefault(0, "parameter")); |
|||
Assert.Throws<ArgumentException>(() => Guard.NotDefault((string)null, "parameter")); |
|||
Assert.Throws<ArgumentException>(() => Guard.NotDefault(false, "parameter")); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("")] |
|||
[InlineData(" ")] |
|||
[InlineData(" Not a Slug ")] |
|||
[InlineData(" not--a--slug ")] |
|||
[InlineData(" not-a-slug ")] |
|||
[InlineData("-not-a-slug-")] |
|||
[InlineData("not$-a-slug")] |
|||
public void Should_throw_exception_for_invalid_slug(string slug) |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => Guard.ValidSlug(slug, "slug")); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("slug")] |
|||
[InlineData("slug23")] |
|||
[InlineData("other-slug")] |
|||
[InlineData("just-another-slug")] |
|||
public void Should_do_nothing_for_valid_slug(string slug) |
|||
{ |
|||
Guard.ValidSlug(slug, "parameter"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>840c02b1-48f8-4c8a-8862-8a3fdefde8d5</ProjectGuid> |
|||
<RootNamespace>PinkParrot.Infrastructure</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,281 @@ |
|||
// ==========================================================================
|
|||
// PropertiesBagTests.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using NodaTime; |
|||
using Xunit; |
|||
|
|||
// ReSharper disable PossibleInvalidOperationException
|
|||
// ReSharper disable UnusedParameter.Local
|
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public class PropertiesBagTest |
|||
{ |
|||
private readonly CultureInfo c = CultureInfo.InvariantCulture; |
|||
private readonly PropertiesBag bag = new PropertiesBag(); |
|||
|
|||
[Fact] |
|||
public void Should_return_false_when_renaming_unknown_property() |
|||
{ |
|||
Assert.False(bag.Rename("OldKey", "NewKey")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_renaming_to_existing_property() |
|||
{ |
|||
bag.Set("NewKey", 1); |
|||
|
|||
Assert.Throws<ArgumentException>(() => bag.Rename("OldKey", "NewKey")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_renaming_to_same_key() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => bag.Rename("SameKey", "SameKey")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_provide_property_with_new_name_after_rename() |
|||
{ |
|||
bag.Set("OldKey", 123); |
|||
|
|||
Assert.True(bag.Rename("OldKey", "NewKey")); |
|||
Assert.True(bag.Contains("NewKey")); |
|||
|
|||
Assert.Equal(1, bag.Count); |
|||
Assert.Equal(123, bag["NewKey"].ToInt32(c)); |
|||
|
|||
Assert.False(bag.Contains("OldKey")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_calculate_count_correctly() |
|||
{ |
|||
bag.Set("Key1", 1); |
|||
bag.Set("Key2", 1); |
|||
|
|||
Assert.Equal(2, bag.Count); |
|||
Assert.Equal(new[] { "Key1", "Key2" }, bag.PropertyNames.ToArray()); |
|||
Assert.Equal(new[] { "Key1", "Key2" }, bag.Properties.Keys.ToArray()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_correct_value_when_contains_check() |
|||
{ |
|||
Assert.False(bag.Contains("Key")); |
|||
|
|||
bag.Set("Key", 1); |
|||
|
|||
Assert.True(bag.Contains("Key")); |
|||
Assert.True(bag.Contains("KEY")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_returne_false_when_property_to_rename_does_not_exist() |
|||
{ |
|||
Assert.False(bag.Remove("NOTFOUND")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_ignore_casing_when_returning() |
|||
{ |
|||
bag.Set("Key", 1); |
|||
|
|||
Assert.True(bag.Remove("KEY")); |
|||
Assert.False(bag.Contains("KEY")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_setting_value_with_invalid_type() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => bag.Set("Key", (byte)1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_string_to_numbers() |
|||
{ |
|||
bag.Set("Key", 123); |
|||
|
|||
AssertNumber(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_int_to_numbers() |
|||
{ |
|||
bag.Set("Key", 123); |
|||
|
|||
AssertNumber(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_long_to_numbers() |
|||
{ |
|||
bag.Set("Key", 123L); |
|||
|
|||
AssertNumber(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_casting_from_large_long() |
|||
{ |
|||
bag.Set("Key", long.MaxValue); |
|||
|
|||
Assert.Throws<InvalidCastException>(() => bag["Key"].ToInt32(c)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_float_to_number() |
|||
{ |
|||
bag.Set("Key", 123f); |
|||
|
|||
AssertNumber(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_double_to_number() |
|||
{ |
|||
bag.Set("Key", 123d); |
|||
|
|||
AssertNumber(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_casting_from_large_doule() |
|||
{ |
|||
bag.Set("Key", double.MaxValue); |
|||
|
|||
Assert.Equal(float.PositiveInfinity, bag["Key"].ToSingle(c)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_from_instant_value() |
|||
{ |
|||
var time = SystemClock.Instance.GetCurrentInstant(); |
|||
|
|||
bag.Set("Key", time); |
|||
|
|||
AssertInstant(time); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_from_instant_string() |
|||
{ |
|||
var time = SystemClock.Instance.GetCurrentInstant(); |
|||
|
|||
bag.Set("Key", time.ToString()); |
|||
|
|||
AssertInstant(time); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_from_guid_value() |
|||
{ |
|||
var id = new Guid(); |
|||
|
|||
bag.Set("Key", id); |
|||
|
|||
AssertGuid(id); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_from_guid_string() |
|||
{ |
|||
var id = new Guid(); |
|||
|
|||
bag.Set("Key", id.ToString()); |
|||
|
|||
AssertGuid(id); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_from_boolean_value() |
|||
{ |
|||
bag.Set("Key", true); |
|||
|
|||
AssertBoolean(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_from_boolean_string() |
|||
{ |
|||
bag.Set("Key", "true"); |
|||
|
|||
AssertBoolean(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_boolean_from_number() |
|||
{ |
|||
bag.Set("Key", 1); |
|||
|
|||
AssertBoolean(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_when_converting_instant_to_number() |
|||
{ |
|||
bag.Set("Key", SystemClock.Instance.GetCurrentInstant()); |
|||
|
|||
Assert.Throws<InvalidCastException>(() => bag["Key"].ToGuid(CultureInfo.InvariantCulture)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_default_when_property_value_is_null() |
|||
{ |
|||
bag.Set("Key", null); |
|||
|
|||
Assert.Equal(null, bag["Key"].ToString()); |
|||
|
|||
Assert.Equal(0f, bag["Key"].ToSingle(CultureInfo.CurrentCulture)); |
|||
Assert.Equal(0d, bag["Key"].ToDouble(CultureInfo.CurrentCulture)); |
|||
Assert.Equal(0L, bag["Key"].ToInt64(CultureInfo.CurrentCulture)); |
|||
Assert.Equal(0, bag["Key"].ToInt32(CultureInfo.CurrentCulture)); |
|||
|
|||
Assert.Equal(false, bag["Key"].ToBoolean(CultureInfo.CurrentCulture)); |
|||
|
|||
Assert.Equal(new Guid(), bag["Key"].ToGuid(CultureInfo.CurrentCulture)); |
|||
|
|||
Assert.Equal(new Instant(), bag["Key"].ToInstant(CultureInfo.CurrentCulture)); |
|||
} |
|||
|
|||
private void AssertBoolean() |
|||
{ |
|||
Assert.True(bag["Key"].ToBoolean(c)); |
|||
Assert.True(bag["Key"].ToNullableBoolean(c)); |
|||
} |
|||
|
|||
private void AssertInstant(Instant expected) |
|||
{ |
|||
Assert.Equal(expected.ToUnixTimeSeconds(), bag["Key"].ToInstant(c).ToUnixTimeSeconds()); |
|||
Assert.Equal(expected.ToUnixTimeSeconds(), bag["Key"].ToNullableInstant(c).Value.ToUnixTimeSeconds()); |
|||
} |
|||
|
|||
private void AssertGuid(Guid expected) |
|||
{ |
|||
Assert.Equal(expected, bag["Key"].ToGuid(c)); |
|||
Assert.Equal(expected, bag["Key"].ToNullableGuid(c)); |
|||
} |
|||
|
|||
private void AssertNumber() |
|||
{ |
|||
Assert.Equal(123, bag["Key"].ToInt32(c)); |
|||
Assert.Equal(123, bag["Key"].ToNullableInt32(c)); |
|||
Assert.Equal(123L, bag["Key"].ToInt64(c)); |
|||
Assert.Equal(123L, bag["Key"].ToNullableInt64(c)); |
|||
Assert.Equal(123f, bag["Key"].ToSingle(c)); |
|||
Assert.Equal(123f, bag["Key"].ToNullableSingle(c)); |
|||
Assert.Equal(123d, bag["Key"].ToDouble(c)); |
|||
Assert.Equal(123d, bag["Key"].ToNullableDouble(c)); |
|||
|
|||
Assert.True(bag["Key"].ToBoolean(c)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
"testRunner": "xunit", |
|||
"dependencies": { |
|||
"dotnet-test-xunit": "2.2.0-preview2-build1029", |
|||
"PinkParrot.Infrastructure": "1.0.0-*", |
|||
"xunit": "2.2.0-beta2-build3300" |
|||
}, |
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"buildOptions": { |
|||
"copyToOutput": { |
|||
"include": [ |
|||
"xunit.runner.json" |
|||
] |
|||
} |
|||
}, |
|||
"tooling": { |
|||
"defaultNamespace": "PinkParrot.Core.Tests" |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
{ |
|||
"diagnosticMessages": false, |
|||
"methodDisplay": "classAndMethod", |
|||
"parallelizeTestCollections": true |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// CommonHeaders.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public sealed class CommonHeaders |
|||
{ |
|||
public const string AggregateId = "AggregateId"; |
|||
public const string CommitId = "CommitId"; |
|||
public const string Timestamp = "Timestamp"; |
|||
public const string EventId = "EventId"; |
|||
public const string EventType = "EventType"; |
|||
public const string EventNumber = "EventNumber"; |
|||
} |
|||
} |
|||
@ -0,0 +1,105 @@ |
|||
// ==========================================================================
|
|||
// DomainObject.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public abstract class DomainObject : IAggregate, IEquatable<IAggregate> |
|||
{ |
|||
private readonly List<Envelope<IEvent>> uncomittedEvents = new List<Envelope<IEvent>>(); |
|||
private readonly Guid id; |
|||
private int version; |
|||
|
|||
public int Version |
|||
{ |
|||
get { return version; } |
|||
} |
|||
|
|||
public Guid Id |
|||
{ |
|||
get { return id; } |
|||
} |
|||
|
|||
protected DomainObject(Guid id, int version) |
|||
{ |
|||
Guard.NotEmpty(id, nameof(id)); |
|||
Guard.GreaterEquals(version, 0, nameof(version)); |
|||
|
|||
this.id = id; |
|||
|
|||
this.version = version; |
|||
} |
|||
|
|||
protected void RaiseEvent<TEvent>(Envelope<TEvent> envelope, bool disableApply = false) where TEvent : class, IEvent |
|||
{ |
|||
Guard.NotNull(envelope, nameof(envelope)); |
|||
|
|||
uncomittedEvents.Add(envelope.To<IEvent>()); |
|||
|
|||
if (!disableApply) |
|||
{ |
|||
ApplyEvent(envelope.Payload); |
|||
} |
|||
} |
|||
|
|||
protected void RaiseEvent(IEvent @event, bool disableApply = false) |
|||
{ |
|||
Guard.NotNull(@event, nameof(@event)); |
|||
|
|||
uncomittedEvents.Add(EnvelopeFactory.ForEvent(@event, id)); |
|||
|
|||
if (!disableApply) |
|||
{ |
|||
ApplyEvent(@event); |
|||
} |
|||
} |
|||
|
|||
protected void Apply(object @event) |
|||
{ |
|||
} |
|||
|
|||
private void ApplyEvent(dynamic @event) |
|||
{ |
|||
Apply(@event); |
|||
version++; |
|||
} |
|||
|
|||
void IAggregate.ApplyEvent(IEvent @event) |
|||
{ |
|||
Apply(@event as dynamic); |
|||
version++; |
|||
} |
|||
|
|||
void IAggregate.ClearUncommittedEvents() |
|||
{ |
|||
uncomittedEvents.Clear(); |
|||
} |
|||
|
|||
ICollection<Envelope<IEvent>> IAggregate.GetUncomittedEvents() |
|||
{ |
|||
return uncomittedEvents; |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
return id.GetHashCode(); |
|||
} |
|||
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return Equals(obj as IAggregate); |
|||
} |
|||
|
|||
public bool Equals(IAggregate other) |
|||
{ |
|||
return other != null && other.Id.Equals(id); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// ==========================================================================
|
|||
// Envelope.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public class Envelope<TPayload> where TPayload : class |
|||
{ |
|||
private readonly EnvelopeHeaders headers; |
|||
private readonly TPayload payload; |
|||
|
|||
public EnvelopeHeaders Headers |
|||
{ |
|||
get |
|||
{ |
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
public TPayload Payload |
|||
{ |
|||
get |
|||
{ |
|||
return payload; |
|||
} |
|||
} |
|||
|
|||
public Envelope(TPayload payload) |
|||
{ |
|||
Guard.NotNull(payload, nameof(payload)); |
|||
|
|||
this.payload = payload; |
|||
|
|||
headers = new EnvelopeHeaders(); |
|||
} |
|||
|
|||
public Envelope(TPayload payload, EnvelopeHeaders headers) |
|||
{ |
|||
Guard.NotNull(payload, nameof(payload)); |
|||
Guard.NotNull(headers, nameof(headers)); |
|||
|
|||
this.payload = payload; |
|||
this.headers = headers; |
|||
} |
|||
|
|||
public Envelope<TOther> To<TOther>() where TOther : class |
|||
{ |
|||
return new Envelope<TOther>(payload as TOther, headers.Clone()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
// ==========================================================================
|
|||
// EnvelopeExtensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Globalization; |
|||
using NodaTime; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public static class EnvelopeExtensions |
|||
{ |
|||
public static int EventNumber<T>(this Envelope<T> envelope) where T : class |
|||
{ |
|||
return envelope.Headers[CommonHeaders.EventNumber].ToInt32(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
public static Envelope<T> SetEventNumber<T>(this Envelope<T> envelope, int value) where T : class |
|||
{ |
|||
envelope.Headers.Set(CommonHeaders.EventNumber, value); |
|||
|
|||
return envelope; |
|||
} |
|||
|
|||
public static Guid CommitId<T>(this Envelope<T> envelope) where T : class |
|||
{ |
|||
return envelope.Headers[CommonHeaders.CommitId].ToGuid(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
public static Envelope<T> SetCommitId<T>(this Envelope<T> envelope, Guid value) where T : class |
|||
{ |
|||
envelope.Headers.Set(CommonHeaders.CommitId, value); |
|||
|
|||
return envelope; |
|||
} |
|||
|
|||
public static Guid AggregateId<T>(this Envelope<T> envelope) where T : class |
|||
{ |
|||
return envelope.Headers[CommonHeaders.AggregateId].ToGuid(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
public static Envelope<T> SetAggregateId<T>(this Envelope<T> envelope, Guid value) where T : class |
|||
{ |
|||
envelope.Headers.Set(CommonHeaders.AggregateId, value); |
|||
|
|||
return envelope; |
|||
} |
|||
|
|||
public static Guid EventId<T>(this Envelope<T> envelope) where T : class |
|||
{ |
|||
return envelope.Headers[CommonHeaders.EventId].ToGuid(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
public static Envelope<T> SetEventId<T>(this Envelope<T> envelope, Guid value) where T : class |
|||
{ |
|||
envelope.Headers.Set(CommonHeaders.EventId, value); |
|||
|
|||
return envelope; |
|||
} |
|||
|
|||
public static Instant Timestamp<T>(this Envelope<T> envelope) where T : class |
|||
{ |
|||
return envelope.Headers[CommonHeaders.Timestamp].ToInstant(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
public static Envelope<T> SetTimestamp<T>(this Envelope<T> envelope, Instant value) where T : class |
|||
{ |
|||
envelope.Headers.Set(CommonHeaders.Timestamp, value); |
|||
|
|||
return envelope; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// ==========================================================================
|
|||
// EnvelopeFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using NodaTime; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public static class EnvelopeFactory |
|||
{ |
|||
public static Envelope<IEvent> ForEvent(IEvent @event, Guid aggregateId) |
|||
{ |
|||
return new Envelope<IEvent>(@event) |
|||
.SetAggregateId(aggregateId) |
|||
.SetEventId(aggregateId) |
|||
.SetTimestamp(SystemClock.Instance.GetCurrentInstant()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// ==========================================================================
|
|||
// EnvelopeHeaders.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public sealed class EnvelopeHeaders : PropertiesBag |
|||
{ |
|||
public EnvelopeHeaders Clone() |
|||
{ |
|||
var clone = new EnvelopeHeaders(); |
|||
|
|||
foreach (var property in Properties) |
|||
{ |
|||
clone.Set(property.Key, property.Value.RawValue); |
|||
} |
|||
|
|||
return clone; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
// ==========================================================================
|
|||
// IAggregate.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public interface IAggregate |
|||
{ |
|||
Guid Id { get; } |
|||
|
|||
int Version { get; } |
|||
|
|||
void ApplyEvent(IEvent @event); |
|||
|
|||
void ClearUncommittedEvents(); |
|||
|
|||
ICollection<Envelope<IEvent>> GetUncomittedEvents(); |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,13 @@ |
|||
// ==========================================================================
|
|||
// IEvent.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
namespace PinkParrot.Infrastructure.CQRS |
|||
{ |
|||
public interface IEvent |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,110 @@ |
|||
// ==========================================================================
|
|||
// CollectionExtensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
// ReSharper disable InvertIf
|
|||
// ReSharper disable LoopCanBeConvertedToQuery
|
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public static class CollectionExtensions |
|||
{ |
|||
public static int SequentialHashCode<T>(this IEnumerable<T> collection) |
|||
{ |
|||
return collection.SequentialHashCode(EqualityComparer<T>.Default); |
|||
} |
|||
|
|||
public static int SequentialHashCode<T>(this IEnumerable<T> collection, IEqualityComparer<T> comparer) |
|||
{ |
|||
var hashCode = 17; |
|||
|
|||
foreach (var item in collection) |
|||
{ |
|||
if (item != null) |
|||
{ |
|||
hashCode = hashCode * 23 + item.GetHashCode(); |
|||
} |
|||
} |
|||
|
|||
return hashCode; |
|||
} |
|||
|
|||
public static int OrderedHashCode<T>(this IEnumerable<T> collection) |
|||
{ |
|||
return collection.OrderedHashCode(EqualityComparer<T>.Default); |
|||
} |
|||
|
|||
public static int OrderedHashCode<T>(this IEnumerable<T> collection, IEqualityComparer<T> comparer) |
|||
{ |
|||
var hashCodes = collection.Where(x => x != null).Select(x => x.GetHashCode()).OrderBy(x => x).ToArray(); |
|||
|
|||
var hashCode = 17; |
|||
|
|||
foreach (var code in hashCodes) |
|||
{ |
|||
hashCode = hashCode * 23 + code; |
|||
} |
|||
|
|||
return hashCode; |
|||
} |
|||
|
|||
public static bool EqualsDictionary<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, IDictionary<TKey, TValue> other) |
|||
{ |
|||
return Equals(dictionary, other) || (other != null && dictionary.Count == other.Count && !dictionary.Except(other).Any()); |
|||
} |
|||
|
|||
public static TValue GetOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key) |
|||
{ |
|||
return dictionary.GetOrCreate(key, _ => default(TValue)); |
|||
} |
|||
|
|||
public static TValue GetOrAddDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) |
|||
{ |
|||
return dictionary.GetOrAdd(key, _ => default(TValue)); |
|||
} |
|||
|
|||
public static TValue GetOrNew<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key) where TValue : class, new() |
|||
{ |
|||
return dictionary.GetOrCreate(key, _ => new TValue()); |
|||
} |
|||
|
|||
public static TValue GetOrAddNew<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) where TValue : class, new() |
|||
{ |
|||
return dictionary.GetOrAdd(key, _ => new TValue()); |
|||
} |
|||
|
|||
public static TValue GetOrCreate<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> creator) |
|||
{ |
|||
TValue result; |
|||
|
|||
if (!dictionary.TryGetValue(key, out result)) |
|||
{ |
|||
result = creator(key); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> creator) |
|||
{ |
|||
TValue result; |
|||
|
|||
if (!dictionary.TryGetValue(key, out result)) |
|||
{ |
|||
result = creator(key); |
|||
|
|||
dictionary.Add(key, result); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// ==========================================================================
|
|||
// DomainValidationException.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public class DomainValidationException : Exception |
|||
{ |
|||
private readonly IReadOnlyList<string> errors; |
|||
|
|||
public IReadOnlyList<string> Errors |
|||
{ |
|||
get { return errors; } |
|||
} |
|||
|
|||
public DomainValidationException(string message, params string[] errors) |
|||
: base(message) |
|||
{ |
|||
this.errors = errors != null ? errors.ToList() : new List<string>(); |
|||
} |
|||
|
|||
public DomainValidationException(string message, IReadOnlyList<string> errors) |
|||
: base(message) |
|||
{ |
|||
this.errors = errors ?? new List<string>(); |
|||
} |
|||
|
|||
public DomainValidationException(string message, Exception inner, params string[] errors) |
|||
: base(message, inner) |
|||
{ |
|||
this.errors = errors != null ? errors.ToList() : new List<string>(); |
|||
} |
|||
|
|||
public DomainValidationException(string message, Exception inner, IReadOnlyList<string> errors) |
|||
: base(message, inner) |
|||
{ |
|||
this.errors = errors ?? new List<string>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// EnumExtensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public static class EnumExtensions |
|||
{ |
|||
public static bool IsEnumValue<TEnum>(this TEnum value) where TEnum : struct |
|||
{ |
|||
try |
|||
{ |
|||
return Enum.IsDefined(typeof(TEnum), value); |
|||
} |
|||
catch |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
// ==========================================================================
|
|||
// Extensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text.RegularExpressions; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public static class Extensions |
|||
{ |
|||
private static readonly Regex SlugRegex = new Regex("^[a-z0-9]+(\\-[a-z0-9]+)*$", RegexOptions.Compiled); |
|||
|
|||
public static bool IsSlug(this string value) |
|||
{ |
|||
return value != null && SlugRegex.IsMatch(value); |
|||
} |
|||
|
|||
public static bool IsBetween<TValue>(this TValue value, TValue low, TValue high) where TValue : IComparable |
|||
{ |
|||
return Comparer<TValue>.Default.Compare(low, value) <= 0 && Comparer<TValue>.Default.Compare(high, value) >= 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,240 @@ |
|||
// ==========================================================================
|
|||
// Guard.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Globalization; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
// ReSharper disable InvertIf
|
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public static class Guard |
|||
{ |
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ValidNumber(float target, string parameterName) |
|||
{ |
|||
if (float.IsNaN(target) || float.IsPositiveInfinity(target) || float.IsNegativeInfinity(target)) |
|||
{ |
|||
throw new ArgumentException("Value must be a valid number.", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ValidNumber(double target, string parameterName) |
|||
{ |
|||
if (double.IsNaN(target) || double.IsPositiveInfinity(target) || double.IsNegativeInfinity(target)) |
|||
{ |
|||
throw new ArgumentException("Value must be a valid number.", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ValidSlug(string target, string parameterName) |
|||
{ |
|||
NotNullOrEmpty(target, parameterName); |
|||
|
|||
if (!target.IsSlug()) |
|||
{ |
|||
throw new ArgumentException("Target is not a valid slug.", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void HasType<T>(object target, string parameterName) |
|||
{ |
|||
NotNull(target, "parameterName"); |
|||
|
|||
if (target.GetType() != typeof(T)) |
|||
{ |
|||
throw new ArgumentException("The parameter must be of type " + typeof(T), parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Between<TValue>(TValue target, TValue lower, TValue upper, string parameterName) where TValue : IComparable |
|||
{ |
|||
if (!target.IsBetween(lower, upper)) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be between {0} and {1}", lower, upper); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Enum<TEnum>(TEnum target, string parameterName) where TEnum : struct |
|||
{ |
|||
if (!target.IsEnumValue()) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be a valid enum type {0}", typeof(TEnum)); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void GreaterThan<TValue>(TValue target, TValue lower, string parameterName) where TValue : IComparable |
|||
{ |
|||
if (target.CompareTo(lower) <= 0) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be greater than {0}", lower); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void GreaterEquals<TValue>(TValue target, TValue lower, string parameterName) where TValue : IComparable |
|||
{ |
|||
if (target.CompareTo(lower) < 0) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be greater than {0}", lower); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void LessThan<TValue>(TValue target, TValue upper, string parameterName) where TValue : IComparable |
|||
{ |
|||
if (target.CompareTo(upper) >= 0) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be less than {0}", upper); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void LessEquals<TValue>(TValue target, TValue upper, string parameterName) where TValue : IComparable |
|||
{ |
|||
if (target.CompareTo(upper) > 0) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be less than {0}", upper); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void NotEmpty<TType>(ICollection<TType> enumerable, string parameterName) |
|||
{ |
|||
if (enumerable == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(enumerable)); |
|||
} |
|||
|
|||
if (enumerable.Count == 0) |
|||
{ |
|||
throw new ArgumentException("Collection does not contain an item", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void NotEmpty(Guid target, string parameterName) |
|||
{ |
|||
if (target == Guid.Empty) |
|||
{ |
|||
throw new ArgumentException("Value cannot be empty.", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void NotNull(object target, string parameterName) |
|||
{ |
|||
if (target == null) |
|||
{ |
|||
throw new ArgumentNullException(parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void NotDefault<T>(T target, string parameterName) |
|||
{ |
|||
if (Equals(target, default(T))) |
|||
{ |
|||
throw new ArgumentException("Value cannot be an the default value", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void NotNullOrEmpty(string target, string parameterName, bool allowWhitespacesAtStartOrEnd = true) |
|||
{ |
|||
if (target == null) |
|||
{ |
|||
throw new ArgumentNullException(parameterName); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(target)) |
|||
{ |
|||
throw new ArgumentException("String parameter cannot be null or empty and cannot contain only blanks.", parameterName); |
|||
} |
|||
|
|||
if (!allowWhitespacesAtStartOrEnd && target.Trim() != target) |
|||
{ |
|||
throw new ArgumentException("String cannot start or end with whitespaces", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ValidFileName(string target, string parameterName) |
|||
{ |
|||
NotNullOrEmpty(target, parameterName); |
|||
|
|||
if (target.Intersect(Path.GetInvalidFileNameChars()).Any()) |
|||
{ |
|||
throw new ArgumentException("Value contains an invalid character.", parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void IsType<T>(object target, string parameterName) |
|||
{ |
|||
if (target != null && target.GetType() != typeof(T)) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be of type {0}", typeof(T)); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
[DebuggerStepThrough] |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void IsType(object target, Type expectedType, string parameterName) |
|||
{ |
|||
if (target != null && expectedType != null && target.GetType() != expectedType) |
|||
{ |
|||
var message = string.Format(CultureInfo.CurrentCulture, "Value must be of type {0}", expectedType); |
|||
|
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
|
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>bd1c30a8-8ffa-4a92-a9bd-b67b1cddd84c</ProjectGuid> |
|||
<RootNamespace>PinkParrot.Infrastructure</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,94 @@ |
|||
// ==========================================================================
|
|||
// PropertiesBag.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public class PropertiesBag |
|||
{ |
|||
private readonly Dictionary<string, PropertyValue> internalDictionary = new Dictionary<string, PropertyValue>(StringComparer.OrdinalIgnoreCase); |
|||
|
|||
public int Count |
|||
{ |
|||
get { return internalDictionary.Count; } |
|||
} |
|||
|
|||
public IReadOnlyDictionary<string, PropertyValue> Properties |
|||
{ |
|||
get { return internalDictionary; } |
|||
} |
|||
|
|||
public IEnumerable<string> PropertyNames |
|||
{ |
|||
get { return internalDictionary.Keys; } |
|||
} |
|||
|
|||
public PropertyValue this[string propertyName] |
|||
{ |
|||
get |
|||
{ |
|||
Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); |
|||
|
|||
return internalDictionary[propertyName]; |
|||
} |
|||
} |
|||
|
|||
public bool Contains(string propertyName) |
|||
{ |
|||
Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); |
|||
|
|||
return internalDictionary.ContainsKey(propertyName); |
|||
} |
|||
|
|||
public PropertiesBag Set(string propertyName, object value) |
|||
{ |
|||
Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); |
|||
|
|||
internalDictionary[propertyName] = new PropertyValue(value); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public bool Remove(string propertyName) |
|||
{ |
|||
Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); |
|||
|
|||
return internalDictionary.Remove(propertyName); |
|||
} |
|||
|
|||
public bool Rename(string oldPropertyName, string newPropertyName) |
|||
{ |
|||
Guard.NotNullOrEmpty(oldPropertyName, nameof(oldPropertyName)); |
|||
Guard.NotNullOrEmpty(newPropertyName, nameof(newPropertyName)); |
|||
|
|||
if (internalDictionary.ContainsKey(newPropertyName)) |
|||
{ |
|||
throw new ArgumentException($"An property with the key '{newPropertyName}' already exists.", newPropertyName); |
|||
} |
|||
|
|||
if (string.Equals(oldPropertyName, newPropertyName, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
throw new ArgumentException($"The property names '{newPropertyName}' are equal.", newPropertyName); |
|||
} |
|||
|
|||
PropertyValue property; |
|||
|
|||
if (!internalDictionary.TryGetValue(oldPropertyName, out property)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
internalDictionary[newPropertyName] = property; |
|||
internalDictionary.Remove(oldPropertyName); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,211 @@ |
|||
// ==========================================================================
|
|||
// PropertyValue.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using NodaTime; |
|||
using NodaTime.Text; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public sealed class PropertyValue |
|||
{ |
|||
private readonly object rawValue; |
|||
|
|||
private static readonly HashSet<Type> AllowedTypes = new HashSet<Type> |
|||
{ |
|||
typeof(string), |
|||
typeof(bool), |
|||
typeof(bool?), |
|||
typeof(float), |
|||
typeof(float?), |
|||
typeof(double), |
|||
typeof(double?), |
|||
typeof(int), |
|||
typeof(int?), |
|||
typeof(long), |
|||
typeof(long?), |
|||
typeof(Instant), |
|||
typeof(Instant?), |
|||
typeof(Guid), |
|||
typeof(Guid?) |
|||
}; |
|||
|
|||
public object RawValue |
|||
{ |
|||
get { return rawValue; } |
|||
} |
|||
|
|||
internal PropertyValue(object rawValue) |
|||
{ |
|||
if (rawValue != null && !AllowedTypes.Contains(rawValue.GetType())) |
|||
{ |
|||
throw new ArgumentException("The type is not supported.", nameof(rawValue)); |
|||
} |
|||
|
|||
this.rawValue = rawValue; |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return rawValue?.ToString(); |
|||
} |
|||
|
|||
public bool ToBoolean(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, bool.Parse); |
|||
} |
|||
|
|||
public bool? ToNullableBoolean(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, bool.Parse); |
|||
} |
|||
|
|||
public float ToSingle(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, x => float.Parse(x, culture)); |
|||
} |
|||
|
|||
public float? ToNullableSingle(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, x => float.Parse(x, culture)); |
|||
} |
|||
|
|||
public double ToDouble(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, x => double.Parse(x, culture)); |
|||
} |
|||
|
|||
public double? ToNullableDouble(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, x => double.Parse(x, culture)); |
|||
} |
|||
|
|||
public int ToInt32(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, x => int.Parse(x, culture)); |
|||
} |
|||
|
|||
public int? ToNullableInt32(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, x => int.Parse(x, culture)); |
|||
} |
|||
|
|||
public long ToInt64(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, x => long.Parse(x, culture)); |
|||
} |
|||
|
|||
public long? ToNullableInt64(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, x => long.Parse(x, culture)); |
|||
} |
|||
|
|||
public Instant ToInstant(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, x => InstantPattern.GeneralPattern.Parse(x).Value); |
|||
} |
|||
|
|||
public Instant? ToNullableInstant(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, x => InstantPattern.GeneralPattern.Parse(x).Value); |
|||
} |
|||
|
|||
public Guid ToGuid(CultureInfo culture) |
|||
{ |
|||
return ToOrParseValue(culture, Guid.Parse); |
|||
} |
|||
|
|||
public Guid? ToNullableGuid(CultureInfo culture) |
|||
{ |
|||
return ToNullableOrParseValue(culture, Guid.Parse); |
|||
} |
|||
|
|||
private T? ToNullableOrParseValue<T>(IFormatProvider culture, Func<string, T> parser) where T : struct |
|||
{ |
|||
T result; |
|||
|
|||
return TryParse(culture, parser, out result) ? result : (T?)null; |
|||
} |
|||
|
|||
private T ToOrParseValue<T>(IFormatProvider culture, Func<string, T> parser) |
|||
{ |
|||
T result; |
|||
|
|||
return TryParse(culture, parser, out result) ? result : default(T); |
|||
} |
|||
|
|||
private bool TryParse<T>(IFormatProvider culture, Func<string, T> parser, out T result) |
|||
{ |
|||
var value = rawValue; |
|||
|
|||
if (value != null) |
|||
{ |
|||
var valueType = value.GetType(); |
|||
|
|||
if (valueType == typeof(T)) |
|||
{ |
|||
result = (T)value; |
|||
} |
|||
else if (valueType == typeof(string)) |
|||
{ |
|||
result = Parse(parser, valueType, value); |
|||
} |
|||
else |
|||
{ |
|||
result = Convert<T>(culture, value, valueType); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
result = default(T); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private static T Convert<T>(IFormatProvider culture, object value, Type valueType) |
|||
{ |
|||
var requestedType = typeof(T); |
|||
|
|||
try |
|||
{ |
|||
return (T)System.Convert.ChangeType(value, requestedType, culture); |
|||
} |
|||
catch (OverflowException) |
|||
{ |
|||
string message = $"The property has type '{valueType}' and cannot be casted to '{requestedType}' because it is either too small or large."; |
|||
|
|||
throw new InvalidCastException(message); |
|||
} |
|||
catch (InvalidCastException) |
|||
{ |
|||
string message = $"The property has type '{valueType}' and cannot be casted to '{requestedType}'."; |
|||
|
|||
throw new InvalidCastException(message); |
|||
} |
|||
} |
|||
|
|||
private static T Parse<T>(Func<string, T> parser, Type valueType, object value) |
|||
{ |
|||
var requestedType = typeof(T); |
|||
|
|||
try |
|||
{ |
|||
return parser(value.ToString()); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
string message = $"The property has type '{valueType}' and cannot be casted to '{requestedType}'."; |
|||
|
|||
throw new InvalidCastException(message, e); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// TaskExtensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.Tasks |
|||
{ |
|||
public static class TaskExtensions |
|||
{ |
|||
public static void Forget(this Task task) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// ==========================================================================
|
|||
// TaskHelper.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.Tasks |
|||
{ |
|||
public static class TaskHelper |
|||
{ |
|||
public static readonly Task Done = CreateDoneTask(); |
|||
|
|||
private static Task CreateDoneTask() |
|||
{ |
|||
var result = new TaskCompletionSource<object>(); |
|||
|
|||
result.SetResult(null); |
|||
|
|||
return result.Task; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
"dependencies": { |
|||
"NodaTime": "2.0.0-alpha20160729", |
|||
"NETStandard.Library": "1.6.0" |
|||
}, |
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"tooling": { |
|||
"defaultNamespace": "PinkParrot.Infrastructure" |
|||
} |
|||
} |
|||
@ -0,0 +1,234 @@ |
|||
## Ignore Visual Studio temporary files, build results, and |
|||
## files generated by popular Visual Studio add-ons. |
|||
|
|||
# User-specific files |
|||
*.suo |
|||
*.user |
|||
*.userosscache |
|||
*.sln.docstates |
|||
|
|||
# User-specific files (MonoDevelop/Xamarin Studio) |
|||
*.userprefs |
|||
|
|||
# Build results |
|||
[Dd]ebug/ |
|||
[Dd]ebugPublic/ |
|||
[Rr]elease/ |
|||
[Rr]eleases/ |
|||
x64/ |
|||
x86/ |
|||
build/ |
|||
bld/ |
|||
[Bb]in/ |
|||
[Oo]bj/ |
|||
|
|||
# Visual Studio 2015 cache/options directory |
|||
.vs/ |
|||
# Uncomment if you have tasks that create the project's static files in wwwroot |
|||
#wwwroot/ |
|||
|
|||
# MSTest test Results |
|||
[Tt]est[Rr]esult*/ |
|||
[Bb]uild[Ll]og.* |
|||
|
|||
# NUNIT |
|||
*.VisualState.xml |
|||
TestResult.xml |
|||
|
|||
# Build Results of an ATL Project |
|||
[Dd]ebugPS/ |
|||
[Rr]eleasePS/ |
|||
dlldata.c |
|||
|
|||
# DNX |
|||
project.lock.json |
|||
artifacts/ |
|||
|
|||
*_i.c |
|||
*_p.c |
|||
*_i.h |
|||
*.ilk |
|||
*.meta |
|||
*.obj |
|||
*.pch |
|||
*.pdb |
|||
*.pgc |
|||
*.pgd |
|||
*.rsp |
|||
*.sbr |
|||
*.tlb |
|||
*.tli |
|||
*.tlh |
|||
*.tmp |
|||
*.tmp_proj |
|||
*.log |
|||
*.vspscc |
|||
*.vssscc |
|||
.builds |
|||
*.pidb |
|||
*.svclog |
|||
*.scc |
|||
|
|||
# Chutzpah Test files |
|||
_Chutzpah* |
|||
|
|||
# Visual C++ cache files |
|||
ipch/ |
|||
*.aps |
|||
*.ncb |
|||
*.opendb |
|||
*.opensdf |
|||
*.sdf |
|||
*.cachefile |
|||
|
|||
# Visual Studio profiler |
|||
*.psess |
|||
*.vsp |
|||
*.vspx |
|||
*.sap |
|||
|
|||
# TFS 2012 Local Workspace |
|||
$tf/ |
|||
|
|||
# Guidance Automation Toolkit |
|||
*.gpState |
|||
|
|||
# ReSharper is a .NET coding add-in |
|||
_ReSharper*/ |
|||
*.[Rr]e[Ss]harper |
|||
*.DotSettings.user |
|||
|
|||
# JustCode is a .NET coding add-in |
|||
.JustCode |
|||
|
|||
# TeamCity is a build add-in |
|||
_TeamCity* |
|||
|
|||
# DotCover is a Code Coverage Tool |
|||
*.dotCover |
|||
|
|||
# NCrunch |
|||
_NCrunch_* |
|||
.*crunch*.local.xml |
|||
nCrunchTemp_* |
|||
|
|||
# MightyMoose |
|||
*.mm.* |
|||
AutoTest.Net/ |
|||
|
|||
# Web workbench (sass) |
|||
.sass-cache/ |
|||
|
|||
# Installshield output folder |
|||
[Ee]xpress/ |
|||
|
|||
# DocProject is a documentation generator add-in |
|||
DocProject/buildhelp/ |
|||
DocProject/Help/*.HxT |
|||
DocProject/Help/*.HxC |
|||
DocProject/Help/*.hhc |
|||
DocProject/Help/*.hhk |
|||
DocProject/Help/*.hhp |
|||
DocProject/Help/Html2 |
|||
DocProject/Help/html |
|||
|
|||
# Click-Once directory |
|||
publish/ |
|||
|
|||
# Publish Web Output |
|||
*.[Pp]ublish.xml |
|||
*.azurePubxml |
|||
# TODO: Comment the next line if you want to checkin your web deploy settings |
|||
# but database connection strings (with potential passwords) will be unencrypted |
|||
*.pubxml |
|||
*.publishproj |
|||
|
|||
# NuGet Packages |
|||
*.nupkg |
|||
# The packages folder can be ignored because of Package Restore |
|||
**/packages/* |
|||
# except build/, which is used as an MSBuild target. |
|||
!**/packages/build/ |
|||
# Uncomment if necessary however generally it will be regenerated when needed |
|||
#!**/packages/repositories.config |
|||
|
|||
# Microsoft Azure Build Output |
|||
csx/ |
|||
*.build.csdef |
|||
|
|||
# Microsoft Azure Emulator |
|||
ecf/ |
|||
rcf/ |
|||
|
|||
# Microsoft Azure ApplicationInsights config file |
|||
ApplicationInsights.config |
|||
|
|||
# Windows Store app package directory |
|||
AppPackages/ |
|||
BundleArtifacts/ |
|||
|
|||
# Visual Studio cache files |
|||
# files ending in .cache can be ignored |
|||
*.[Cc]ache |
|||
# but keep track of directories ending in .cache |
|||
!*.[Cc]ache/ |
|||
|
|||
# Others |
|||
ClientBin/ |
|||
~$* |
|||
*~ |
|||
*.dbmdl |
|||
*.dbproj.schemaview |
|||
*.pfx |
|||
*.publishsettings |
|||
node_modules/ |
|||
orleans.codegen.cs |
|||
|
|||
# RIA/Silverlight projects |
|||
Generated_Code/ |
|||
|
|||
# Backup & report files from converting an old project file |
|||
# to a newer Visual Studio version. Backup files are not needed, |
|||
# because we have git ;-) |
|||
_UpgradeReport_Files/ |
|||
Backup*/ |
|||
UpgradeLog*.XML |
|||
UpgradeLog*.htm |
|||
|
|||
# SQL Server files |
|||
*.mdf |
|||
*.ldf |
|||
|
|||
# Business Intelligence projects |
|||
*.rdl.data |
|||
*.bim.layout |
|||
*.bim_*.settings |
|||
|
|||
# Microsoft Fakes |
|||
FakesAssemblies/ |
|||
|
|||
# GhostDoc plugin setting file |
|||
*.GhostDoc.xml |
|||
|
|||
# Node.js Tools for Visual Studio |
|||
.ntvs_analysis.dat |
|||
|
|||
# Visual Studio 6 build log |
|||
*.plg |
|||
|
|||
# Visual Studio 6 workspace options file |
|||
*.opt |
|||
|
|||
# Visual Studio LightSwitch build output |
|||
**/*.HTMLClient/GeneratedArtifacts |
|||
**/*.DesktopClient/GeneratedArtifacts |
|||
**/*.DesktopClient/ModelManifest.xml |
|||
**/*.Server/GeneratedArtifacts |
|||
**/*.Server/ModelManifest.xml |
|||
_Pvt_Extensions |
|||
|
|||
# Paket dependency manager |
|||
.paket/paket.exe |
|||
|
|||
# FAKE - F# Make |
|||
.fake/ |
|||
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>a85201c6-6af8-4b63-8365-08f741050438</ProjectGuid> |
|||
<RootNamespace>PinkParrot.Write</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,21 @@ |
|||
// ==========================================================================
|
|||
// AddModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class AddModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public string FieldType; |
|||
|
|||
public string FieldName; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// CreateModelSchema.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class CreateModelSchema |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public string Name; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// DeleteModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class DeleteModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// ==========================================================================
|
|||
// DeleteModelSchema.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class DeleteModelSchema |
|||
{ |
|||
public Guid AggregateId; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// DisableModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class DisableModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// EnableModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class EnableModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// HideModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class HideModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// ShowModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class ShowModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public Guid FieldId; |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// UpdateModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class UpdateModelField |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public Guid FieldId; |
|||
|
|||
public PropertiesBag Settings; |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// UpdateModelSchema.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Write.Schema.Commands |
|||
{ |
|||
public class UpdateModelSchema |
|||
{ |
|||
public Guid AggregateId; |
|||
|
|||
public string NewName; |
|||
|
|||
public PropertiesBag Settings { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaDomainObject.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using PinkParrot.Core.Schema; |
|||
using PinkParrot.Events.Schema; |
|||
using PinkParrot.Infrastructure.CQRS; |
|||
using PinkParrot.Write.Schema.Commands; |
|||
|
|||
namespace PinkParrot.Write.Schema |
|||
{ |
|||
public class ModelSchemaDomainObject : DomainObject |
|||
{ |
|||
private readonly ModelFieldFactory fieldFactory; |
|||
private bool isDeleted; |
|||
private ModelSchema schema; |
|||
|
|||
public ModelSchemaDomainObject(Guid id, int version, ModelFieldFactory fieldFactory) |
|||
: base(id, version) |
|||
{ |
|||
this.fieldFactory = fieldFactory; |
|||
} |
|||
|
|||
public ModelSchema Schema |
|||
{ |
|||
get { return schema; } |
|||
} |
|||
|
|||
public bool IsDeleted |
|||
{ |
|||
get { return isDeleted; } |
|||
} |
|||
|
|||
protected void Apply(ModelSchemaCreated @event) |
|||
{ |
|||
schema = ModelSchema.Create(@event.Name); |
|||
} |
|||
|
|||
protected void Apply(ModelFieldAdded @event) |
|||
{ |
|||
schema = schema.AddField(@event.FieldId, @event.FieldType, @event.FieldName, fieldFactory); |
|||
} |
|||
|
|||
protected void Apply(ModelFieldUpdated @event) |
|||
{ |
|||
schema = schema.SetField(@event.FieldId, @event.Settings); |
|||
} |
|||
|
|||
public void Apply(ModelFieldHidden @event) |
|||
{ |
|||
schema = schema.HideField(@event.FieldId); |
|||
} |
|||
|
|||
public void Apply(ModelFieldShown @event) |
|||
{ |
|||
schema = schema.ShowField(@event.FieldId); |
|||
} |
|||
|
|||
public void Apply(ModelFieldDisabled @event) |
|||
{ |
|||
schema = schema.DisableField(@event.FieldId); |
|||
} |
|||
|
|||
public void Apply(ModelFieldEnabled @event) |
|||
{ |
|||
schema = schema.EnableField(@event.FieldId); |
|||
} |
|||
|
|||
protected void Apply(ModelSchemaUpdated @event) |
|||
{ |
|||
schema = schema.Update(schema.Metadata.Configure(@event.NewName, @event.Settings)); |
|||
} |
|||
|
|||
protected void Apply(ModelFieldDeleted @event) |
|||
{ |
|||
schema = schema.DeleteField(@event.FieldId); |
|||
} |
|||
|
|||
protected void Apply(ModelSchemaDeleted @event) |
|||
{ |
|||
isDeleted = false; |
|||
} |
|||
|
|||
public void Create(CreateModelSchema command) |
|||
{ |
|||
VerifyNotCreated(); |
|||
|
|||
schema = ModelSchema.Create(command.Name); |
|||
|
|||
RaiseEvent(new ModelSchemaCreated {Name = command.Name}, true); |
|||
} |
|||
|
|||
public void AddField(Guid id, AddModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.AddField(id, command.FieldType, command.FieldName, fieldFactory); |
|||
|
|||
RaiseEvent( |
|||
new ModelFieldAdded {FieldId = id, FieldType = command.FieldType, FieldName = command.FieldName}, true); |
|||
} |
|||
|
|||
public void Update(UpdateModelSchema command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.Update(schema.Metadata.Configure(command.NewName, command.Settings)); |
|||
|
|||
RaiseEvent(new ModelSchemaUpdated {NewName = command.NewName, Settings = command.Settings}, true); |
|||
} |
|||
|
|||
public void UpdateField(UpdateModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.SetField(command.FieldId, command.Settings); |
|||
|
|||
RaiseEvent(new ModelFieldUpdated {FieldId = command.FieldId, Settings = command.Settings}, true); |
|||
} |
|||
|
|||
public void HideField(HideModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.HideField(command.FieldId); |
|||
|
|||
RaiseEvent(new ModelFieldHidden {FieldId = command.FieldId}, true); |
|||
} |
|||
|
|||
public void ShowField(HideModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.ShowField(command.FieldId); |
|||
|
|||
RaiseEvent(new ModelFieldShown {FieldId = command.FieldId}, true); |
|||
} |
|||
|
|||
public void DisableField(DisableModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.DisableField(command.FieldId); |
|||
|
|||
RaiseEvent(new ModelFieldDisabled {FieldId = command.FieldId}, true); |
|||
} |
|||
|
|||
public void EnableField(EnableModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.EnableField(command.FieldId); |
|||
|
|||
RaiseEvent(new ModelFieldEnabled {FieldId = command.FieldId}, true); |
|||
} |
|||
|
|||
public void Delete(DeleteModelSchema command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
isDeleted = true; |
|||
|
|||
RaiseEvent(new ModelSchemaDeleted(), true); |
|||
} |
|||
|
|||
public void DeleteField(DeleteModelField command) |
|||
{ |
|||
VerifyCreatedAndNotDeleted(); |
|||
|
|||
schema = schema.DeleteField(command.FieldId); |
|||
|
|||
RaiseEvent(new ModelFieldDeleted {FieldId = command.FieldId}, true); |
|||
} |
|||
|
|||
private void VerifyNotCreated() |
|||
{ |
|||
if (schema != null) |
|||
{ |
|||
throw new InvalidOperationException("Schema has already been created."); |
|||
} |
|||
} |
|||
|
|||
private void VerifyCreatedAndNotDeleted() |
|||
{ |
|||
if (isDeleted || schema == null) |
|||
{ |
|||
throw new InvalidOperationException("Schema has already been deleted or not created yet."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
|
|||
"dependencies": { |
|||
"NETStandard.Library": "1.6.0", |
|||
"NodaTime": "2.0.0-alpha20160729", |
|||
"PinkParrot.Core": "1.0.0-*", |
|||
"PinkParrot.Events": "1.0.0-*", |
|||
"PinkParrot.Infrastructure": "1.0.0-*" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"netcoreapp1.0": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
|
|||
"tooling": { |
|||
"defaultNamespace": "PinkParrot.Write" |
|||
} |
|||
} |
|||
Loading…
Reference in new issue