├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── Structurizr.Client.Tests ├── Api │ ├── Md5DigestTests.cs │ └── StructurizrClientTests.cs ├── Encryption │ ├── AesEncryptionStrategyTests.cs │ ├── EncryptedWorkspaceTests.cs │ └── MockEncryptionStrategy.cs ├── IO │ └── JsonReaderTests.cs ├── Structurizr.Client.Tests.csproj └── TestFailedException.cs ├── Structurizr.Client ├── Api │ ├── ApiResponse.cs │ ├── HashBasedMessageAuthenticationCode.cs │ ├── HmacAuthorizationHeader.cs │ ├── HmacContent.cs │ ├── HttpHeaders.cs │ ├── Md5Digest.cs │ ├── StructurizrClient.cs │ └── StructurizrClientException.cs ├── AssemblyInfo.cs ├── Encryption │ ├── AesEncryptionStrategy.cs │ ├── EncryptedJsonReader.cs │ ├── EncryptedJsonWriter.cs │ ├── EncryptedWorkspace.cs │ └── EncryptionStrategy.cs ├── IO │ └── Json │ │ ├── EncryptionStrategyJsonConverter.cs │ │ ├── JsonReader.cs │ │ ├── JsonWriter.cs │ │ └── PaperSizeJsonConverter.cs ├── Structurizr.Client.csproj └── Util │ └── WorkspaceUtils.cs ├── Structurizr.Core.Tests ├── AbstractTestBase.cs ├── Config │ └── WorkspaceConfigurationTests.cs ├── Documentation │ ├── Arc42DocumentationTests.cs │ ├── DocumentationTemplateTests.cs │ ├── DocumentationTests.cs │ ├── FormatFinderTests.cs │ ├── SectionTests.cs │ ├── StructurizrDocumentationTests.cs │ ├── ViewpointsAndPerspectivesDocumentationTests.cs │ ├── arc42 │ │ ├── architectural-decisions.md │ │ ├── building-block-view.md │ │ ├── constraints.md │ │ ├── context-and-scope.md │ │ ├── crosscutting-concepts.md │ │ ├── deployment-view.md │ │ ├── glossary.md │ │ ├── introduction-and-goals.md │ │ ├── quality-requirements.md │ │ ├── risks-and-technical-debt.md │ │ ├── runtime-view.md │ │ └── solution-strategy.md │ ├── example.md │ ├── image.gif │ ├── image.jpeg │ ├── image.jpg │ ├── image.png │ ├── images │ │ ├── image.gif │ │ ├── image.jpeg │ │ ├── image.jpg │ │ └── image.png │ ├── markdown │ │ ├── 1.md │ │ └── subdirectory │ │ │ └── 2.md │ ├── noimages │ │ └── readme.md │ ├── structurizr │ │ ├── code-for-componentA1.md │ │ ├── code-for-componentA2.md │ │ ├── components-for-containerA.md │ │ ├── components-for-containerB.md │ │ ├── constraints.md │ │ ├── containers.md │ │ ├── context.md │ │ ├── data.md │ │ ├── decision-log.md │ │ ├── deployment.md │ │ ├── development-environment.md │ │ ├── functional-overview.md │ │ ├── infrastructure-architecture.md │ │ ├── operation-and-support.md │ │ ├── principles.md │ │ ├── quality-attributes.md │ │ └── software-architecture.md │ └── viewpointsandperspectives │ │ ├── 01-introduction.md │ │ ├── 02-glossary.md │ │ ├── 03-system-stakeholders-and-requirements.md │ │ ├── 04-architectural-forces.md │ │ ├── 05-architectural-views.md │ │ ├── 06-system-qualities.md │ │ └── 07-appendices.adoc ├── Model │ ├── CodeElementTests.cs │ ├── ComponentTests.cs │ ├── ContainerInstanceTests.cs │ ├── ContainerTests.cs │ ├── CreateImpliedRelationshipsUnlessAnyRelationshipExistsStrategyTests.cs │ ├── CreateImpliedRelationshipsUnlessSameRelationshipExistsStrategyTests.cs │ ├── DeploymentNodeTests.cs │ ├── ElementTests.cs │ ├── GroupableElementTests.cs │ ├── HttpHealthCheckTests.cs │ ├── ModelItemTests.cs │ ├── ModelTests.cs │ ├── PersonTests.cs │ ├── RelationshipTests.cs │ └── SoftwareSystemInstanceTests.cs ├── Structurizr.Core.Tests.csproj ├── TestFailedException.cs ├── Util │ ├── ImageUtilTests.cs │ ├── UrlTests.cs │ ├── readme.txt │ └── structurizr-logo.png ├── View │ ├── AutomaticLayoutTests.cs │ ├── BrandingTests.cs │ ├── ColorPairTests.cs │ ├── ColorTests.cs │ ├── ComponentViewTests.cs │ ├── ConfigurationTests.cs │ ├── ContainerViewTests.cs │ ├── DefaultLayoutMergeStrategyTests.cs │ ├── DeploymentViewTests.cs │ ├── DimensionsTests.cs │ ├── DynamicViewTests.cs │ ├── ElementStyleTests.cs │ ├── FilteredViewTests.cs │ ├── FontTests.cs │ ├── RelationshipStyleTests.cs │ ├── SequenceCounterTests.cs │ ├── SequenceNumberTests.cs │ ├── StaticViewTests.cs │ ├── StyleTests.cs │ ├── SystemContextViewTests.cs │ ├── SystemLandscapeViewTests.cs │ └── ViewTests.cs └── WorkspaceTests.cs ├── Structurizr.Core ├── AbstractWorkspace.cs ├── AssemblyInfo.cs ├── Config │ ├── Role.cs │ ├── User.cs │ └── WorkspaceConfiguration.cs ├── Documentation │ ├── Arc42DocumentationTemplate.cs │ ├── Decision.cs │ ├── DecisionStatus.cs │ ├── Documentation.cs │ ├── DocumentationTemplate.cs │ ├── Format.cs │ ├── FormatFinder.cs │ ├── FormattedContent.cs │ ├── Image.cs │ ├── Section.cs │ ├── StructurizrDocumentationTemplate.cs │ └── ViewpointsAndPerspectivesDocumentationTemplate.cs ├── Model │ ├── AbstractImpliedRelationshipsStrategy.cs │ ├── CanonicalNameGenerator.cs │ ├── CodeElement.cs │ ├── CodeElementRole.cs │ ├── Component.cs │ ├── Container.cs │ ├── ContainerInstance.cs │ ├── CreateImpliedRelationshipsUnlessAnyRelationshipExistsStrategy.cs │ ├── CreateImpliedRelationshipsUnlessSameRelationshipExistsStrategy.cs │ ├── DefaultImpliedRelationshipsStrategy.cs │ ├── DeploymentElement.cs │ ├── DeploymentNode.cs │ ├── Element.cs │ ├── Enterprise.cs │ ├── GroupableElement.cs │ ├── HttpHealthCheck.cs │ ├── IdGenerator.cs │ ├── ImpliedRelationshipsStrategy.cs │ ├── InfrastructureNode.cs │ ├── InteractionStyle.cs │ ├── Location.cs │ ├── Model.cs │ ├── ModelItem.cs │ ├── Person.cs │ ├── Perspective.cs │ ├── Relationship.cs │ ├── SequentialIntegerIdGeneratorStrategy.cs │ ├── SoftwareSystem.cs │ ├── SoftwareSystemInstance.cs │ ├── StaticStructureElement.cs │ ├── StaticStructureElementInstance.cs │ └── Tags.cs ├── Structurizr.Core.csproj ├── Util │ ├── DictionaryUtils.cs │ ├── ImageUtils.cs │ └── Url.cs ├── View │ ├── Animation.cs │ ├── AutomaticLayout.cs │ ├── Border.cs │ ├── Branding.cs │ ├── Color.cs │ ├── ColorPair.cs │ ├── ComponentView.cs │ ├── ContainerView.cs │ ├── DefaultLayoutMergeStrategy.cs │ ├── DeploymentView.cs │ ├── Dimensions.cs │ ├── DynamicView.cs │ ├── ElementNotPermittedInViewException.cs │ ├── ElementStyle.cs │ ├── ElementView.cs │ ├── FilterMode.cs │ ├── FilteredView.cs │ ├── Font.cs │ ├── LayoutMergeStrategy.cs │ ├── MetadataSymbols.cs │ ├── PaperSize.cs │ ├── ParallelSequenceCounter.cs │ ├── RankDirection.cs │ ├── RelationshipStyle.cs │ ├── RelationshipView.cs │ ├── Routing.cs │ ├── SequenceCounter.cs │ ├── SequenceNumber.cs │ ├── Shape.cs │ ├── StaticView.cs │ ├── Styles.cs │ ├── SystemContextView.cs │ ├── SystemLandscapeView.cs │ ├── Terminology.cs │ ├── Vertex.cs │ ├── View.cs │ ├── ViewConfiguration.cs │ ├── ViewSet.cs │ └── ViewSortOrder.cs └── Workspace.cs ├── Structurizr.Examples ├── AmazonWebServicesExample.cs ├── Arc42DocumentationExample.cs ├── BigBankPlc.cs ├── ClientSideEncryption.cs ├── CorporateBranding.cs ├── Documentation │ ├── adr │ │ ├── 0001-record-architecture-decisions.md │ │ ├── 0002-implement-as-shell-scripts.md │ │ ├── 0003-single-command-with-subcommands.md │ │ ├── 0004-markdown-format.md │ │ ├── 0005-help-comments.md │ │ ├── 0006-packaging-and-distribution-in-other-version-control-repositories.md │ │ ├── 0007-invoke-adr-config-executable-to-get-configuration.md │ │ └── 0008-use-iso-8601-format-for-dates.md │ ├── arc42 │ │ ├── asciidoc │ │ │ ├── 01-introduction-and-goals.adoc │ │ │ ├── 02-architecture-constraints.adoc │ │ │ ├── 03-system-scope-and-context.adoc │ │ │ ├── 04-solution-strategy.adoc │ │ │ ├── 05-building-block-view.adoc │ │ │ ├── 06-runtime-view.adoc │ │ │ ├── 07-deployment-view.adoc │ │ │ ├── 08-crosscutting-concepts.adoc │ │ │ ├── 09-architecture-decisions.adoc │ │ │ ├── 10-quality-requirements.adoc │ │ │ ├── 11-risks-and-technical-debt.adoc │ │ │ └── 12-glossary.adoc │ │ └── markdown │ │ │ ├── 01-introduction-and-goals.md │ │ │ ├── 02-architecture-constraints.md │ │ │ ├── 03-system-scope-and-context.md │ │ │ ├── 04-solution-strategy.md │ │ │ ├── 05-building-block-view.md │ │ │ ├── 06-runtime-view.md │ │ │ ├── 07-deployment-view.md │ │ │ ├── 08-crosscutting-concepts.md │ │ │ ├── 09-architecture-decisions.md │ │ │ ├── 10-quality-requirements.md │ │ │ ├── 11-risks-and-technical-debt.md │ │ │ └── 12-glossary.md │ ├── structurizr │ │ ├── asciidoc │ │ │ ├── 01-context.adoc │ │ │ ├── 02-functional-overview.adoc │ │ │ ├── 03-quality-attributes.adoc │ │ │ ├── 04-constraints.adoc │ │ │ ├── 05-principles.adoc │ │ │ ├── 06-software-architecture.adoc │ │ │ ├── 07-data.adoc │ │ │ ├── 08-infrastructure-architecture.adoc │ │ │ ├── 09-deployment.adoc │ │ │ ├── 10-development-environment.adoc │ │ │ ├── 11-operation-and-support.adoc │ │ │ └── 12-decision-log.adoc │ │ └── markdown │ │ │ ├── 01-context.md │ │ │ ├── 02-functional-overview.md │ │ │ ├── 03-quality-attributes.md │ │ │ ├── 04-constraints.md │ │ │ ├── 05-principles.md │ │ │ ├── 06-software-architecture.md │ │ │ ├── 07-data.md │ │ │ ├── 08-infrastructure-architecture.md │ │ │ ├── 09-deployment.md │ │ │ ├── 10-development-environment.md │ │ │ ├── 11-operation-and-support.md │ │ │ └── 12-decision-log.md │ └── viewpointsandperspectives │ │ ├── asciidoc │ │ ├── 01-introduction.adoc │ │ ├── 02-glossary.adoc │ │ ├── 03-system-stakeholders-and-requirements.adoc │ │ ├── 04-architectural-forces.adoc │ │ ├── 05-architectural-views │ │ │ ├── 01-architectural-views.adoc │ │ │ ├── 02-context-view.adoc │ │ │ ├── 03-functional-view.adoc │ │ │ ├── 04-information-view.adoc │ │ │ ├── 05-concurrency-view.adoc │ │ │ ├── 06-deployment-view.adoc │ │ │ ├── 07-development-view.adoc │ │ │ └── 08-operational-view.adoc │ │ ├── 06-system-qualities.adoc │ │ └── 07-appendices.adoc │ │ └── markdown │ │ ├── 01-introduction.md │ │ ├── 02-glossary.md │ │ ├── 03-system-stakeholders-and-requirements.md │ │ ├── 04-architectural-forces.md │ │ ├── 05-architectural-views │ │ ├── 01-architectural-views.md │ │ ├── 02-context-view.md │ │ ├── 03-functional-view.md │ │ ├── 04-information-view.md │ │ ├── 05-concurrency-view.md │ │ ├── 06-deployment-view.md │ │ ├── 07-development-view.md │ │ └── 08-operational-view.md │ │ ├── 06-system-qualities.md │ │ └── 07-appendices.md ├── FilteredViews.cs ├── FinancialRiskSystem.cs ├── FinancialRiskSystem │ ├── context.adoc │ ├── context.md │ ├── functional-overview.md │ ├── images │ │ └── functional-overview.png │ └── quality-attributes.md ├── GettingStarted.cs ├── HttpHealthChecks.cs ├── MicroservicesExample.cs ├── Structurizr.Examples.csproj ├── StructurizrDocumentationExample.cs ├── StylingElements.cs ├── StylingRelationships.cs ├── Theme.cs ├── Theme │ └── theme.json ├── ViewpointsAndPerspectivesDocumentationExample.cs ├── WidgetsLimited.cs └── structurizr-logo.png ├── Structurizr.sln ├── appveyor.yml ├── docs ├── api-client.md ├── binaries.md ├── changelog.md ├── client-side-encryption.md ├── component-diagram.md ├── container-diagram.md ├── corporate-branding.md ├── deployment-diagram.md ├── documentation-arc42.md ├── documentation-structurizr.md ├── documentation-viewpoints-and-perspectives.md ├── documentation.md ├── dynamic-diagram.md ├── faq.md ├── filtered-views.md ├── getting-started.md ├── health-checks.md ├── images │ ├── basic-concepts.png │ ├── component-diagram-1.png │ ├── container-diagram-1.png │ ├── corporate-branding-1.png │ ├── corporate-branding-2.png │ ├── corporate-branding-3.png │ ├── corporate-branding-4.png │ ├── deployment-diagram-1.png │ ├── documentation-1.png │ ├── documentation-2.png │ ├── documentation-3.png │ ├── dynamic-diagram-1.png │ ├── filtered-views-1.png │ ├── filtered-views-2.png │ ├── getting-started-1.png │ ├── getting-started-2.png │ ├── getting-started-diagram-key.png │ ├── implied-relationships-1.png │ ├── readme-1.png │ ├── structurizr-banner.png │ ├── structurizr-overview.png │ ├── styling-elements-1.png │ ├── styling-elements-2.png │ ├── styling-elements-3.png │ ├── styling-elements-4.png │ ├── styling-elements-5.png │ ├── styling-elements-6.png │ ├── styling-relationships-1.png │ ├── styling-relationships-2.png │ ├── styling-relationships-3.png │ ├── styling-relationships-4.png │ ├── system-context-diagram-1.png │ └── system-landscape-diagram-1.png ├── implied-relationships.md ├── model.md ├── nuget.md ├── styling-elements.md ├── styling-relationships.md ├── system-context-diagram.md ├── system-landscape-diagram.md ├── usage-patterns.md └── views.md └── nuget.bat /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | #*.ts text 7 | 8 | # Shell scripts should always have lf line endings 9 | *.sh text eol=lf 10 | sources.list text eol=lf 11 | 12 | #### Visual Studio specific stuff 13 | 14 | ############################################################################### 15 | # Set default behavior for command prompt diff. 16 | # 17 | # This is need for earlier builds of msysgit that does not have it on by 18 | # default for csharp files. 19 | # Note: This is only used by command line 20 | ############################################################################### 21 | *.cs diff=csharp 22 | 23 | ############################################################################### 24 | # Set the merge driver for project and solution files 25 | # 26 | # Merging from the command prompt will add diff markers to the files if there 27 | # are conflicts (Merging from VS is not affected by the settings below, in VS 28 | # the diff markers are never inserted). Diff markers may cause the following 29 | # file extensions to fail to load in VS. An alternative would be to treat 30 | # these files as binary and thus will always conflict and require user 31 | # intervention with every merge. To do so, just comment the entries below and 32 | # uncomment the group further below 33 | ############################################################################### 34 | *.sln text eol=crlf 35 | *.csproj text eol=crlf 36 | *.vbproj text eol=crlf 37 | *.vcxproj text eol=crlf 38 | *.vcproj text eol=crlf 39 | *.dbproj text eol=crlf 40 | *.fsproj text eol=crlf 41 | *.lsproj text eol=crlf 42 | *.wixproj text eol=crlf 43 | *.modelproj text eol=crlf 44 | *.sqlproj text eol=crlf 45 | *.wmaproj text eol=crlf 46 | 47 | *.xproj text eol=crlf 48 | *.props text eol=crlf 49 | *.filters text eol=crlf 50 | *.vcxitems text eol=crlf 51 | 52 | *.sln merge=binary 53 | *.csproj merge=binary 54 | *.vbproj merge=binary 55 | *.vcxproj merge=binary 56 | *.vcproj merge=binary 57 | *.dbproj merge=binary 58 | *.fsproj merge=binary 59 | *.lsproj merge=binary 60 | *.wixproj merge=binary 61 | *.modelproj merge=binary 62 | *.sqlproj merge=binary 63 | *.wmaproj merge=binary 64 | 65 | *.xproj merge=binary 66 | *.props merge=binary 67 | *.filters merge=binary 68 | *.vcxitems merge=binary 69 | 70 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | solution: Structurizr.sln 3 | -------------------------------------------------------------------------------- /Structurizr.Client.Tests/Api/Md5DigestTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Api.Tests 4 | { 5 | 6 | public class Md5DigestTests 7 | { 8 | 9 | private Md5Digest md5 = new Md5Digest(); 10 | 11 | [Fact] 12 | public void Test_Generate_TreatsNullAsEmptyContent() 13 | { 14 | Assert.Equal(md5.Generate(""), md5.Generate(null)); 15 | } 16 | 17 | [Fact] 18 | public void Test_Generate_WorksForUTF8CharacterEncoding() 19 | { 20 | Assert.Equal("0a35e149dbbb2d10d744bf675c7744b1", md5.Generate("è")); 21 | } 22 | 23 | [Fact] 24 | public void Test_Generate() 25 | { 26 | Assert.Equal("ed076287532e86365e841e92bfc50d8c", md5.Generate("Hello World!")); 27 | Assert.Equal("d41d8cd98f00b204e9800998ecf8427e", md5.Generate("")); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Structurizr.Client.Tests/Encryption/MockEncryptionStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Structurizr.Encryption; 3 | 4 | namespace Structurizr.Api.Encryption.Tests 5 | { 6 | internal class MockEncryptionStrategy : EncryptionStrategy 7 | { 8 | public override string Type { get; } 9 | 10 | public override string Encrypt(string plaintext) 11 | { 12 | var array = plaintext.ToCharArray(); 13 | Array.Reverse(array); 14 | return new string(array); 15 | } 16 | 17 | public override string Decrypt(string ciphertext) 18 | { 19 | var array = ciphertext.ToCharArray(); 20 | Array.Reverse(array); 21 | return new string(array); 22 | } 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /Structurizr.Client.Tests/Structurizr.Client.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp3.1 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Structurizr.Client.Tests/TestFailedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Structurizr.Api.Tests 4 | { 5 | public class TestFailedException : Exception 6 | { 7 | 8 | public TestFailedException() 9 | { 10 | } 11 | 12 | public TestFailedException(string message) : base(message) 13 | { 14 | } 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /Structurizr.Client/Api/ApiResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System.Collections.Generic; 4 | using System.Runtime.Serialization; 5 | 6 | namespace Structurizr.Api 7 | { 8 | 9 | [DataContract] 10 | internal sealed class ApiResponse 11 | { 12 | 13 | [DataMember(Name = "success", EmitDefaultValue = false)] 14 | internal bool Success; 15 | 16 | [DataMember(Name = "message", EmitDefaultValue = false)] 17 | internal string Message; 18 | 19 | [DataMember(Name = "revision", EmitDefaultValue = false)] 20 | internal long? Revision; 21 | 22 | static internal ApiResponse Parse(string json) 23 | { 24 | JsonSerializerSettings settings = new JsonSerializerSettings() 25 | { 26 | ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 27 | Converters = new List { 28 | new IsoDateTimeConverter() 29 | } 30 | }; 31 | 32 | ApiResponse apiResponse = JsonConvert.DeserializeObject(json, settings); 33 | return apiResponse; 34 | } 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /Structurizr.Client/Api/HashBasedMessageAuthenticationCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace Structurizr.Api 6 | { 7 | internal class HashBasedMessageAuthenticationCode 8 | { 9 | 10 | private string apiSecret; 11 | 12 | internal HashBasedMessageAuthenticationCode(string apiSecret) 13 | { 14 | this.apiSecret = apiSecret; 15 | } 16 | 17 | public string Generate(string content) 18 | { 19 | HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)); 20 | byte[] bytes = Encoding.UTF8.GetBytes(content); 21 | byte[] hash = hmac.ComputeHash(bytes); 22 | 23 | return BitConverter.ToString(hash).Replace("-", "").ToLower(); 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Structurizr.Client/Api/HmacAuthorizationHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Structurizr.Api 5 | { 6 | internal class HmacAuthorizationHeader 7 | { 8 | 9 | private string apiKey; 10 | private string hmac; 11 | 12 | public HmacAuthorizationHeader(string apiKey, string hmac) 13 | { 14 | this.apiKey = apiKey; 15 | this.hmac = hmac; 16 | } 17 | 18 | public override string ToString() 19 | { 20 | return apiKey + ":" + Convert.ToBase64String(Encoding.UTF8.GetBytes(hmac)); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Structurizr.Client/Api/HmacContent.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Structurizr.Api 4 | { 5 | internal class HmacContent 6 | { 7 | 8 | private string[] strings; 9 | 10 | internal HmacContent(params string[] strings) 11 | { 12 | this.strings = strings; 13 | } 14 | 15 | public override string ToString() 16 | { 17 | StringBuilder buf = new StringBuilder(); 18 | foreach (string s in strings) 19 | { 20 | buf.Append(s); 21 | buf.Append("\n"); 22 | } 23 | 24 | return buf.ToString(); 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Structurizr.Client/Api/HttpHeaders.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Api 2 | { 3 | internal class HttpHeaders 4 | { 5 | 6 | internal const string UserAgent = "User-Agent"; 7 | internal const string Authorization = "Authorization"; 8 | internal const string XAuthorization = "X-Authorization"; 9 | internal const string ContentType = "Content-Type"; 10 | internal const string ContentMd5 = "Content-MD5"; 11 | internal const string Nonce = "Nonce"; 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Structurizr.Client/Api/Md5Digest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace Structurizr.Api 6 | { 7 | internal class Md5Digest 8 | { 9 | 10 | internal string Generate(string content) 11 | { 12 | if (content == null) 13 | { 14 | content = ""; 15 | } 16 | 17 | MD5 md5 = MD5.Create(); 18 | byte[] textToHash = Encoding.UTF8.GetBytes(content); 19 | byte[] result = md5.ComputeHash(textToHash); 20 | 21 | return BitConverter.ToString(result).Replace("-", "").ToLower(); 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Structurizr.Client/Api/StructurizrClientException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Structurizr.Api 4 | { 5 | public class StructurizrClientException : Exception 6 | { 7 | 8 | public StructurizrClientException(String message) : base(message) { } 9 | 10 | public StructurizrClientException(String message, Exception innerException) : base(message, innerException) { } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Structurizr.Client/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Structurizr.Client.Tests")] 2 | 3 | namespace Structurizr.Api 4 | { 5 | public class AssemblyInfo 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /Structurizr.Client/Encryption/EncryptedJsonReader.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Structurizr.IO.Json; 3 | using System.IO; 4 | 5 | namespace Structurizr.Encryption 6 | { 7 | public class EncryptedJsonReader 8 | { 9 | 10 | public EncryptedWorkspace Read(StringReader reader) 11 | { 12 | EncryptedWorkspace workspace = JsonConvert.DeserializeObject( 13 | reader.ReadToEnd(), 14 | new Newtonsoft.Json.Converters.StringEnumConverter(), 15 | new PaperSizeJsonConverter(), 16 | new EncryptionStrategyJsonConverter()); 17 | 18 | return workspace; 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Structurizr.Client/Encryption/EncryptedJsonWriter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Structurizr.IO.Json; 3 | using System.IO; 4 | 5 | namespace Structurizr.Encryption 6 | { 7 | public class EncryptedJsonWriter 8 | { 9 | 10 | public bool IndentOutput { get; set; } 11 | 12 | public EncryptedJsonWriter(bool indentOutput) 13 | { 14 | this.IndentOutput = indentOutput; 15 | } 16 | 17 | public void Write(EncryptedWorkspace workspace, StringWriter writer) 18 | { 19 | string json = JsonConvert.SerializeObject(workspace, 20 | IndentOutput == true ? Formatting.Indented : Formatting.None, 21 | new Newtonsoft.Json.Converters.StringEnumConverter(), 22 | new PaperSizeJsonConverter()); 23 | 24 | writer.WriteLine(json); 25 | } 26 | 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Structurizr.Client/Encryption/EncryptedWorkspace.cs: -------------------------------------------------------------------------------- 1 | using Structurizr.IO.Json; 2 | using System.IO; 3 | using System.Runtime.Serialization; 4 | 5 | namespace Structurizr.Encryption 6 | { 7 | 8 | [DataContract] 9 | public class EncryptedWorkspace : AbstractWorkspace 10 | { 11 | 12 | private Workspace _workspace; 13 | public Workspace Workspace 14 | { 15 | get 16 | { 17 | if (_workspace != null) 18 | { 19 | return _workspace; 20 | } 21 | else if (Ciphertext != null) 22 | { 23 | Plaintext = EncryptionStrategy.Decrypt(Ciphertext); 24 | StringReader stringReader = new StringReader(Plaintext); 25 | return new JsonReader().Read(stringReader); 26 | } 27 | else 28 | { 29 | return null; 30 | } 31 | } 32 | 33 | set 34 | { 35 | _workspace = value; 36 | } 37 | } 38 | 39 | [DataMember(Name = "encryptionStrategy", EmitDefaultValue = false)] 40 | public EncryptionStrategy EncryptionStrategy { get; internal set; } 41 | 42 | internal string Plaintext { get; set; } 43 | 44 | [DataMember(Name = "ciphertext", EmitDefaultValue = false)] 45 | public string Ciphertext { get; internal set; } 46 | 47 | public EncryptedWorkspace() { } 48 | 49 | public EncryptedWorkspace(Workspace workspace, EncryptionStrategy encryptionStrategy) 50 | { 51 | Workspace = workspace; 52 | EncryptionStrategy = encryptionStrategy; 53 | 54 | Configuration = workspace.Configuration; 55 | workspace.ClearConfiguration(); 56 | 57 | StringWriter stringWriter = new StringWriter(); 58 | JsonWriter jsonWriter = new JsonWriter(false); 59 | jsonWriter.Write(workspace, stringWriter); 60 | 61 | Id = workspace.Id; 62 | Name = workspace.Name; 63 | Description = workspace.Description; 64 | Version = workspace.Version; 65 | Revision = workspace.Revision; 66 | LastModifiedAgent = workspace.LastModifiedAgent; 67 | LastModifiedUser = workspace.LastModifiedUser; 68 | Thumbnail = workspace.Thumbnail; 69 | 70 | Plaintext = stringWriter.ToString(); 71 | Ciphertext = encryptionStrategy.Encrypt(Plaintext); 72 | } 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Structurizr.Client/Encryption/EncryptionStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace Structurizr.Encryption 4 | { 5 | 6 | [DataContract] 7 | public abstract class EncryptionStrategy 8 | { 9 | 10 | [DataMember(Name = "type", EmitDefaultValue = false)] 11 | public abstract string Type { get; } 12 | 13 | public string Passphrase { get; set; } 14 | 15 | [DataMember(Name = "location", EmitDefaultValue = false)] 16 | public string Location 17 | { 18 | get 19 | { 20 | return "Client"; 21 | } 22 | } 23 | 24 | public EncryptionStrategy() { } 25 | 26 | public EncryptionStrategy(string passphrase) 27 | { 28 | this.Passphrase = passphrase; 29 | } 30 | 31 | public abstract string Encrypt(string plaintext); 32 | public abstract string Decrypt(string ciphertext); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Structurizr.Client/IO/Json/EncryptionStrategyJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using Structurizr.Encryption; 4 | using System; 5 | using System.Reflection; 6 | 7 | namespace Structurizr.IO.Json 8 | { 9 | internal class EncryptionStrategyJsonConverter : JsonConverter 10 | { 11 | public override bool CanConvert(Type objectType) 12 | { 13 | return typeof(EncryptionStrategy).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); 14 | } 15 | 16 | public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 17 | { 18 | JObject item = JObject.Load(reader); 19 | string type = item["type"].Value(); 20 | if (type == "aes") 21 | { 22 | return item.ToObject(); 23 | } 24 | else 25 | { 26 | throw new NotSupportedException("The encryption strategy type of " + type + " is not supported"); 27 | } 28 | } 29 | 30 | public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, JsonSerializer serializer) 31 | { 32 | throw new NotImplementedException("This operation is not implemented"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Structurizr.Client/IO/Json/JsonReader.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using Newtonsoft.Json.Converters; 5 | 6 | namespace Structurizr.IO.Json 7 | { 8 | public class JsonReader 9 | { 10 | 11 | public IdGenerator IdGenerator; 12 | 13 | public Workspace Read(StringReader reader) 14 | { 15 | JsonSerializerSettings settings = new JsonSerializerSettings() 16 | { 17 | ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 18 | Converters = new List { 19 | new StringEnumConverter(), 20 | new IsoDateTimeConverter(), 21 | new PaperSizeJsonConverter() 22 | }, 23 | ObjectCreationHandling = ObjectCreationHandling.Replace 24 | }; 25 | 26 | Workspace workspace = JsonConvert.DeserializeObject(reader.ReadToEnd(), settings); 27 | 28 | if (IdGenerator != null) { 29 | workspace.Model.IdGenerator = IdGenerator; 30 | } 31 | 32 | workspace.Hydrate(); 33 | 34 | return workspace; 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Structurizr.Client/IO/Json/JsonWriter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | using Newtonsoft.Json.Converters; 4 | 5 | namespace Structurizr.IO.Json 6 | { 7 | public class JsonWriter 8 | { 9 | 10 | public bool IndentOutput { get; set; } 11 | 12 | public JsonWriter(bool indentOutput) 13 | { 14 | this.IndentOutput = indentOutput; 15 | } 16 | 17 | public void Write(Workspace workspace, TextWriter writer) 18 | { 19 | string json = JsonConvert.SerializeObject(workspace, 20 | IndentOutput ? Formatting.Indented : Formatting.None, 21 | new StringEnumConverter(), 22 | new IsoDateTimeConverter(), 23 | new PaperSizeJsonConverter()); 24 | 25 | writer.Write(json); 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Structurizr.Client/IO/Json/PaperSizeJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Reflection; 4 | 5 | namespace Structurizr.IO.Json 6 | { 7 | internal class PaperSizeJsonConverter : JsonConverter 8 | { 9 | public override bool CanConvert(Type objectType) 10 | { 11 | return typeof(PaperSize).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); 12 | } 13 | 14 | public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 15 | { 16 | return PaperSize.GetPaperSize(reader.Value as string); 17 | } 18 | 19 | public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, JsonSerializer serializer) 20 | { 21 | PaperSize paperSize = value as PaperSize; 22 | if (paperSize != null) 23 | { 24 | writer.WriteValue(paperSize.Key); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Structurizr.Client/Structurizr.Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 1.1.1 7 | true 8 | 9 | 10 | 11 | The API client for publishing models on the Structurizr cloud service and on-premises installation. 12 | Structurizr Limited 13 | Copyright 2017-2023 14 | https://opensource.org/licenses/Apache-2.0 15 | https://structurizr.com 16 | https://github.com/structurizr/dotnet 17 | 18 | 19 | 20 | netstandard2.0 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Structurizr.Client/Util/WorkspaceUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using Structurizr.IO.Json; 5 | 6 | namespace Structurizr 7 | { 8 | 9 | public class WorkspaceUtils 10 | { 11 | 12 | /// 13 | /// Loads a workspace from a JSON definition saved as a file 14 | /// 15 | /// a FileInfo object representing the location of the JSON definition 16 | /// a Workspace object 17 | public static Workspace LoadWorkspaceFromJson(FileInfo file) 18 | { 19 | if (file == null) { 20 | throw new ArgumentException("The path to a JSON file must be specified."); 21 | } 22 | 23 | if (!file.Exists) { 24 | throw new ArgumentException("The specified JSON file does not exist."); 25 | } 26 | 27 | string content = File.ReadAllText(file.FullName, Encoding.UTF8); 28 | 29 | return new JsonReader().Read(new StringReader(content)); 30 | } 31 | 32 | /// 33 | /// Saves a workspace to a JSON definition as a file. 34 | /// 35 | /// a FileInfo object representing the location of the file to write the JSON definition 36 | public static void SaveWorkspaceToJson(Workspace workspace, FileInfo file) 37 | { 38 | if (workspace == null) { 39 | throw new ArgumentException("A workspace must be provided."); 40 | } 41 | 42 | if (file == null) { 43 | throw new ArgumentException("The path to a JSON file must be specified."); 44 | } 45 | 46 | using (StreamWriter writer = new StreamWriter(new FileStream(file.FullName, FileMode.Create))) 47 | { 48 | new JsonWriter(true).Write(workspace, writer); 49 | } 50 | } 51 | 52 | /// 53 | /// Prints the given workspace as an indented JSON document. 54 | /// 55 | /// the Workspace object to be printed 56 | public static void PrintWorkspaceAsJson(Workspace workspace) 57 | { 58 | JsonWriter jsonWriter = new JsonWriter(true); 59 | StringWriter stringWriter = new StringWriter(); 60 | jsonWriter.Write(workspace, stringWriter); 61 | Console.WriteLine(stringWriter.ToString()); 62 | } 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/AbstractTestBase.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Core.Tests 2 | { 3 | public abstract class AbstractTestBase 4 | { 5 | 6 | protected Workspace Workspace; 7 | protected Model Model; 8 | protected ViewSet Views; 9 | 10 | public AbstractTestBase() 11 | { 12 | Workspace = new Workspace("Name", "Description"); 13 | Model = Workspace.Model; 14 | Views = Workspace.Views; 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Config/WorkspaceConfigurationTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Structurizr.Config; 4 | using Xunit; 5 | 6 | namespace Structurizr.Core.Tests.Configuration 7 | { 8 | public class ConfigurationTests 9 | { 10 | 11 | [Fact] 12 | public void Test_AddUser_ThrowsAnException_WhenANullUsernameIsSpecified() 13 | { 14 | try 15 | { 16 | WorkspaceConfiguration configuration = new WorkspaceConfiguration(); 17 | configuration.AddUser(null, Role.ReadWrite); 18 | throw new TestFailedException(); 19 | } 20 | catch (ArgumentException iae) 21 | { 22 | Assert.Equal("A username must be specified.", iae.Message); 23 | } 24 | } 25 | 26 | [Fact] 27 | public void Test_AddUser_ThrowsAnException_WhenAnEmptyUsernameIsSpecified() 28 | { 29 | try 30 | { 31 | WorkspaceConfiguration configuration = new WorkspaceConfiguration(); 32 | configuration.AddUser(" ", Role.ReadWrite); 33 | throw new TestFailedException(); 34 | } 35 | catch (ArgumentException iae) 36 | { 37 | Assert.Equal("A username must be specified.", iae.Message); 38 | } 39 | } 40 | 41 | [Fact] 42 | public void Test_AddUser_AddsAUser() 43 | { 44 | WorkspaceConfiguration configuration = new WorkspaceConfiguration(); 45 | configuration.AddUser("user@domain.com", Role.ReadOnly); 46 | 47 | Assert.Equal(1, configuration.Users.Count); 48 | Assert.Equal("user@domain.com", configuration.Users.First().Username); 49 | Assert.Equal(Role.ReadOnly, configuration.Users.First().Role); 50 | } 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/FormatFinderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Structurizr.Documentation; 4 | using Xunit; 5 | 6 | namespace Structurizr.Core.Tests.Documentation 7 | { 8 | 9 | public class FormatFinderTests 10 | { 11 | 12 | [Fact] 13 | public void Test_FindFormat_ThrowsAnException_WhenAFileIsNotSpecified() { 14 | try { 15 | FormatFinder.FindFormat(null); 16 | throw new TestFailedException(); 17 | } catch (ArgumentException iae) { 18 | Assert.Equal("A file must be specified.", iae.Message); 19 | } 20 | } 21 | 22 | [Fact] 23 | public void Test_FindFormat_ReturnsMarkdown_WhenAMarkdownFileIsSpecified() { 24 | Assert.Equal(Format.Markdown, FormatFinder.FindFormat(new FileInfo("foo.md"))); 25 | Assert.Equal(Format.Markdown, FormatFinder.FindFormat(new FileInfo("foo.markdown"))); 26 | Assert.Equal(Format.Markdown, FormatFinder.FindFormat(new FileInfo("foo.text"))); 27 | } 28 | 29 | [Fact] 30 | public void Test_FindFormat_ReturnsAsciiDoc_WhenAnAsciiDocFileIsSpecified() { 31 | Assert.Equal(Format.AsciiDoc, FormatFinder.FindFormat(new FileInfo("foo.adoc"))); 32 | Assert.Equal(Format.AsciiDoc, FormatFinder.FindFormat(new FileInfo("foo.asciidoc"))); 33 | Assert.Equal(Format.AsciiDoc, FormatFinder.FindFormat(new FileInfo("foo.asc"))); 34 | } 35 | 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/SectionTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Documentation.Tests 4 | { 5 | public class SectionTests 6 | { 7 | 8 | [Fact] 9 | public void Test_SetType_ProvidesBackwardsCompatibility() 10 | { 11 | Section section = new Section(); 12 | section.SectionType = "Title"; // older clients use the type property 13 | Assert.Equal("Title", section.Title); 14 | } 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/architectural-decisions.md: -------------------------------------------------------------------------------- 1 | Section 9 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/building-block-view.md: -------------------------------------------------------------------------------- 1 | Section 5 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/constraints.md: -------------------------------------------------------------------------------- 1 | Section 2 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/context-and-scope.md: -------------------------------------------------------------------------------- 1 | Section 3 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/crosscutting-concepts.md: -------------------------------------------------------------------------------- 1 | Section 8 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/deployment-view.md: -------------------------------------------------------------------------------- 1 | Section 7 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/glossary.md: -------------------------------------------------------------------------------- 1 | Section 12 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/introduction-and-goals.md: -------------------------------------------------------------------------------- 1 | Section 1 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/quality-requirements.md: -------------------------------------------------------------------------------- 1 | Section 10 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/risks-and-technical-debt.md: -------------------------------------------------------------------------------- 1 | Section 11 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/runtime-view.md: -------------------------------------------------------------------------------- 1 | Section 6 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/arc42/solution-strategy.md: -------------------------------------------------------------------------------- 1 | Section 4 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/example.md: -------------------------------------------------------------------------------- 1 | ## Heading 2 | 3 | Here is a paragraph. -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/image.gif -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/image.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/image.jpeg -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/image.jpg -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/image.png -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/images/image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/images/image.gif -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/images/image.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/images/image.jpeg -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/images/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/images/image.jpg -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/images/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Documentation/images/image.png -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/markdown/1.md: -------------------------------------------------------------------------------- 1 | File 1 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/markdown/subdirectory/2.md: -------------------------------------------------------------------------------- 1 | File 2 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/noimages/readme.md: -------------------------------------------------------------------------------- 1 | There are no images in this directory. -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/code-for-componentA1.md: -------------------------------------------------------------------------------- 1 | Code section for component A1 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/code-for-componentA2.md: -------------------------------------------------------------------------------- 1 | Code section for component A2 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/components-for-containerA.md: -------------------------------------------------------------------------------- 1 | Components section for container A -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/components-for-containerB.md: -------------------------------------------------------------------------------- 1 | Components section for container B -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/constraints.md: -------------------------------------------------------------------------------- 1 | Constraints section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/containers.md: -------------------------------------------------------------------------------- 1 | Containers section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/context.md: -------------------------------------------------------------------------------- 1 | Context section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/data.md: -------------------------------------------------------------------------------- 1 | Data section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/decision-log.md: -------------------------------------------------------------------------------- 1 | Decision log section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/deployment.md: -------------------------------------------------------------------------------- 1 | Deployment section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/development-environment.md: -------------------------------------------------------------------------------- 1 | Development environment section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/functional-overview.md: -------------------------------------------------------------------------------- 1 | Functional overview section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/infrastructure-architecture.md: -------------------------------------------------------------------------------- 1 | Infrastructure architecture section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/operation-and-support.md: -------------------------------------------------------------------------------- 1 | Operation and support section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/principles.md: -------------------------------------------------------------------------------- 1 | Principles section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/quality-attributes.md: -------------------------------------------------------------------------------- 1 | Quality attributes section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/structurizr/software-architecture.md: -------------------------------------------------------------------------------- 1 | Software architecture section -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/01-introduction.md: -------------------------------------------------------------------------------- 1 | Section 1 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/02-glossary.md: -------------------------------------------------------------------------------- 1 | Section 2 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/03-system-stakeholders-and-requirements.md: -------------------------------------------------------------------------------- 1 | Section 3 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/04-architectural-forces.md: -------------------------------------------------------------------------------- 1 | Section 4 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/05-architectural-views.md: -------------------------------------------------------------------------------- 1 | Section 5 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/06-system-qualities.md: -------------------------------------------------------------------------------- 1 | Section 6 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Documentation/viewpointsandperspectives/07-appendices.adoc: -------------------------------------------------------------------------------- 1 | Section 7 -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Model/CodeElementTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests 5 | { 6 | 7 | 8 | public class CodeElementTests 9 | { 10 | 11 | private readonly CodeElement _codeElement = new CodeElement("Wibble.Wobble, Foo.Bar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xyz"); 12 | 13 | [Fact] 14 | public void Test_Construction_WhenAFullyQualifiedTypeIsSpecified() 15 | { 16 | Assert.Equal("Wobble", _codeElement.Name); 17 | } 18 | 19 | [Fact] 20 | public void Test_SetUrl_DoesNotThrowAnException_WhenANullUrlIsSpecified() 21 | { 22 | _codeElement.Url = null; 23 | } 24 | 25 | [Fact] 26 | public void Test_SetUrl_DoesNotThrowAnException_WhenAnEmptyUrlIsSpecified() 27 | { 28 | _codeElement.Url = ""; 29 | } 30 | 31 | [Fact] 32 | public void Test_SetUrl_ThrowsAnException_WhenAnInvalidUrlIsSpecified() 33 | { 34 | try 35 | { 36 | _codeElement.Url = "www.somedomain.com"; 37 | throw new TestFailedException(); 38 | } 39 | catch (Exception e) 40 | { 41 | Assert.Equal("www.somedomain.com is not a valid URL.", e.Message); 42 | } 43 | } 44 | 45 | [Fact] 46 | public void Test_SetUrl_DoesNotThrowAnException_WhenAValidUrlIsSpecified() 47 | { 48 | _codeElement.Url = "http://www.somedomain.com"; 49 | Assert.Equal("http://www.somedomain.com", _codeElement.Url); 50 | } 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Model/ComponentTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | 6 | public class ComponentTests 7 | { 8 | 9 | private Workspace workspace; 10 | private Model model; 11 | private SoftwareSystem softwareSystem; 12 | private Container container; 13 | 14 | public ComponentTests() 15 | { 16 | workspace = new Workspace("Name", "Description"); 17 | model = workspace.Model; 18 | softwareSystem = model.AddSoftwareSystem("System", "Description"); 19 | container = softwareSystem.AddContainer("Container", "Description", "Some technology"); 20 | } 21 | 22 | [Fact] 23 | public void Test_Name_ReturnsTheGivenName_WhenANameIsGiven() 24 | { 25 | Component component = new Component(); 26 | component.Name = "Some name"; 27 | Assert.Equal("Some name", component.Name); 28 | } 29 | 30 | [Fact] 31 | public void Test_CanonicalName() 32 | { 33 | Component component = container.AddComponent("Component", "Description"); 34 | Assert.Equal("Component://System.Container.Component", component.CanonicalName); 35 | } 36 | 37 | [Fact] 38 | public void Test_CanonicalName_WhenNameContainsASlashCharacter() 39 | { 40 | Component component = container.AddComponent("Name1/Name2", "Description"); 41 | Assert.Equal("Component://System.Container.Name1Name2", component.CanonicalName); 42 | } 43 | 44 | [Fact] 45 | public void Test_Parent_ReturnsTheParentContainer() 46 | { 47 | Component component = container.AddComponent("Component", "Description"); 48 | Assert.Equal(container, component.Parent); 49 | } 50 | 51 | [Fact] 52 | public void Test_Container_ReturnsTheParentContainer() 53 | { 54 | Component component = container.AddComponent("Name", "Description"); 55 | Assert.Equal(container, component.Container); 56 | } 57 | 58 | [Fact] 59 | public void Test_RemoveTags_DoesNotRemoveRequiredTags() 60 | { 61 | Component component = new Component(); 62 | Assert.True(component.Tags.Contains(Tags.Element)); 63 | Assert.True(component.Tags.Contains(Tags.Component)); 64 | 65 | component.RemoveTag(Tags.Component); 66 | component.RemoveTag(Tags.Element); 67 | 68 | Assert.True(component.Tags.Contains(Tags.Element)); 69 | Assert.True(component.Tags.Contains(Tags.Component)); 70 | } 71 | 72 | } 73 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Model/ContainerTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | 6 | public class ContainerTests 7 | { 8 | 9 | private Workspace workspace; 10 | private Model model; 11 | private SoftwareSystem softwareSystem; 12 | private Container container; 13 | 14 | public ContainerTests() 15 | { 16 | workspace = new Workspace("Name", "Description"); 17 | model = workspace.Model; 18 | softwareSystem = model.AddSoftwareSystem("System", "Description"); 19 | container = softwareSystem.AddContainer("Container", "Description", "Some technology"); 20 | } 21 | 22 | [Fact] 23 | public void Test_CanonicalName() 24 | { 25 | Assert.Equal("Container://System.Container", container.CanonicalName); 26 | } 27 | 28 | [Fact] 29 | public void Test_CanonicalName_WhenNameContainsASlashCharacter() 30 | { 31 | container.Name = "Name1/Name2"; 32 | Assert.Equal("Container://System.Name1Name2", container.CanonicalName); 33 | } 34 | 35 | [Fact] 36 | public void Test_Parent_ReturnsTheParentSoftwareSystem() 37 | { 38 | Assert.Equal(softwareSystem, container.Parent); 39 | } 40 | 41 | [Fact] 42 | public void Test_SoftwareSystem_ReturnsTheParentSoftwareSystem() 43 | { 44 | Assert.Equal(softwareSystem, container.SoftwareSystem); 45 | } 46 | 47 | [Fact] 48 | public void Test_RemoveTags_DoesNotRemoveRequiredTags() 49 | { 50 | Assert.True(container.Tags.Contains(Tags.Element)); 51 | Assert.True(container.Tags.Contains(Tags.Container)); 52 | 53 | container.RemoveTag(Tags.Container); 54 | container.RemoveTag(Tags.Element); 55 | 56 | Assert.True(container.Tags.Contains(Tags.Element)); 57 | Assert.True(container.Tags.Contains(Tags.Container)); 58 | } 59 | 60 | } 61 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Model/GroupableElementTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | 6 | public class GroupableElementTests : AbstractTestBase 7 | { 8 | 9 | [Fact] 10 | public void Test_getGroup_ReturnsNullByDefault() 11 | { 12 | Person element = Model.AddPerson("Person"); 13 | Assert.Null(element.Group); 14 | } 15 | 16 | [Fact] 17 | public void Test_setGroup() 18 | { 19 | Person element = Model.AddPerson("Person"); 20 | element.Group = "Group"; 21 | Assert.Equal("Group", element.Group); 22 | } 23 | 24 | [Fact] 25 | public void Test_setGroup_TrimsWhiteSpace() 26 | { 27 | Person element = Model.AddPerson("Person"); 28 | element.Group = " Group "; 29 | Assert.Equal("Group", element.Group); 30 | } 31 | 32 | [Fact] 33 | public void Test_setGroup_HandlesEmptyAndNullValues() 34 | { 35 | Person element = Model.AddPerson("Person"); 36 | element.Group = "Group"; 37 | 38 | element.Group = null; 39 | Assert.Null(element.Group); 40 | 41 | element.Group = "Group"; 42 | element.Group = ""; 43 | Assert.Null(element.Group); 44 | 45 | element.Group = "Group"; 46 | element.Group = " "; 47 | Assert.Null(element.Group); 48 | } 49 | 50 | } 51 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Model/PersonTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | 6 | public class PersonTests 7 | { 8 | 9 | private Workspace workspace; 10 | private Model model; 11 | private Person person; 12 | 13 | public PersonTests() 14 | { 15 | workspace = new Workspace("Name", "Description"); 16 | model = workspace.Model; 17 | person = model.AddPerson("Name", "Description"); 18 | } 19 | 20 | [Fact] 21 | public void Test_CanonicalName() 22 | { 23 | Assert.Equal("Person://Name", person.CanonicalName); 24 | } 25 | 26 | [Fact] 27 | public void Test_CanonicalName_WhenNameContainsASlashCharacter() 28 | { 29 | person.Name = "Name1/Name2"; 30 | Assert.Equal("Person://Name1Name2", person.CanonicalName); 31 | } 32 | 33 | [Fact] 34 | public void Test_Parent_ReturnsNull() 35 | { 36 | Assert.Null(person.Parent); 37 | } 38 | 39 | [Fact] 40 | public void Test_RemoveTags_DoesNotRemoveRequiredTags() 41 | { 42 | Assert.True(person.Tags.Contains(Tags.Element)); 43 | Assert.True(person.Tags.Contains(Tags.Person)); 44 | 45 | person.RemoveTag(Tags.Person); 46 | person.RemoveTag(Tags.Element); 47 | 48 | Assert.True(person.Tags.Contains(Tags.Element)); 49 | Assert.True(person.Tags.Contains(Tags.Person)); 50 | } 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/TestFailedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | public class TestFailedException : Exception 6 | { 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Util/UrlTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | using Structurizr.Util; 8 | 9 | namespace Structurizr.Core.Tests 10 | { 11 | 12 | 13 | public class UrlTests 14 | { 15 | 16 | [Fact] 17 | public void test_IsUrl_ReturnsFalse_WhenPassedNull() 18 | { 19 | Assert.False(Url.IsUrl(null)); 20 | } 21 | 22 | [Fact] 23 | public void test_IsUrl_ReturnsFalse_WhenPassedAnEmptyString() 24 | { 25 | Assert.False(Url.IsUrl("")); 26 | Assert.False(Url.IsUrl(" ")); 27 | } 28 | 29 | [Fact] 30 | public void test_IsUrl_ReturnsFalse_WhenPassedAnInvalidUrl() 31 | { 32 | Assert.False(Url.IsUrl("www.google.com")); 33 | } 34 | 35 | [Fact] 36 | public void test_IsUrl_ReturnsTrue_WhenPassedAValidUrl() 37 | { 38 | Assert.True(Url.IsUrl("https://www.google.com")); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Util/readme.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Structurizr.Core.Tests/Util/structurizr-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Core.Tests/Util/structurizr-logo.png -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/AutomaticLayoutTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests.View 5 | { 6 | public class AutomaticLayoutTests 7 | { 8 | [Fact] 9 | public void Test_AutomaticLayout() 10 | { 11 | AutomaticLayout automaticLayout = new AutomaticLayout(RankDirection.LeftRight, 100, 200, 300, true); 12 | 13 | Assert.Equal(RankDirection.LeftRight, automaticLayout.RankDirection); 14 | Assert.Equal(100, automaticLayout.RankSeparation); 15 | Assert.Equal(200, automaticLayout.NodeSeparation); 16 | Assert.Equal(300, automaticLayout.EdgeSeparation); 17 | Assert.True(automaticLayout.Vertices); 18 | } 19 | 20 | [Fact] 21 | public void Test_RankSeparation_ThrowsAnException_WhenANegativeIntegerIsSpecified() 22 | { 23 | try 24 | { 25 | AutomaticLayout automaticLayout = new AutomaticLayout(); 26 | automaticLayout.RankSeparation = -100; 27 | throw new TestFailedException(); 28 | } 29 | catch (ArgumentException iae) 30 | { 31 | Assert.Equal("The rank separation must be a positive integer.", iae.Message); 32 | } 33 | } 34 | 35 | [Fact] 36 | public void Test_NodeSeparation_ThrowsAnException_WhenANegativeIntegerIsSpecified() 37 | { 38 | try 39 | { 40 | AutomaticLayout automaticLayout = new AutomaticLayout(); 41 | automaticLayout.NodeSeparation = -100; 42 | throw new TestFailedException(); 43 | } 44 | catch (ArgumentException iae) 45 | { 46 | Assert.Equal("The node separation must be a positive integer.", iae.Message); 47 | } 48 | } 49 | 50 | [Fact] 51 | public void Test_EdgeSeparation_ThrowsAnException_WhenANegativeIntegerIsSpecified() 52 | { 53 | try 54 | { 55 | AutomaticLayout automaticLayout = new AutomaticLayout(); 56 | automaticLayout.EdgeSeparation = -100; 57 | throw new TestFailedException(); 58 | } 59 | catch (ArgumentException iae) 60 | { 61 | Assert.Equal("The edge separation must be a positive integer.", iae.Message); 62 | } 63 | } 64 | 65 | } 66 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/ColorTests.cs: -------------------------------------------------------------------------------- 1 |  2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests 5 | { 6 | 7 | 8 | public class ColorTests 9 | { 10 | 11 | [Fact] 12 | public void Test_IsHexColorCode_ReturnsFalse_WhenPassedNull() 13 | { 14 | Assert.False(Color.IsHexColorCode(null)); 15 | } 16 | 17 | [Fact] 18 | public void Test_IsHexColorCode_ReturnsFalse_WhenPassedAnEmptyString() 19 | { 20 | Assert.False(Color.IsHexColorCode("")); 21 | } 22 | 23 | [Fact] 24 | public void Test_IsHexColorCode_ReturnsFalse_WhenPassedAnInvalidString() 25 | { 26 | Assert.False(Color.IsHexColorCode("ffffff")); 27 | Assert.False(Color.IsHexColorCode("#fffff")); 28 | Assert.False(Color.IsHexColorCode("#gggggg")); 29 | } 30 | 31 | [Fact] 32 | public void Test_IsHexColorCode_ReturnsTrue_WhenPassedAnValidString() 33 | { 34 | Assert.True(Color.IsHexColorCode("#abcdef")); 35 | Assert.True(Color.IsHexColorCode("#ABCDEF")); 36 | Assert.True(Color.IsHexColorCode("#123456")); 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/DimensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests.View 5 | { 6 | public class DimensionsTests 7 | { 8 | [Fact] 9 | public void Test_Construction() 10 | { 11 | Dimensions dimensions = new Dimensions(123, 456); 12 | 13 | Assert.Equal(123, dimensions.Width); 14 | Assert.Equal(456, dimensions.Height); 15 | } 16 | 17 | [Fact] 18 | public void Test_Width_ThrowsAnException_WhenANegativeIntegerIsSpecified() 19 | { 20 | try 21 | { 22 | Dimensions dimensions = new Dimensions(); 23 | dimensions.Width = -100; 24 | throw new TestFailedException(); 25 | } 26 | catch (ArgumentException iae) 27 | { 28 | Assert.Equal("The width must be a positive integer.", iae.Message); 29 | } 30 | } 31 | 32 | [Fact] 33 | public void Test_Height_ThrowsAnException_WhenANegativeIntegerIsSpecified() 34 | { 35 | try 36 | { 37 | Dimensions dimensions = new Dimensions(); 38 | dimensions.Height = -100; 39 | throw new TestFailedException(); 40 | } 41 | catch (ArgumentException iae) 42 | { 43 | Assert.Equal("The height must be a positive integer.", iae.Message); 44 | } 45 | } 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/FilteredViewTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests.View 4 | { 5 | 6 | public class FilteredViewTests : AbstractTestBase 7 | { 8 | 9 | [Fact] 10 | public void Test_Construction() 11 | { 12 | SoftwareSystem softwareSystem = Model.AddSoftwareSystem("Name", "Description"); 13 | SystemContextView systemContextView = Views.CreateSystemContextView(softwareSystem, "SystemContext", "Description"); 14 | FilteredView filteredView = Views.CreateFilteredView( 15 | systemContextView, 16 | "CurrentStateSystemContext", 17 | "The system context as-is.", 18 | FilterMode.Exclude, 19 | "v2", "v3" 20 | ); 21 | 22 | Assert.Equal("CurrentStateSystemContext", filteredView.Key); 23 | Assert.Equal("SystemContext", filteredView.BaseViewKey); 24 | Assert.Same(systemContextView, filteredView.View); 25 | Assert.Equal("The system context as-is.", filteredView.Description); 26 | Assert.Equal(FilterMode.Exclude, filteredView.Mode); 27 | Assert.Equal(2, filteredView.Tags.Count); 28 | Assert.True(filteredView.Tags.Contains("v2")); 29 | Assert.True(filteredView.Tags.Contains("v3")); 30 | } 31 | 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/FontTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests.View 5 | { 6 | 7 | 8 | public class FontTests 9 | { 10 | 11 | private Font _font; 12 | 13 | [Fact] 14 | public void construction_WithANameOnly() 15 | { 16 | this._font = new Font("Times New Roman"); 17 | Assert.Equal("Times New Roman", _font.Name); 18 | } 19 | 20 | [Fact] 21 | public void construction_WithANameAndUrl() 22 | { 23 | this._font = new Font("Open Sans", "https://fonts.googleapis.com/css?family=Open+Sans:400,700"); 24 | Assert.Equal("Open Sans", _font.Name); 25 | Assert.Equal("https://fonts.googleapis.com/css?family=Open+Sans:400,700", _font.Url); 26 | } 27 | 28 | [Fact] 29 | public void test_setUrl_WithAUrl() 30 | { 31 | _font = new Font(); 32 | _font.Url = "https://fonts.googleapis.com/css?family=Open+Sans:400,700"; 33 | Assert.Equal("https://fonts.googleapis.com/css?family=Open+Sans:400,700", _font.Url); 34 | } 35 | 36 | [Fact] 37 | public void test_setUrl_ThrowsAnArgumentException_WhenAnInvalidUrlIsSpecified() 38 | { 39 | _font = new Font(); 40 | Assert.Throws(() => 41 | _font.Url = "www.google.com" 42 | ); 43 | } 44 | 45 | [Fact] 46 | public void test_setUrl_DoesNothing_WhenANullUrlIsSpecified() 47 | { 48 | _font = new Font(); 49 | _font.Url = null; 50 | Assert.Null(_font.Url); 51 | } 52 | 53 | [Fact] 54 | public void test_setUrl_DoesNothing_WhenAnEmptyUrlIsSpecified() 55 | { 56 | _font = new Font(); 57 | _font.Url = " "; 58 | Assert.Null(_font.Url); 59 | } 60 | 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/RelationshipStyleTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests.View 5 | { 6 | 7 | public class RelationshipStyleTests 8 | { 9 | 10 | [Fact] 11 | public void Test_Position() 12 | { 13 | RelationshipStyle style = new RelationshipStyle(); 14 | Assert.Null(style.Position); 15 | 16 | style.Position = -1; 17 | Assert.Equal(0, style.Position); 18 | 19 | style.Position = 0; 20 | Assert.Equal(0, style.Position); 21 | 22 | style.Position = 50; 23 | Assert.Equal(50, style.Position); 24 | 25 | style.Position = 100; 26 | Assert.Equal(100, style.Position); 27 | 28 | style.Position = 101; 29 | Assert.Equal(100, style.Position); 30 | } 31 | 32 | [Fact] 33 | public void Test_Opacity() 34 | { 35 | RelationshipStyle style = new RelationshipStyle(); 36 | Assert.Null(style.Opacity); 37 | 38 | style.Opacity = -1; 39 | Assert.Equal(0, style.Opacity); 40 | 41 | style.Opacity = 0; 42 | Assert.Equal(0, style.Opacity); 43 | 44 | style.Opacity = 50; 45 | Assert.Equal(50, style.Opacity); 46 | 47 | style.Opacity = 100; 48 | Assert.Equal(100, style.Opacity); 49 | 50 | style.Opacity = 101; 51 | Assert.Equal(100, style.Opacity); 52 | } 53 | 54 | [Fact] 55 | public void Test_Color_SetsTheColorProperty_WhenAValidHexColorCodeIsSpecified() 56 | { 57 | RelationshipStyle style = new RelationshipStyle(); 58 | style.Color = "#ffffff"; 59 | Assert.Equal("#ffffff", style.Color); 60 | 61 | style.Color = "#FFFFFF"; 62 | Assert.Equal("#ffffff", style.Color); 63 | 64 | style.Color = "#123456"; 65 | Assert.Equal("#123456", style.Color); 66 | } 67 | 68 | [Fact] 69 | public void Test_Color_ThrowsAnException_WhenAnInvalidHexColorCodeIsSpecified() 70 | { 71 | try 72 | { 73 | RelationshipStyle style = new RelationshipStyle(); 74 | style.Color = "white"; 75 | throw new TestFailedException(); 76 | } 77 | catch (ArgumentException ae) 78 | { 79 | Assert.Equal("'white' is not a valid hex color code.", ae.Message); 80 | } 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/SequenceCounterTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | 6 | public class SequenceCounterTests 7 | { 8 | 9 | [Fact] 10 | public void Test_increment_IncrementsTheCounter() 11 | { 12 | SequenceCounter counter = new SequenceCounter(); 13 | Assert.Equal("0", counter.AsString()); 14 | 15 | counter.Increment(); 16 | Assert.Equal("1", counter.AsString()); 17 | 18 | counter.Increment(); 19 | Assert.Equal("2", counter.AsString()); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/SequenceNumberTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Structurizr.Core.Tests 4 | { 5 | 6 | public class SequenceNumberTests 7 | { 8 | 9 | [Fact] 10 | public void Test_Increment() 11 | { 12 | SequenceNumber sequenceNumber = new SequenceNumber(); 13 | Assert.Equal("1", sequenceNumber.GetNext()); 14 | Assert.Equal("2", sequenceNumber.GetNext()); 15 | } 16 | 17 | [Fact] 18 | public void Test_ParallelSequences() 19 | { 20 | SequenceNumber sequenceNumber = new SequenceNumber(); 21 | Assert.Equal("1", sequenceNumber.GetNext()); 22 | 23 | sequenceNumber.StartParallelSequence(); 24 | Assert.Equal("2", sequenceNumber.GetNext()); 25 | sequenceNumber.EndParallelSequence(false); 26 | 27 | sequenceNumber.StartParallelSequence(); 28 | Assert.Equal("2", sequenceNumber.GetNext()); 29 | sequenceNumber.EndParallelSequence(true); 30 | 31 | Assert.Equal("3", sequenceNumber.GetNext()); 32 | } 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/View/StyleTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Structurizr.Core.Tests.View 5 | { 6 | 7 | public class StyleTests 8 | { 9 | 10 | private Styles _styles = new Styles(); 11 | 12 | [Fact] 13 | public void Test_AddElementStyle_ThrowsAnException_WhenAStyleWithTheSameTagExistsAlready() 14 | { 15 | try 16 | { 17 | _styles.Add(new ElementStyle(Tags.SoftwareSystem) { Color = "#ff0000" }); 18 | _styles.Add(new ElementStyle(Tags.SoftwareSystem) { Color = "#ff0000" }); 19 | 20 | throw new TestFailedException(); 21 | } 22 | catch (ArgumentException ae) 23 | { 24 | Assert.Equal("An element style for the tag \"Software System\" already exists.", ae.Message); 25 | } 26 | } 27 | 28 | [Fact] 29 | public void Test_AddRelationshipStyle_ThrowsAnException_WhenAStyleWithTheSameTagExistsAlready() 30 | { 31 | try 32 | { 33 | _styles.Add(new RelationshipStyle(Tags.Relationship) { Color = "#ff0000" }); 34 | _styles.Add(new RelationshipStyle(Tags.Relationship) { Color = "#ff0000" }); 35 | 36 | throw new TestFailedException(); 37 | } 38 | catch (ArgumentException ae) 39 | { 40 | Assert.Equal("A relationship style for the tag \"Relationship\" already exists.", ae.Message); 41 | } 42 | } 43 | 44 | [Fact] 45 | public void Test_ClearElementStyles_RemovesAllElementStyles() 46 | { 47 | _styles.Add(new ElementStyle(Tags.SoftwareSystem) { Color = "#ff0000" }); 48 | Assert.Equal(1, _styles.Elements.Count); 49 | 50 | _styles.ClearElementStyles(); 51 | Assert.Equal(0, _styles.Elements.Count); 52 | } 53 | 54 | [Fact] 55 | public void Test_ClearRelationshipStyles_RemovesAllRelationshipStyles() 56 | { 57 | _styles.Add(new RelationshipStyle(Tags.Relationship) { Color = "#ff0000" }); 58 | Assert.Equal(1, _styles.Relationships.Count); 59 | 60 | _styles.ClearRelationshipStyles(); 61 | Assert.Equal(0, _styles.Relationships.Count); 62 | } 63 | 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /Structurizr.Core.Tests/WorkspaceTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using System; 3 | 4 | namespace Structurizr.Core.Tests 5 | { 6 | 7 | 8 | public class WorkspaceTests 9 | { 10 | 11 | private Workspace workspace = new Workspace("Name", "Description"); 12 | 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Structurizr.Core/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Structurizr.Core.Tests")] 2 | 3 | namespace Structurizr 4 | { 5 | public class AssemblyInfo 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /Structurizr.Core/Config/Role.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Config 2 | { 3 | public enum Role 4 | { 5 | 6 | ReadWrite, 7 | ReadOnly 8 | 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Structurizr.Core/Config/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Structurizr.Config 5 | { 6 | 7 | [DataContract] 8 | public sealed class User : IEquatable 9 | { 10 | 11 | [DataMember(Name = "username", EmitDefaultValue = false)] 12 | public string Username { get; internal set; } 13 | 14 | [DataMember(Name = "role", EmitDefaultValue = true)] 15 | public Role Role { get; internal set; } 16 | 17 | internal User() 18 | { 19 | } 20 | 21 | internal User(string username, Role role) 22 | { 23 | Username = username; 24 | Role = role; 25 | } 26 | 27 | public bool Equals(User other) 28 | { 29 | if (ReferenceEquals(null, other)) return false; 30 | if (ReferenceEquals(this, other)) return true; 31 | return string.Equals(Username, other.Username); 32 | } 33 | 34 | public override bool Equals(object obj) 35 | { 36 | if (ReferenceEquals(null, obj)) return false; 37 | if (ReferenceEquals(this, obj)) return true; 38 | if (obj.GetType() != this.GetType()) return false; 39 | return Equals((User) obj); 40 | } 41 | 42 | public override int GetHashCode() 43 | { 44 | return Username.GetHashCode(); 45 | } 46 | 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /Structurizr.Core/Config/WorkspaceConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | using Newtonsoft.Json; 5 | 6 | namespace Structurizr.Config 7 | { 8 | 9 | [DataContract] 10 | public sealed class WorkspaceConfiguration 11 | { 12 | 13 | private HashSet _users; 14 | 15 | [DataMember(Name = "users", EmitDefaultValue = false)] 16 | public ISet Users 17 | { 18 | get 19 | { 20 | return new HashSet(_users); 21 | } 22 | 23 | internal set 24 | { 25 | _users = new HashSet(value); 26 | } 27 | } 28 | 29 | [JsonConstructor] 30 | internal WorkspaceConfiguration() 31 | { 32 | _users = new HashSet(); 33 | } 34 | 35 | public void AddUser(string username, Role role) 36 | { 37 | if (string.IsNullOrWhiteSpace(username)) 38 | { 39 | throw new ArgumentException("A username must be specified."); 40 | } 41 | 42 | _users.Add(new User(username, role)); 43 | } 44 | 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /Structurizr.Core/Documentation/DecisionStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Documentation 2 | { 3 | 4 | /// 5 | /// Represents the status of a decision. 6 | /// 7 | public enum DecisionStatus 8 | { 9 | 10 | Proposed, 11 | Accepted, 12 | Superseded, 13 | Deprecated, 14 | Rejected 15 | 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /Structurizr.Core/Documentation/Format.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Documentation 2 | { 3 | public enum Format 4 | { 5 | 6 | Markdown, 7 | AsciiDoc 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Structurizr.Core/Documentation/FormatFinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace Structurizr.Documentation 6 | { 7 | 8 | internal class FormatFinder 9 | { 10 | 11 | private static ISet MARKDOWN_EXTENSIONS = new HashSet 12 | { 13 | ".md", ".markdown", ".text" 14 | }; 15 | 16 | private static ISet ASCIIDOC_EXTENSIONS = new HashSet 17 | { 18 | ".asciidoc", ".adoc", ".asc" 19 | }; 20 | 21 | internal static Format FindFormat(FileSystemInfo file) { 22 | if (file == null) { 23 | throw new ArgumentException("A file must be specified."); 24 | } 25 | 26 | if (MARKDOWN_EXTENSIONS.Contains(file.Extension)) { 27 | return Format.Markdown; 28 | } else if (ASCIIDOC_EXTENSIONS.Contains(file.Extension)) { 29 | return Format.AsciiDoc; 30 | } else { 31 | // just assume Markdown 32 | return Format.Markdown; 33 | } 34 | 35 | } 36 | 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /Structurizr.Core/Documentation/FormattedContent.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Documentation 2 | { 3 | 4 | internal class FormattedContent 5 | { 6 | 7 | internal string Content { get; } 8 | internal Format Format { get; } 9 | 10 | internal FormattedContent(string content, Format format) 11 | { 12 | Content = content; 13 | Format = format; 14 | } 15 | 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /Structurizr.Core/Documentation/Image.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace Structurizr.Documentation 4 | { 5 | 6 | [DataContract] 7 | public sealed class Image 8 | { 9 | 10 | [DataMember(Name = "name", EmitDefaultValue = false)] 11 | public string Name { get; internal set; } 12 | 13 | [DataMember(Name = "content", EmitDefaultValue = false)] 14 | public string Content { get; private set; } 15 | 16 | [DataMember(Name = "type", EmitDefaultValue = false)] 17 | public string Type { get; private set; } 18 | 19 | internal Image() { } 20 | 21 | internal Image(string name, string content, string type) 22 | { 23 | this.Name = name; 24 | this.Content = content; 25 | this.Type = type; 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/AbstractImpliedRelationshipsStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | public abstract class AbstractImpliedRelationshipsStrategy : IImpliedRelationshipsStrategy 5 | { 6 | 7 | protected bool ImpliedRelationshipIsAllowed(Element source, Element destination) 8 | { 9 | if (source.Equals(destination)) 10 | { 11 | return false; 12 | } 13 | 14 | return !(IsChildOf(source, destination) || IsChildOf(destination, source)); 15 | } 16 | 17 | private bool IsChildOf(Element e1, Element e2) 18 | { 19 | if (e1 is Person || e2 is Person) { 20 | return false; 21 | } 22 | 23 | Element parent = e2.Parent; 24 | while (parent != null) { 25 | if (parent.Id.Equals(e1.Id)) { 26 | return true; 27 | } 28 | 29 | parent = parent.Parent; 30 | } 31 | 32 | return false; 33 | } 34 | 35 | /// 36 | /// Called after a relationship has been created in the model, 37 | /// providing an opportunity to create any resulting implied relationships. 38 | /// 39 | /// the newly created Relationship 40 | public abstract void CreateImpliedRelationships(Relationship relationship); 41 | 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/CodeElementRole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Structurizr 7 | { 8 | 9 | public enum CodeElementRole 10 | { 11 | 12 | Primary, 13 | Supporting 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/ContainerInstance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | 5 | namespace Structurizr 6 | { 7 | 8 | /// 9 | /// Represents a deployment instance of a Container, which can be added to a DeploymentNode. 10 | /// 11 | [DataContract] 12 | public sealed class ContainerInstance : StaticStructureElementInstance 13 | { 14 | 15 | public Container Container { get; internal set; } 16 | 17 | private string _containerId; 18 | 19 | [DataMember(Name = "containerId", EmitDefaultValue = false)] 20 | public string ContainerId 21 | { 22 | get 23 | { 24 | if (Container != null) 25 | { 26 | return Container.Id; 27 | } 28 | else 29 | { 30 | return _containerId; 31 | } 32 | } 33 | set { _containerId = value; } 34 | } 35 | 36 | internal ContainerInstance() { 37 | } 38 | 39 | internal ContainerInstance(Container container, int instanceId, string environment, string deploymentGroup) 40 | { 41 | Container = container; 42 | AddTags(Structurizr.Tags.ContainerInstance); 43 | InstanceId = instanceId; 44 | Environment = environment; 45 | DeploymentGroup = deploymentGroup; 46 | } 47 | 48 | public override StaticStructureElement getElement() 49 | { 50 | return Container; 51 | } 52 | 53 | public override string CanonicalName 54 | { 55 | get { return new CanonicalNameGenerator().Generate(this); } 56 | } 57 | 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/CreateImpliedRelationshipsUnlessAnyRelationshipExistsStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | /// 7 | /// This strategy creates implied relationships between all valid combinations of the parent elements, 8 | /// unless any relationship already exists between them. 9 | /// 10 | public class CreateImpliedRelationshipsUnlessAnyRelationshipExistsStrategy : AbstractImpliedRelationshipsStrategy 11 | { 12 | public override void CreateImpliedRelationships(Relationship relationship) 13 | { 14 | Element source = relationship.Source; 15 | Element destination = relationship.Destination; 16 | 17 | Model model = source.Model; 18 | 19 | while (source != null) { 20 | while (destination != null) { 21 | if (ImpliedRelationshipIsAllowed(source, destination)) { 22 | bool createRelationship = !source.HasEfferentRelationshipWith(destination); 23 | 24 | if (createRelationship) { 25 | model.AddRelationship(source, destination, relationship.Description, relationship.Technology, relationship.InteractionStyle, relationship.GetTagsAsSet().ToArray(), false); 26 | } 27 | } 28 | 29 | destination = destination.Parent; 30 | } 31 | 32 | destination = relationship.Destination; 33 | source = source.Parent; 34 | } 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/CreateImpliedRelationshipsUnlessSameRelationshipExistsStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | /// 7 | /// This strategy creates implied relationships between all valid combinations of the parent elements, 8 | /// unless the same relationship already exists between them. 9 | /// 10 | public class CreateImpliedRelationshipsUnlessSameRelationshipExistsStrategy : AbstractImpliedRelationshipsStrategy 11 | { 12 | public override void CreateImpliedRelationships(Relationship relationship) 13 | { 14 | Element source = relationship.Source; 15 | Element destination = relationship.Destination; 16 | 17 | Model model = source.Model; 18 | 19 | while (source != null) { 20 | while (destination != null) { 21 | if (ImpliedRelationshipIsAllowed(source, destination)) { 22 | bool createRelationship = !source.HasEfferentRelationshipWith(destination, relationship.Description); 23 | 24 | if (createRelationship) { 25 | model.AddRelationship(source, destination, relationship.Description, relationship.Technology, relationship.InteractionStyle, relationship.GetTagsAsSet().ToArray(), false); 26 | } 27 | } 28 | 29 | destination = destination.Parent; 30 | } 31 | 32 | destination = relationship.Destination; 33 | source = source.Parent; 34 | } 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/DefaultImpliedRelationshipsStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | /// 5 | /// The default strategy is to NOT create implied relationships. 6 | /// 7 | public class DefaultImpliedRelationshipsStrategy : AbstractImpliedRelationshipsStrategy 8 | { 9 | 10 | public override void CreateImpliedRelationships(Relationship relationship) 11 | { 12 | // do nothing 13 | } 14 | 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/DeploymentElement.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | /// 7 | /// This is the superclass for model elements that describe deployment nodes, infrastructure nodes, and container instances. 8 | /// 9 | [DataContract] 10 | public abstract class DeploymentElement : Element 11 | { 12 | 13 | internal const string DefaultDeploymentEnvironment = "Default"; 14 | internal const string DefaultDeploymentGroup = "Default"; 15 | 16 | [DataMember(Name = "environment", EmitDefaultValue = false)] 17 | public string Environment { get; internal set; } 18 | 19 | private Element _parent; 20 | 21 | public override Element Parent { get; set; } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/Enterprise.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Structurizr 5 | { 6 | 7 | [DataContract] 8 | public sealed class Enterprise 9 | { 10 | 11 | /// 12 | /// The name of this enterprise. 13 | /// 14 | [DataMember(Name = "name", EmitDefaultValue = false)] 15 | public string Name { get; set; } 16 | 17 | public Enterprise(string name) 18 | { 19 | if (name == null || name.Trim().Length == 0) 20 | { 21 | throw new ArgumentException("Name must be specified."); 22 | } 23 | 24 | this.Name = name; 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/GroupableElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Structurizr 5 | { 6 | 7 | public abstract class GroupableElement : Element 8 | { 9 | 10 | private string _group; 11 | 12 | /// 13 | /// The name of the group in which this element should be included in. 14 | /// 15 | [DataMember(Name = "group", EmitDefaultValue = false)] 16 | public string Group 17 | { 18 | get 19 | { 20 | return _group; 21 | } 22 | 23 | set 24 | { 25 | if (value == null) 26 | { 27 | _group = null; 28 | } 29 | else { 30 | _group = value.Trim(); 31 | 32 | if (String.IsNullOrEmpty(_group)) 33 | { 34 | _group = null; 35 | } 36 | } 37 | } 38 | } 39 | 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/IdGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | /// 5 | /// The interface that ID generators, used when creating IDs for model elements/relationships, must implement. 6 | /// 7 | public interface IdGenerator 8 | { 9 | 10 | /// 11 | /// Generates an ID for the specified model element. 12 | /// 13 | /// an Element instance 14 | /// the ID 15 | string GenerateId(Element element); 16 | 17 | /// 18 | /// Generates an ID for the specified model element. 19 | /// 20 | /// a Relationship instance 21 | /// the ID 22 | string GenerateId(Relationship relationship); 23 | 24 | /// 25 | /// Called when loading/deserializing a model, to indicate that the specified ID has been found 26 | /// (and shouldn't be reused when generating new IDs). 27 | /// 28 | /// he ID that has been found 29 | void Found(string id); 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/ImpliedRelationshipsStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | /// 5 | /// Defines the interface for strategies to create implied relationships in the model, 6 | /// after a relationship has been created. 7 | /// 8 | public interface IImpliedRelationshipsStrategy 9 | { 10 | 11 | /// 12 | /// Called after a relationship has been created in the model, 13 | /// providing an opportunity to create any resulting implied relationships. 14 | /// 15 | /// the newly created Relationship 16 | void CreateImpliedRelationships(Relationship relationship); 17 | 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/InteractionStyle.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum InteractionStyle 4 | { 5 | 6 | Synchronous, 7 | Asynchronous 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/Location.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum Location 4 | { 5 | 6 | Unspecified, 7 | Internal, 8 | External 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/Perspective.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | using System.Text; 5 | 6 | namespace Structurizr 7 | { 8 | 9 | /// 10 | /// Represents an architectural perspective, that can be applied to elements and relationships. 11 | /// See https://www.viewpoints-and-perspectives.info/home/perspectives/ for more details of this concept 12 | /// 13 | [DataContract] 14 | public sealed class Perspective : IEquatable 15 | { 16 | 17 | /// 18 | /// The name of this perspective. 19 | /// 20 | [DataMember(Name = "name", EmitDefaultValue = false)] 21 | public string Name { get; internal set; } 22 | 23 | /// 24 | /// The content of this perspective. 25 | /// 26 | [DataMember(Name = "description", EmitDefaultValue = false)] 27 | public string Description { get; internal set; } 28 | 29 | internal Perspective() 30 | { 31 | } 32 | 33 | internal Perspective(string name, string description) 34 | { 35 | Name = name; 36 | Description = description; 37 | } 38 | 39 | public override bool Equals(object obj) 40 | { 41 | return Equals(obj as Perspective); 42 | } 43 | 44 | public bool Equals(Perspective other) 45 | { 46 | return other != null && 47 | Name == other.Name; 48 | } 49 | 50 | public override int GetHashCode() 51 | { 52 | return Name.GetHashCode(); 53 | } 54 | 55 | } 56 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/SequentialIntegerIdGeneratorStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | /// 7 | /// An ID generator that simply uses a sequential number when generating IDs for model elements and relationships. 8 | /// This is the default ID generator. 9 | /// 10 | public class SequentialIntegerIdGeneratorStrategy : IdGenerator 11 | { 12 | 13 | private int Id = 0; 14 | 15 | public string GenerateId(Element element) 16 | { 17 | lock(this) 18 | { 19 | return "" + ++Id; 20 | } 21 | } 22 | 23 | 24 | public string GenerateId(Relationship relationship) 25 | { 26 | lock(this) 27 | { 28 | return "" + ++Id; 29 | } 30 | } 31 | 32 | public void Found(string id) 33 | { 34 | int idAsInt = int.Parse(id); 35 | if (idAsInt > Id) 36 | { 37 | Id = idAsInt; 38 | } 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Structurizr.Core/Model/SoftwareSystemInstance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | 5 | namespace Structurizr 6 | { 7 | 8 | /// 9 | /// Represents a deployment instance of a Software System, which can be added to a DeploymentNode. 10 | /// 11 | [DataContract] 12 | public sealed class SoftwareSystemInstance : StaticStructureElementInstance 13 | { 14 | 15 | public SoftwareSystem SoftwareSystem { get; internal set; } 16 | 17 | private string _softwareSystemId; 18 | 19 | [DataMember(Name = "softwareSystemId", EmitDefaultValue = false)] 20 | public string SoftwareSystemId 21 | { 22 | get 23 | { 24 | if (SoftwareSystem != null) 25 | { 26 | return SoftwareSystem.Id; 27 | } 28 | else 29 | { 30 | return _softwareSystemId; 31 | } 32 | } 33 | set { _softwareSystemId = value; } 34 | } 35 | 36 | internal SoftwareSystemInstance() { 37 | } 38 | 39 | internal SoftwareSystemInstance(SoftwareSystem softwareSystem, int instanceId, string environment, string deploymentGroup) 40 | { 41 | SoftwareSystem = softwareSystem; 42 | AddTags(Structurizr.Tags.SoftwareSystemInstance); 43 | InstanceId = instanceId; 44 | Environment = environment; 45 | DeploymentGroup = deploymentGroup; 46 | } 47 | 48 | public override StaticStructureElement getElement() 49 | { 50 | return SoftwareSystem; 51 | } 52 | 53 | public override string CanonicalName 54 | { 55 | get { return new CanonicalNameGenerator().Generate(this); } 56 | } 57 | 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /Structurizr.Core/Model/Tags.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public sealed class Tags 4 | { 5 | 6 | public const string Element = "Element"; 7 | public const string Relationship = "Relationship"; 8 | 9 | public const string Person = "Person"; 10 | public const string SoftwareSystem = "Software System"; 11 | public const string Container = "Container"; 12 | public const string Component = "Component"; 13 | 14 | public const string Synchronous = "Synchronous"; 15 | public const string Asynchronous = "Asynchronous"; 16 | 17 | public const string DeploymentNode = "Deployment Node"; 18 | public const string InfrastructureNode = "Infrastructure Node"; 19 | public const string SoftwareSystemInstance = "Software System Instance"; 20 | public const string ContainerInstance = "Container Instance"; 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Structurizr.Core/Structurizr.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 1.1.1 7 | true 8 | 9 | 10 | The core library that can used to create software architecture models. 11 | Structurizr Limited 12 | Copyright 2017-2023 13 | https://opensource.org/licenses/Apache-2.0 14 | https://structurizr.com 15 | https://github.com/structurizr/dotnet 16 | 17 | 18 | netstandard2.0 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Structurizr.Core/Util/DictionaryUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Structurizr.Core.Util 4 | { 5 | 6 | public class DictionaryUtils 7 | { 8 | 9 | public static Dictionary Create(params string[] nameValuePairs) 10 | { 11 | Dictionary map = new Dictionary(); 12 | 13 | if (nameValuePairs != null) { 14 | foreach (string nameValuePair in nameValuePairs) 15 | { 16 | string[] tokens = nameValuePair.Split('='); 17 | if (tokens.Length == 2) 18 | { 19 | map[tokens[0]] = tokens[1]; 20 | } 21 | } 22 | } 23 | 24 | return map; 25 | } 26 | 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /Structurizr.Core/Util/ImageUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Structurizr.Util 8 | { 9 | public class ImageUtils 10 | { 11 | 12 | public static string GetContentType(FileInfo file) 13 | { 14 | if (file == null) 15 | { 16 | throw new ArgumentException("A file must be specified."); 17 | } 18 | else if (Directory.Exists(file.FullName)) 19 | { 20 | throw new ArgumentException(file.FullName + " is not a file."); 21 | } 22 | else if (!file.Exists) 23 | { 24 | throw new ArgumentException(file.FullName + " does not exist."); 25 | } 26 | 27 | string fileExtension = file.FullName.Substring(file.FullName.LastIndexOf(".") + 1).ToLower(); 28 | if (fileExtension.Equals("jpg")) 29 | { 30 | fileExtension = "jpeg"; 31 | } 32 | 33 | if (fileExtension == "png" || fileExtension == "jpeg" || fileExtension == "gif") 34 | { 35 | return "image/" + fileExtension; 36 | } 37 | else 38 | { 39 | throw new ArgumentException(file.FullName + " is not a supported image file."); 40 | } 41 | } 42 | 43 | public static string GetImageAsBase64(FileInfo file) 44 | { 45 | String contentType = GetContentType(file); // this does the file checks 46 | byte[] imageArray = File.ReadAllBytes(file.FullName); 47 | return Convert.ToBase64String(imageArray); 48 | } 49 | 50 | public static string GetImageAsDataUri(FileInfo file) 51 | { 52 | String contentType = GetContentType(file); 53 | String base64Content = GetImageAsBase64(file); 54 | 55 | return "data:" + contentType + ";base64," + base64Content; 56 | } 57 | 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Structurizr.Core/Util/Url.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Structurizr.Util 4 | { 5 | 6 | public class Url 7 | { 8 | 9 | public static bool IsUrl(string urlAsString) 10 | { 11 | if (urlAsString != null && urlAsString.Trim().Length > 0) 12 | { 13 | Uri uri; 14 | return Uri.TryCreate(urlAsString, UriKind.Absolute, out uri); 15 | } 16 | 17 | return false; 18 | } 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Structurizr.Core/View/Animation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Structurizr 5 | { 6 | 7 | [DataContract] 8 | public sealed class Animation 9 | { 10 | 11 | [DataMember(Name = "order", EmitDefaultValue = false)] 12 | public int Order { get; internal set; } 13 | 14 | private HashSet _elements; 15 | 16 | [DataMember(Name = "elements", EmitDefaultValue = false)] 17 | public ISet Elements 18 | { 19 | get 20 | { 21 | return new HashSet(_elements); 22 | } 23 | 24 | internal set 25 | { 26 | _elements = new HashSet(value); 27 | } 28 | } 29 | 30 | private HashSet _relationships; 31 | 32 | [DataMember(Name = "relationships", EmitDefaultValue = false)] 33 | public ISet Relationships 34 | { 35 | get 36 | { 37 | return new HashSet(_relationships); 38 | } 39 | 40 | internal set 41 | { 42 | _relationships = new HashSet(value); 43 | } 44 | } 45 | 46 | internal Animation() 47 | { 48 | _elements = new HashSet(); 49 | _relationships = new HashSet(); 50 | } 51 | 52 | internal Animation(int order, ISet elements, ISet relationships) : this() 53 | { 54 | Order = order; 55 | 56 | foreach (Element element in elements) 57 | { 58 | _elements.Add(element.Id); 59 | } 60 | 61 | foreach (Relationship relationship in relationships) 62 | { 63 | _relationships.Add(relationship.Id); 64 | } 65 | } 66 | 67 | } 68 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/Border.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum Border 4 | { 5 | 6 | Solid, 7 | Dashed, 8 | Dotted 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Structurizr.Core/View/Branding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | using Structurizr.Util; 4 | 5 | namespace Structurizr 6 | { 7 | 8 | [DataContract] 9 | public sealed class Branding 10 | { 11 | 12 | [DataMember(Name = "font", EmitDefaultValue = false)] 13 | public Font Font; 14 | 15 | private string _logo; 16 | 17 | [DataMember(Name = "logo", EmitDefaultValue = false)] 18 | public string Logo 19 | { 20 | get { return _logo; } 21 | set 22 | { 23 | if (value != null && value.Trim().Length > 0) 24 | { 25 | if (Url.IsUrl(value) || value.StartsWith("data:image/")) 26 | { 27 | _logo = value.Trim(); 28 | } 29 | else { 30 | throw new ArgumentException(value + " is not a valid URL."); 31 | } 32 | } 33 | } 34 | } 35 | 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/Color.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace Structurizr 4 | { 5 | public class Color 6 | { 7 | 8 | public static bool IsHexColorCode(string colorAsString) 9 | { 10 | return colorAsString != null && Regex.IsMatch(colorAsString, "^#[A-Fa-f0-9]{6}"); 11 | } 12 | 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Structurizr.Core/View/ColorPair.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Structurizr 5 | { 6 | 7 | [DataContract] 8 | public sealed class ColorPair 9 | { 10 | 11 | private string _background; 12 | private string _foreground; 13 | 14 | internal ColorPair() 15 | { } 16 | 17 | public ColorPair(string background, string foreground) 18 | { 19 | this.Background = background; 20 | this.Foreground = foreground; 21 | } 22 | 23 | [DataMember(Name = "background", EmitDefaultValue = false)] 24 | public string Background 25 | { 26 | get { return this._background; } 27 | set 28 | { 29 | if (Color.IsHexColorCode(value)) 30 | { 31 | this._background = value.ToLower(); 32 | } 33 | else 34 | { 35 | throw new ArgumentException("'" + value + "' is not a valid hex color code."); 36 | } 37 | } 38 | } 39 | 40 | [DataMember(Name = "foreground", EmitDefaultValue = false)] 41 | public string Foreground 42 | { 43 | get { return this._foreground; } 44 | set 45 | { 46 | if (Color.IsHexColorCode(value)) 47 | { 48 | this._foreground = value.ToLower(); 49 | } 50 | else 51 | { 52 | throw new ArgumentException("'" + value + "' is not a valid hex color code."); 53 | } 54 | } 55 | } 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /Structurizr.Core/View/Dimensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Structurizr 5 | { 6 | [DataContract] 7 | public class Dimensions 8 | { 9 | 10 | private int _width; 11 | 12 | /// 13 | /// The width (pixels). 14 | /// 15 | [DataMember(Name = "width", EmitDefaultValue = false)] 16 | public int Width 17 | { 18 | get { return _width; } 19 | 20 | set 21 | { 22 | if (value < 0) 23 | { 24 | throw new ArgumentException("The width must be a positive integer."); 25 | } 26 | 27 | _width = value; 28 | } 29 | } 30 | 31 | private int _height; 32 | 33 | /// 34 | /// The height (pixels). 35 | /// 36 | [DataMember(Name = "height", EmitDefaultValue = false)] 37 | public int Height 38 | { 39 | get { return _height; } 40 | 41 | set 42 | { 43 | if (value < 0) 44 | { 45 | throw new ArgumentException("The height must be a positive integer."); 46 | } 47 | 48 | _height = value; 49 | } 50 | } 51 | 52 | internal Dimensions() 53 | { 54 | } 55 | 56 | public Dimensions(int width, int height) 57 | { 58 | Width = width; 59 | Height = height; 60 | } 61 | 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/ElementNotPermittedInViewException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | public sealed class ElementNotPermittedInViewException : Exception 7 | { 8 | 9 | internal ElementNotPermittedInViewException(string message) : base(message) 10 | { 11 | } 12 | 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/FilterMode.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum FilterMode 4 | { 5 | 6 | Include, 7 | Exclude 8 | 9 | } 10 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/FilteredView.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Serialization; 3 | using Newtonsoft.Json; 4 | 5 | namespace Structurizr 6 | { 7 | /// 8 | /// Represents a view on top of a view, which can be used to include or exclude specific elements. 9 | /// 10 | [DataContract] 11 | public sealed class FilteredView 12 | { 13 | 14 | [DataMember(Name="key", EmitDefaultValue=false)] 15 | public string Key { get; internal set; } 16 | 17 | public View View { get; internal set; } 18 | 19 | [DataMember(Name="description", EmitDefaultValue=false)] 20 | public string Description { get; internal set; } 21 | 22 | [DataMember(Name="mode", EmitDefaultValue=true)] 23 | public FilterMode Mode { get; internal set; } 24 | 25 | [DataMember(Name="tags", EmitDefaultValue=false)] 26 | public ISet Tags { get; internal set; } 27 | 28 | private string _baseViewKey; 29 | 30 | [DataMember(Name="baseViewKey", EmitDefaultValue=false)] 31 | public string BaseViewKey 32 | { 33 | get 34 | { 35 | if (View != null) 36 | { 37 | return View.Key; 38 | } 39 | else 40 | { 41 | return _baseViewKey; 42 | } 43 | } 44 | set { _baseViewKey = value; } 45 | } 46 | 47 | [JsonConstructor] 48 | internal FilteredView() 49 | { 50 | Mode = FilterMode.Exclude; 51 | Tags = new HashSet(); 52 | } 53 | 54 | internal FilteredView(StaticView view, string key, string description, FilterMode mode, params string[] tags) : this() 55 | { 56 | View = view; 57 | Key = key; 58 | Description = description; 59 | Mode = mode; 60 | 61 | if (tags != null) 62 | { 63 | foreach (string tag in tags) 64 | { 65 | Tags.Add(tag); 66 | } 67 | } 68 | } 69 | 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/Font.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | 7 | namespace Structurizr 8 | { 9 | 10 | [DataContract] 11 | public sealed class Font 12 | { 13 | 14 | private string _url; 15 | 16 | [DataMember(Name = "name", EmitDefaultValue = false)] 17 | public string Name; 18 | 19 | /// 20 | /// The URL where more information about this element can be found. 21 | /// 22 | [DataMember(Name = "url", EmitDefaultValue = false)] 23 | public string Url 24 | { 25 | get 26 | { 27 | return _url; 28 | } 29 | 30 | set 31 | { 32 | if (value != null && value.Trim().Length > 0) 33 | { 34 | if (Util.Url.IsUrl(value)) 35 | { 36 | this._url = value; 37 | } 38 | else 39 | { 40 | throw new ArgumentException(value + " is not a valid URL."); 41 | } 42 | } 43 | } 44 | } 45 | 46 | internal Font() 47 | { 48 | } 49 | 50 | public Font(string name) 51 | { 52 | this.Name = name; 53 | } 54 | 55 | public Font(string name, string url) 56 | { 57 | this.Name = name; 58 | this.Url = url; 59 | } 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Structurizr.Core/View/LayoutMergeStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | /// 5 | /// A pluggable strategy that can be used to copy layout information from one version of a view to another. 6 | /// 7 | public interface LayoutMergeStrategy 8 | { 9 | 10 | /// 11 | /// Attempts to copy the visual layout information (e.g. x,y coordinates) of elements and relationships 12 | /// from the specified source view into the specified destination view. 13 | /// 14 | /// the source view (e.g. the version stored by the Structurizr service) 15 | /// the destination View (e.g. the new version, created locally with code) 16 | void CopyLayoutInformation(View viewWithLayoutInformation, View viewWithoutLayoutInformation); 17 | 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/MetadataSymbols.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr.Core.View 2 | { 3 | 4 | /// 5 | /// The type of symbols to use when rendering metadata. 6 | /// 7 | public enum MetadataSymbols 8 | { 9 | 10 | SquareBrackets, 11 | RoundBrackets, 12 | CurlyBrackets, 13 | AngleBrackets, 14 | DoubleAngleBrackets, 15 | None 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/ParallelSequenceCounter.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | internal class ParallelSequenceCounter : SequenceCounter 5 | { 6 | 7 | internal ParallelSequenceCounter(SequenceCounter parent) : base(parent) 8 | { 9 | Sequence = Parent.Sequence; 10 | } 11 | 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/RankDirection.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum RankDirection 4 | { 5 | TopBottom, 6 | BottomTop, 7 | LeftRight, 8 | RightLeft 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/Routing.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum Routing 4 | { 5 | Direct, 6 | Curved, 7 | Orthogonal 8 | } 9 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/SequenceCounter.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | internal class SequenceCounter 5 | { 6 | 7 | internal readonly SequenceCounter Parent; 8 | internal int Sequence { get; set; } 9 | 10 | internal SequenceCounter() 11 | { 12 | } 13 | 14 | internal SequenceCounter(SequenceCounter parent) 15 | { 16 | Parent = parent; 17 | } 18 | 19 | internal virtual void Increment() 20 | { 21 | Sequence++; 22 | } 23 | 24 | public virtual string AsString() 25 | { 26 | return "" + Sequence; 27 | } 28 | 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/SequenceNumber.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | internal class SequenceNumber 4 | { 5 | 6 | private SequenceCounter _counter = new SequenceCounter(); 7 | 8 | internal SequenceNumber() 9 | { 10 | } 11 | 12 | internal string GetNext() 13 | { 14 | _counter.Increment(); 15 | return _counter.AsString(); 16 | } 17 | 18 | internal void StartParallelSequence() 19 | { 20 | _counter = new ParallelSequenceCounter(_counter); 21 | } 22 | 23 | internal void EndParallelSequence(bool endAllParallelSequencesAndContinueNumbering) 24 | { 25 | if (endAllParallelSequencesAndContinueNumbering) 26 | { 27 | int sequence = _counter.Sequence; 28 | _counter = _counter.Parent; 29 | _counter.Sequence = sequence; 30 | } 31 | else 32 | { 33 | _counter = _counter.Parent; 34 | } 35 | } 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/Shape.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | public enum Shape 4 | { 5 | 6 | Box, 7 | RoundedBox, 8 | Circle, 9 | Ellipse, 10 | Hexagon, 11 | Diamond, 12 | Cylinder, 13 | Pipe, 14 | Person, 15 | Robot, 16 | Folder, 17 | WebBrowser, 18 | MobileDevicePortrait, 19 | MobileDeviceLandscape, 20 | Component 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Structurizr.Core/View/SystemContextView.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | /// 7 | /// A system context view. 8 | /// 9 | [DataContract] 10 | public sealed class SystemContextView : StaticView 11 | { 12 | 13 | public override string Name 14 | { 15 | get 16 | { 17 | return SoftwareSystem.Name + " - System Context"; 18 | } 19 | } 20 | 21 | /// 22 | /// Determines whether the enterprise boundary (to differentiate "internal" elements from "external" elements") should be visible on the resulting diagram. 23 | /// 24 | [DataMember(Name = "enterpriseBoundaryVisible", EmitDefaultValue = false)] 25 | public bool? EnterpriseBoundaryVisible { get; set; } 26 | 27 | internal SystemContextView() : base() 28 | { 29 | } 30 | 31 | internal SystemContextView(SoftwareSystem softwareSystem, string key, string description) : base(softwareSystem, key, description) 32 | { 33 | AddElement(softwareSystem, true); 34 | } 35 | 36 | protected override void CheckElementCanBeAdded(Element element) 37 | { 38 | if (element is Person || element is SoftwareSystem) 39 | { 40 | // all good 41 | } 42 | else 43 | { 44 | throw new ElementNotPermittedInViewException("Only people and software systems can be added to a system context view."); 45 | } 46 | } 47 | 48 | /// 49 | /// Adds all software systems and all people to this view. 50 | /// 51 | public override void AddAllElements() 52 | { 53 | AddAllSoftwareSystems(); 54 | AddAllPeople(); 55 | } 56 | 57 | /// 58 | /// Adds people and software systems that are directly related to the given element. 59 | /// 60 | public override void AddNearestNeighbours(Element element) 61 | { 62 | AddNearestNeighbours(element, typeof(SoftwareSystem)); 63 | AddNearestNeighbours(element, typeof(Person)); 64 | } 65 | 66 | /// 67 | /// Adds the default set of elements to this view. 68 | /// 69 | public override void AddDefaultElements() 70 | { 71 | AddNearestNeighbours(SoftwareSystem, typeof(Person)); 72 | AddNearestNeighbours(SoftwareSystem, typeof(SoftwareSystem)); 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Structurizr.Core/View/Terminology.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace Structurizr.Core.View 4 | { 5 | 6 | /// 7 | /// Provides a way for the terminology on diagrams, etc to be modified (e.g. language translations). 8 | /// 9 | [DataContract] 10 | public sealed class Terminology 11 | { 12 | 13 | [DataMember(Name = "enterprise", EmitDefaultValue = false)] 14 | public string Enterprise; 15 | 16 | [DataMember(Name = "person", EmitDefaultValue = false)] 17 | public string Person; 18 | 19 | [DataMember(Name = "softwareSystem", EmitDefaultValue = false)] 20 | public string SoftwareSystem; 21 | 22 | [DataMember(Name = "container", EmitDefaultValue = false)] 23 | public string Container; 24 | 25 | [DataMember(Name = "component", EmitDefaultValue = false)] 26 | public string Component; 27 | 28 | [DataMember(Name = "code", EmitDefaultValue = false)] 29 | public string Code; 30 | 31 | [DataMember(Name = "deploymentNode", EmitDefaultValue = false)] 32 | public string DeploymentNode; 33 | 34 | [DataMember(Name = "infrastructureNode", EmitDefaultValue = false)] 35 | public string InfrastructureNode; 36 | 37 | [DataMember(Name = "relationship", EmitDefaultValue = false)] 38 | public string Relationship; 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /Structurizr.Core/View/Vertex.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace Structurizr 4 | { 5 | 6 | /// 7 | /// The X, Y coordinate of a bend in a line. 8 | /// 9 | [DataContract] 10 | public sealed class Vertex 11 | { 12 | 13 | internal Vertex() 14 | { 15 | } 16 | 17 | internal Vertex(int x, int y) 18 | { 19 | X = x; 20 | Y = y; 21 | } 22 | 23 | /// 24 | /// The horizontal position of the vertex when rendered. 25 | /// 26 | [DataMember(Name="x", EmitDefaultValue=false)] 27 | public int? X { get; set; } 28 | 29 | 30 | /// 31 | /// The vertical position of the vertex when rendered. 32 | /// 33 | [DataMember(Name="y", EmitDefaultValue=false)] 34 | public int? Y { get; set; } 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Structurizr.Core/View/ViewSortOrder.cs: -------------------------------------------------------------------------------- 1 | namespace Structurizr 2 | { 3 | 4 | /// 5 | /// Allows the sort order of views to be customized as follows: 6 | /// 7 | /// - Default: Views are grouped by the software system they are associated with, and then sorted by type (System Landscape, System Context, Container, Component, Dynamic and Deployment) within these groups. 8 | /// - Type: Views are sorted by type (System Landscape, System Context, Container, Component, Dynamic and Deployment). 9 | /// - Key: Views are sorted by the view key (alphabetical, ascending). 10 | /// 11 | public enum ViewSortOrder 12 | { 13 | 14 | Default, 15 | Type, 16 | Key 17 | 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Structurizr.Core/Workspace.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | using Structurizr.Documentation; 3 | 4 | namespace Structurizr 5 | { 6 | 7 | /// 8 | /// Represents a Structurizr workspace, which is a wrapper for a software architecture model and the associated views. 9 | /// 10 | [DataContract] 11 | public class Workspace : AbstractWorkspace 12 | { 13 | 14 | /// 15 | /// The software architecture model. 16 | /// 17 | /// The software architecture model. 18 | [DataMember(Name = "model", EmitDefaultValue = false)] 19 | public Model Model { get; set; } 20 | 21 | /// 22 | /// The set of views onto a software architecture model. 23 | /// 24 | /// The set of views onto a software architecture model. 25 | [DataMember(Name = "views", EmitDefaultValue = false)] 26 | public ViewSet Views { get; set; } 27 | 28 | /// 29 | /// The documentation associated with this workspace. 30 | /// 31 | [DataMember(Name = "documentation", EmitDefaultValue = false)] 32 | public Documentation.Documentation Documentation { get; set; } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// The name of the workspace.. 38 | /// A short description of the workspace.. 39 | public Workspace(string name, string description) : base(name, description) 40 | { 41 | this.Model = new Model(); 42 | this.Views = new ViewSet(Model); 43 | this.Documentation = new Documentation.Documentation(Model); 44 | } 45 | 46 | public void Hydrate() 47 | { 48 | this.Views.Model = Model; 49 | this.Documentation.Model = Model; 50 | 51 | this.Model.Hydrate(); 52 | this.Views.Hydrate(); 53 | this.Documentation.Hydrate(); 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Structurizr.Examples/ClientSideEncryption.cs: -------------------------------------------------------------------------------- 1 | using Structurizr.Api; 2 | using Structurizr.Encryption; 3 | 4 | namespace Structurizr.Examples 5 | { 6 | 7 | /// 8 | /// This is an example of how to use client-side encryption. 9 | /// 10 | /// You can see the workspace online at https://structurizr.com/share/41 11 | /// (the passphrase is "password") 12 | /// 13 | public class ClientSideEncryption 14 | { 15 | 16 | private const long WorkspaceId = 41; 17 | private const string ApiKey = "key"; 18 | private const string ApiSecret = "secret"; 19 | 20 | static void Main() 21 | { 22 | Workspace workspace = new Workspace("Client-side encrypted workspace", "This is a client-side encrypted workspace. The passphrase is 'password'."); 23 | Model model = workspace.Model; 24 | 25 | Person user = model.AddPerson("User", "A user of my software system."); 26 | SoftwareSystem softwareSystem = model.AddSoftwareSystem("Software System", "My software system."); 27 | user.Uses(softwareSystem, "Uses"); 28 | 29 | ViewSet viewSet = workspace.Views; 30 | SystemContextView contextView = viewSet.CreateSystemContextView(softwareSystem, "SystemContext", "An example of a System Context diagram."); 31 | contextView.AddAllSoftwareSystems(); 32 | contextView.AddAllPeople(); 33 | 34 | Styles styles = viewSet.Configuration.Styles; 35 | styles.Add(new ElementStyle(Tags.SoftwareSystem) { Background = "#d34407", Color = "#ffffff" }); 36 | styles.Add(new ElementStyle(Tags.Person) { Background = "#f86628", Color = "#ffffff", Shape = Shape.Person }); 37 | 38 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 39 | structurizrClient.EncryptionStrategy = new AesEncryptionStrategy("password"); 40 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 41 | } 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /Structurizr.Examples/CorporateBranding.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Structurizr.Api; 3 | using Structurizr.Documentation; 4 | using Structurizr.Util; 5 | 6 | namespace Structurizr.Examples 7 | { 8 | 9 | /// 10 | /// This is a simple example that illustrates the corporate branding features of Structurizr, including: 11 | /// - A logo, which is included in diagrams and documentation. 12 | /// 13 | /// You can see the live workspace at https://structurizr.com/share/35031 14 | /// 15 | public class CorporateBranding 16 | { 17 | 18 | private const long WorkspaceId = 35031; 19 | private const string ApiKey = "key"; 20 | private const string ApiSecret = "secret"; 21 | 22 | static void Main() 23 | { 24 | Workspace workspace = new Workspace("Corporate Branding", "This is a model of my software system."); 25 | Model model = workspace.Model; 26 | 27 | Person user = model.AddPerson("User", "A user of my software system."); 28 | SoftwareSystem softwareSystem = model.AddSoftwareSystem("Software System", "My software system."); 29 | user.Uses(softwareSystem, "Uses"); 30 | 31 | ViewSet views = workspace.Views; 32 | SystemContextView contextView = views.CreateSystemContextView(softwareSystem, "SystemContext", "An example of a System Context diagram."); 33 | contextView.AddAllSoftwareSystems(); 34 | contextView.AddAllPeople(); 35 | 36 | Styles styles = views.Configuration.Styles; 37 | styles.Add(new ElementStyle(Tags.Person) { Shape = Shape.Person }); 38 | 39 | StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace); 40 | template.AddContextSection(softwareSystem, Format.Markdown, "Here is some context about the software system...\n\n![](embed:SystemContext)"); 41 | 42 | Branding branding = views.Configuration.Branding; 43 | branding.Logo = ImageUtils.GetImageAsDataUri(new FileInfo("structurizr-logo.png")); 44 | 45 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 46 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 47 | } 48 | 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0001-record-architecture-decisions.md: -------------------------------------------------------------------------------- 1 | # 1. Record architecture decisions 2 | 3 | Date: 2016-02-12 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | We need to record the architectural decisions made on this project. 12 | 13 | ## Decision 14 | 15 | We will use Architecture Decision Records, as described by Michael Nygard in this article: [http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions) 16 | 17 | ## Consequences 18 | 19 | See Michael Nygard's article, linked above. 20 | 21 | --- 22 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0002-implement-as-shell-scripts.md: -------------------------------------------------------------------------------- 1 | # 2. Implement as shell scripts 2 | 3 | Date: 2016-02-12 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | ADRs are plain text files stored in a subdirectory of the project. 12 | 13 | The tool needs to create new files and apply small edits to 14 | the Status section of existing files. 15 | 16 | ## Decision 17 | 18 | The tool is implemented as shell scripts that use standard Unix 19 | tools -- grep, sed, awk, etc. 20 | 21 | ## Consequences 22 | 23 | The tool won't support Windows. Being plain text files, ADRs can 24 | be created by hand and edited in any text editor. This tool just 25 | makes the process more convenient. 26 | 27 | Development will have to cope with differences between Unix 28 | variants, particularly Linux and MacOS X. 29 | 30 | --- 31 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0003-single-command-with-subcommands.md: -------------------------------------------------------------------------------- 1 | # 3. Single command with subcommands 2 | 3 | Date: 2016-02-12 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | The tool provides a number of related commands to create 12 | and manipulate architecture decision records. 13 | 14 | How can the user find out about the commands that are available? 15 | 16 | ## Decision 17 | 18 | The tool defines a single command, called `adr`. 19 | 20 | The first argument to `adr` (the subcommand) specifies the 21 | action to perform. Further arguments are interpreted by the 22 | subcommand. 23 | 24 | Running `adr` without any arguments lists the available 25 | subcommands. 26 | 27 | Subcommands are implemented as scripts in the same 28 | directory as the `adr` script. E.g. the subcommand `new` is 29 | implemented as the script `adr-new`, the subcommand `help` 30 | as the script `adr-help` and so on. 31 | 32 | Helper scripts that are part of the implementation but not 33 | subcommands follow a different naming convention, so that 34 | subcommands can be listed by filtering and transforming script 35 | file names. 36 | 37 | ## Consequences 38 | 39 | Users can more easily explore the capabilities of the tool. 40 | 41 | Users are already used to this style of command-line tool. For 42 | example, Git works this way. 43 | 44 | Each subcommand can be implemented in the most appropriate 45 | language. 46 | 47 | --- 48 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). 49 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0004-markdown-format.md: -------------------------------------------------------------------------------- 1 | # 4. Markdown format 2 | 3 | Date: 2016-02-12 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | The decision records must be stored in a plain text format: 12 | 13 | * This works well with version control systems. 14 | 15 | * It allows the tool to modify the status of records and insert 16 | hyperlinks when one decision supercedes another. 17 | 18 | * Decisions can be read in the terminal, IDE, version control 19 | browser, etc. 20 | 21 | People will want to use some formatting: lists, code examples, 22 | and so on. 23 | 24 | People will want to view the decision records in a more readable 25 | format than plain text, and maybe print them out. 26 | 27 | 28 | ## Decision 29 | 30 | Record architecture decisions in [Markdown format](https://daringfireball.net/projects/markdown/). 31 | 32 | ## Consequences 33 | 34 | Decisions can be read in the terminal. 35 | 36 | Decisions will be formatted nicely and hyperlinked by the 37 | browsers of project hosting sites like GitHub and Bitbucket. 38 | 39 | Tools like [Pandoc](http://pandoc.org/) can be used to convert 40 | the decision records into HTML or PDF. 41 | 42 | --- 43 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0005-help-comments.md: -------------------------------------------------------------------------------- 1 | # 5. Help comments 2 | 3 | Date: 2016-02-13 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | The tool will have a `help` subcommand to provide documentation 12 | for users. 13 | 14 | It's nice to have usage documentation in the script files 15 | themselves, in comments. When reading the code, that's the first 16 | place to look for information about how to run a script. 17 | 18 | ## Decision 19 | 20 | Write usage documentation in comments in the source file. 21 | 22 | Distinguish between documentation comments and normal comments. 23 | Documentation comments have two hash characters at the start of 24 | the line. 25 | 26 | The `adr help` command can parse comments out from the script 27 | using the standard Unix tools `grep` and `cut`. 28 | 29 | ## Consequences 30 | 31 | No need to maintain help text in a separate file. 32 | 33 | Help text can easily be kept up to date as the script is edited. 34 | 35 | There's no automated check that the help text is up to date. The 36 | tests do not work well as documentation for users, and the help 37 | text is not easily cross-checked against the code. 38 | 39 | This won't work if any subcommands are not implemented as scripts 40 | that use '#' as a comment character. 41 | 42 | --- 43 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0006-packaging-and-distribution-in-other-version-control-repositories.md: -------------------------------------------------------------------------------- 1 | # 6. Packaging and distribution in other version control repositories 2 | 3 | Date: 2016-02-16 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | Users want to install adr-tools with their preferred package 12 | manager. For example, Ubuntu users use `apt`, RedHat users use 13 | `yum` and Mac OS X users use [Homebrew](http://brew.sh). 14 | 15 | The developers of `adr-tools` don't know how, nor have permissions, 16 | to use all these packaging and distribution systems. Therefore packaging 17 | and distribution must be done by "downstream" parties. 18 | 19 | The developers of the tool should not favour any one particular 20 | packaging and distribution solution. 21 | 22 | ## Decision 23 | 24 | The `adr-tools` project will not contain any packaging or 25 | distribution scripts and config. 26 | 27 | Packaging and distribution will be managed by other projects in 28 | separate version control repositories. 29 | 30 | ## Consequences 31 | 32 | The git repo of this project will be simpler. 33 | 34 | Eventually, users will not have to use Git to get the software. 35 | 36 | We will have to tag releases in the `adr-tools` repository so that 37 | packaging projects know what can be published and how it should be 38 | identified. 39 | 40 | We will document how users can install the software in this 41 | project's README file. 42 | 43 | --- 44 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0007-invoke-adr-config-executable-to-get-configuration.md: -------------------------------------------------------------------------------- 1 | # 7. Invoke adr-config executable to get configuration 2 | 3 | Date: 2016-12-17 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | Packagers (e.g. Homebrew developers) want to configure adr-tools to match the conventions of their installation. 12 | 13 | Currently, this is done by sourcing a file `config.sh`, which should sit beside the `adr` executable. 14 | 15 | This name is too common. 16 | 17 | The `config.sh` file is not executable, and so doesn't belong in a bin directory. 18 | 19 | ## Decision 20 | 21 | Replace `config.sh` with an executable, named `adr-config` that outputs configuration. 22 | 23 | Each script in ADR Tools will eval the output of `adr-config` to configure itself. 24 | 25 | ## Consequences 26 | 27 | Configuration within ADR Tools is a little more complicated. 28 | 29 | Packagers can write their own implementation of `adr-config` that outputs configuration that matches the platform's installation conventions, and deploy it next to the `adr` script. 30 | 31 | To make development easier, the implementation of `adr-config` in the project's src/ directory will output configuration that lets the tool to run from the src/ directory without any installation step. (Packagers should not include this script in a deployable package.) 32 | 33 | --- 34 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/adr/0008-use-iso-8601-format-for-dates.md: -------------------------------------------------------------------------------- 1 | # 8. Use ISO 8601 Format for Dates 2 | 3 | Date: 2017-02-21 4 | 5 | ## Status 6 | 7 | Accepted 8 | 9 | ## Context 10 | 11 | `adr-tools` seeks to communicate the history of architectural decisions of a 12 | project. An important component of the history is the time at which a decision 13 | was made. 14 | 15 | To communicate effectively, `adr-tools` should present information as 16 | unambiguously as possible. That means that culture-neutral data formats should 17 | be preferred over culture-specific formats. 18 | 19 | Existing `adr-tools` deployments format dates as `dd/mm/yyyy` by default. That 20 | formatting is common formatting in the United Kingdom (where the `adr-tools` 21 | project was originally written), but is easily confused with the `mm/dd/yyyy` 22 | format preferred in the United States. 23 | 24 | The default date format may be overridden by setting `ADR_DATE` in `config.sh`. 25 | 26 | ## Decision 27 | 28 | `adr-tools` will use the ISO 8601 format for dates: `yyyy-mm-dd` 29 | 30 | ## Consequences 31 | 32 | Dates are displayed in a standard, culture-neutral format. 33 | 34 | The UK-style and ISO 8601 formats can be distinguished by their separator 35 | character. The UK-style dates used a slash (`/`), while the ISO dates use a 36 | hyphen (`-`). 37 | 38 | Prior to this decision, `adr-tools` was deployed using the UK format for dates. 39 | After adopting the ISO 8601 format, existing deployments of `adr-tools` must do 40 | one of the following: 41 | 42 | * Accept mixed formatting of dates within their documentation library. 43 | * Update existing documents to use ISO 8601 dates by running `adr upgrade-repository` 44 | 45 | --- 46 | This Architecture Decision Record (ADR) was written by Nat Pryce as a part of [adr-tools](https://github.com/npryce/adr-tools), and is reproduced here under the [Creative Commons Attribution 4.0 International (CC BY 4.0) license](https://creativecommons.org/licenses/by/4.0/). -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/01-introduction-and-goals.adoc: -------------------------------------------------------------------------------- 1 | == Introduction and Goals 2 | 3 | === Requirements Overview 4 | 5 | === Quality Goals 6 | 7 | === Stakeholders 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/02-architecture-constraints.adoc: -------------------------------------------------------------------------------- 1 | == Architecture Constraints 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/03-system-scope-and-context.adoc: -------------------------------------------------------------------------------- 1 | == Context and Scope 2 | 3 | image::embed:SystemContext[] 4 | 5 | === Business Context 6 | 7 | === Technical Context 8 | 9 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/04-solution-strategy.adoc: -------------------------------------------------------------------------------- 1 | == Solution Strategy 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/05-building-block-view.adoc: -------------------------------------------------------------------------------- 1 | == Building Block View 2 | 3 | === Level 1 4 | 5 | === Level 2 6 | 7 | === Level 3 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/06-runtime-view.adoc: -------------------------------------------------------------------------------- 1 | == Runtime View 2 | 3 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/07-deployment-view.adoc: -------------------------------------------------------------------------------- 1 | == Deployment View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/08-crosscutting-concepts.adoc: -------------------------------------------------------------------------------- 1 | == Crosscutting Concepts 2 | 3 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/09-architecture-decisions.adoc: -------------------------------------------------------------------------------- 1 | == Architecture Decisions 2 | 3 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/10-quality-requirements.adoc: -------------------------------------------------------------------------------- 1 | == Quality Requirements 2 | 3 | === Quality Tree 4 | 5 | === Quality Scenarios 6 | 7 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/11-risks-and-technical-debt.adoc: -------------------------------------------------------------------------------- 1 | == Risks and Technical Debt 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/asciidoc/12-glossary.adoc: -------------------------------------------------------------------------------- 1 | == Glossary 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/01-introduction-and-goals.md: -------------------------------------------------------------------------------- 1 | ## Introduction and Goals 2 | 3 | ### Requirements Overview 4 | 5 | ### Quality Goals 6 | 7 | ### Stakeholders 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/02-architecture-constraints.md: -------------------------------------------------------------------------------- 1 | ## Architecture Constraints 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/03-system-scope-and-context.md: -------------------------------------------------------------------------------- 1 | ## Context and Scope 2 | 3 | ![](embed:SystemContext) 4 | 5 | ### Business Context 6 | 7 | ### Technical Context 8 | 9 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/04-solution-strategy.md: -------------------------------------------------------------------------------- 1 | ## Solution Strategy 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/05-building-block-view.md: -------------------------------------------------------------------------------- 1 | ## Building Block View 2 | 3 | ### Level 1 4 | 5 | ### Level 2 6 | 7 | ### Level 3 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/06-runtime-view.md: -------------------------------------------------------------------------------- 1 | ## Runtime View 2 | 3 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/07-deployment-view.md: -------------------------------------------------------------------------------- 1 | ## Deployment View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/08-crosscutting-concepts.md: -------------------------------------------------------------------------------- 1 | ## Crosscutting Concepts 2 | 3 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/09-architecture-decisions.md: -------------------------------------------------------------------------------- 1 | ## Architecture Decisions 2 | 3 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/10-quality-requirements.md: -------------------------------------------------------------------------------- 1 | ## Quality Requirements 2 | 3 | ### Quality Tree 4 | 5 | ### Quality Scenarios 6 | 7 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/11-risks-and-technical-debt.md: -------------------------------------------------------------------------------- 1 | ## Risks and Technical Debt 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/arc42/markdown/12-glossary.md: -------------------------------------------------------------------------------- 1 | ## Glossary 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/01-context.adoc: -------------------------------------------------------------------------------- 1 | == Context 2 | 3 | image::embed:SystemContext[] 4 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/02-functional-overview.adoc: -------------------------------------------------------------------------------- 1 | == Functional Overview 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/03-quality-attributes.adoc: -------------------------------------------------------------------------------- 1 | == Quality Attributes 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/04-constraints.adoc: -------------------------------------------------------------------------------- 1 | == Constraints 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/05-principles.adoc: -------------------------------------------------------------------------------- 1 | == Principles 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/06-software-architecture.adoc: -------------------------------------------------------------------------------- 1 | == Software Architecture -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/07-data.adoc: -------------------------------------------------------------------------------- 1 | == Data 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/08-infrastructure-architecture.adoc: -------------------------------------------------------------------------------- 1 | == Infrastructure Architecture 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/09-deployment.adoc: -------------------------------------------------------------------------------- 1 | == Deployment 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/10-development-environment.adoc: -------------------------------------------------------------------------------- 1 | == Development Environment 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/11-operation-and-support.adoc: -------------------------------------------------------------------------------- 1 | == Operations and Support 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/asciidoc/12-decision-log.adoc: -------------------------------------------------------------------------------- 1 | == Decision Log 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/01-context.md: -------------------------------------------------------------------------------- 1 | ## Context 2 | 3 | ![](embed:SystemContext) -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/02-functional-overview.md: -------------------------------------------------------------------------------- 1 | ## Functional Overview 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/03-quality-attributes.md: -------------------------------------------------------------------------------- 1 | ## Quality Attributes 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/04-constraints.md: -------------------------------------------------------------------------------- 1 | ## Constraints 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/05-principles.md: -------------------------------------------------------------------------------- 1 | ## Principles 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/06-software-architecture.md: -------------------------------------------------------------------------------- 1 | ## Software Architecture -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/07-data.md: -------------------------------------------------------------------------------- 1 | ## Data 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/08-infrastructure-architecture.md: -------------------------------------------------------------------------------- 1 | ## Infrastructure Architecture 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/09-deployment.md: -------------------------------------------------------------------------------- 1 | ## Deployment 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/10-development-environment.md: -------------------------------------------------------------------------------- 1 | ## Development Environment 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/11-operation-and-support.md: -------------------------------------------------------------------------------- 1 | ## Operations and Support 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/structurizr/markdown/12-decision-log.md: -------------------------------------------------------------------------------- 1 | ## Decision Log 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/01-introduction.adoc: -------------------------------------------------------------------------------- 1 | == Introduction 2 | 3 | === Purpose and Scope 4 | 5 | === Audience 6 | 7 | === Status 8 | 9 | === Architectural Design Approach 10 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/02-glossary.adoc: -------------------------------------------------------------------------------- 1 | == Glossary 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/03-system-stakeholders-and-requirements.adoc: -------------------------------------------------------------------------------- 1 | == System Stakeholders and Requirements 2 | 3 | === Stakeholders 4 | 5 | === Overview of Requirements 6 | 7 | === System Scenarios 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/04-architectural-forces.adoc: -------------------------------------------------------------------------------- 1 | == Architectural Forces 2 | 3 | === Goals 4 | 5 | === Constraints 6 | 7 | === Architectural Principles 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/01-architectural-views.adoc: -------------------------------------------------------------------------------- 1 | == Architectural Views 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/02-context-view.adoc: -------------------------------------------------------------------------------- 1 | === Context View 2 | 3 | image::embed:SystemContext[] 4 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/03-functional-view.adoc: -------------------------------------------------------------------------------- 1 | === Functional View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/04-information-view.adoc: -------------------------------------------------------------------------------- 1 | === Information View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/05-concurrency-view.adoc: -------------------------------------------------------------------------------- 1 | === Concurrency View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/06-deployment-view.adoc: -------------------------------------------------------------------------------- 1 | === Deployment View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/07-development-view.adoc: -------------------------------------------------------------------------------- 1 | === Development View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/05-architectural-views/08-operational-view.adoc: -------------------------------------------------------------------------------- 1 | === Operational View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/06-system-qualities.adoc: -------------------------------------------------------------------------------- 1 | == System Qualities 2 | 3 | === Performance and Scalability 4 | 5 | === Security 6 | 7 | === Availability and Resilience 8 | 9 | === Evolution 10 | 11 | === Other Qualities 12 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/asciidoc/07-appendices.adoc: -------------------------------------------------------------------------------- 1 | == Appendices 2 | 3 | === Decisions and Alternatives 4 | 5 | === Questions and Answers 6 | 7 | === References 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/01-introduction.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | ### Purpose and Scope 4 | 5 | ### Audience 6 | 7 | ### Status 8 | 9 | ### Architectural Design Approach 10 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/02-glossary.md: -------------------------------------------------------------------------------- 1 | ## Glossary 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/03-system-stakeholders-and-requirements.md: -------------------------------------------------------------------------------- 1 | ## System Stakeholders and Requirements 2 | 3 | ### Stakeholders 4 | 5 | ### Overview of Requirements 6 | 7 | ### System Scenarios 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/04-architectural-forces.md: -------------------------------------------------------------------------------- 1 | ## Architectural Forces 2 | 3 | ### Goals 4 | 5 | ### Constraints 6 | 7 | ### Architectural Principles 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/01-architectural-views.md: -------------------------------------------------------------------------------- 1 | ## Architectural Views 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/02-context-view.md: -------------------------------------------------------------------------------- 1 | ### Context View 2 | 3 | ![](embed:SystemContext) 4 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/03-functional-view.md: -------------------------------------------------------------------------------- 1 | ### Functional View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/04-information-view.md: -------------------------------------------------------------------------------- 1 | ### Information View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/05-concurrency-view.md: -------------------------------------------------------------------------------- 1 | ### Concurrency View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/06-deployment-view.md: -------------------------------------------------------------------------------- 1 | ### Deployment View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/07-development-view.md: -------------------------------------------------------------------------------- 1 | ### Development View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/05-architectural-views/08-operational-view.md: -------------------------------------------------------------------------------- 1 | ### Operational View 2 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/06-system-qualities.md: -------------------------------------------------------------------------------- 1 | ## System Qualities 2 | 3 | ### Performance and Scalability 4 | 5 | ### Security 6 | 7 | ### Availability and Resilience 8 | 9 | ### Evolution 10 | 11 | ### Other Qualities 12 | -------------------------------------------------------------------------------- /Structurizr.Examples/Documentation/viewpointsandperspectives/markdown/07-appendices.md: -------------------------------------------------------------------------------- 1 | ## Appendices 2 | 3 | ### Decisions and Alternatives 4 | 5 | ### Questions and Answers 6 | 7 | ### References 8 | -------------------------------------------------------------------------------- /Structurizr.Examples/FilteredViews.cs: -------------------------------------------------------------------------------- 1 | using Structurizr.Api; 2 | 3 | namespace Structurizr.Examples 4 | { 5 | 6 | /// 7 | /// An example of how to use filtered views to show "before" and "after" views of a software system. 8 | /// 9 | /// You can see the live diagrams at https://structurizr.com/public/19911 10 | /// 11 | public class FilteredViews 12 | { 13 | 14 | private const long WorkspaceId = 19911; 15 | private const string ApiKey = ""; 16 | private const string ApiSecret = ""; 17 | 18 | private const string CurrentState = "Current State"; 19 | private const string FutureState = "Future State"; 20 | 21 | static void Main() 22 | { 23 | Workspace workspace = new Workspace("Filtered Views", "An example of using filtered views."); 24 | Model model = workspace.Model; 25 | 26 | Person user = model.AddPerson("User", "A description of the user."); 27 | SoftwareSystem softwareSystemA = model.AddSoftwareSystem("Software System A", "A description of software system A."); 28 | SoftwareSystem softwareSystemB = model.AddSoftwareSystem("Software System B", "A description of software system B."); 29 | softwareSystemB.AddTags(FutureState); 30 | 31 | user.Uses(softwareSystemA, "Uses for tasks 1 and 2").AddTags(CurrentState); 32 | user.Uses(softwareSystemA, "Uses for task 1").AddTags(FutureState); 33 | user.Uses(softwareSystemB, "Uses for task 2").AddTags(FutureState); 34 | 35 | ViewSet views = workspace.Views; 36 | SystemLandscapeView systemLandscapeView = views.CreateSystemLandscapeView("EnterpriseContext", "An example Enterprise Context diagram."); 37 | systemLandscapeView.AddAllElements(); 38 | 39 | views.CreateFilteredView(systemLandscapeView, "CurrentState", "The current context.", FilterMode.Exclude, FutureState); 40 | views.CreateFilteredView(systemLandscapeView, "FutureState", "The future state context after Software System B is live.", FilterMode.Exclude, CurrentState); 41 | 42 | Styles styles = views.Configuration.Styles; 43 | styles.Add(new ElementStyle(Tags.Element) { Color = "#ffffff" }); 44 | styles.Add(new ElementStyle(Tags.SoftwareSystem) { Background = "#91a437", Shape = Shape.RoundedBox }); 45 | styles.Add(new ElementStyle(Tags.Person) { Background = "#6a7b15", Shape = Shape.Person }); 46 | 47 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 48 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 49 | } 50 | 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /Structurizr.Examples/FinancialRiskSystem/context.adoc: -------------------------------------------------------------------------------- 1 | == Context 2 | 3 | A global investment bank based in London, New York and Singapore trades (buys and sells) financial products with other banks (counterparties). When share prices on the stock markets move up or down, the bank either makes money or loses it. At the end of the working day, the bank needs to gain a view of how much risk they are exposed to (e.g. of losing money) by running some calculations on the data held about their trades. The bank has an existing Trade Data System (TDS) and Reference Data System (RDS) but need a new Risk System. 4 | 5 | image::embed:Context[] 6 | 7 | === Trade Data System 8 | 9 | The Trade Data System maintains a store of all trades made by the bank. It is already configured to generate a file-based XML export of trade data at the close of business (5pm) in New York. The export includes the following information for every trade made by the bank: 10 | 11 | * Trade ID 12 | * Date 13 | * Current trade value in US dollars 14 | * Counterparty ID 15 | 16 | === Reference Data System 17 | 18 | The Reference Data System maintains all of the reference data needed by the bank. This includes information about counterparties; each of which represents an individual, a bank, etc. A file-based XML export is also available and includes basic information about each counterparty. A new organisation-wide reference data system is due for completion in the next 3 months, with the current system eventually being decommissioned. -------------------------------------------------------------------------------- /Structurizr.Examples/FinancialRiskSystem/context.md: -------------------------------------------------------------------------------- 1 | ## Context 2 | 3 | A global investment bank based in London, New York and Singapore trades (buys and sells) financial products with other banks (counterparties). When share prices on the stock markets move up or down, the bank either makes money or loses it. At the end of the working day, the bank needs to gain a view of how much risk they are exposed to (e.g. of losing money) by running some calculations on the data held about their trades. The bank has an existing Trade Data System (TDS) and Reference Data System (RDS) but need a new Risk System. 4 | 5 | ![](embed:Context) 6 | 7 | ### Trade Data System 8 | 9 | The Trade Data System maintains a store of all trades made by the bank. It is already configured to generate a file-based XML export of trade data at the close of business (5pm) in New York. The export includes the following information for every trade made by the bank: 10 | 11 | - Trade ID 12 | - Date 13 | - Current trade value in US dollars 14 | - Counterparty ID 15 | 16 | ### Reference Data System 17 | 18 | The Reference Data System maintains all of the reference data needed by the bank. This includes information about counterparties; each of which represents an individual, a bank, etc. A file-based XML export is also available and includes basic information about each counterparty. A new organisation-wide reference data system is due for completion in the next 3 months, with the current system eventually being decommissioned. -------------------------------------------------------------------------------- /Structurizr.Examples/FinancialRiskSystem/functional-overview.md: -------------------------------------------------------------------------------- 1 | ## Functional Overview 2 | 3 | The high-level functional requirements for the new Risk System are as follows. 4 | 5 | ![Functional overview](images/functional-overview.png) 6 | 7 | 1. Import trade data from the Trade Data System. 8 | 2. Import counterparty data from the Reference Data System. 9 | 3. Join the two sets of data together, enriching the trade data with information about the counterparty. 10 | 4. For each counterparty, calculate the risk that the bank is exposed to. 11 | 5. Generate a report that can be imported into Microsoft Excel containing the risk figures for all counterparties known by the bank. 12 | 6. Distribute the report to the business users before the start of the next trading day (9am) in Singapore. 13 | 7. Provide a way for a subset of the business users to configure and maintain the external parameters used by the risk calculations. 14 | -------------------------------------------------------------------------------- /Structurizr.Examples/FinancialRiskSystem/images/functional-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Examples/FinancialRiskSystem/images/functional-overview.png -------------------------------------------------------------------------------- /Structurizr.Examples/GettingStarted.cs: -------------------------------------------------------------------------------- 1 | using Structurizr.Api; 2 | 3 | namespace Structurizr.Examples 4 | { 5 | 6 | /// 7 | /// A "getting started" example that illustrates how to 8 | /// create a software architecture diagram using code. 9 | /// 10 | /// The live workspace is available to view at https://structurizr.com/share/25441 11 | /// 12 | class GettingStarted 13 | { 14 | 15 | private const long WorkspaceId = 25441; 16 | private const string ApiKey = "key"; 17 | private const string ApiSecret = "secret"; 18 | 19 | static void Main() 20 | { 21 | Workspace workspace = new Workspace("Getting Started", "This is a model of my software system."); 22 | Model model = workspace.Model; 23 | 24 | Person user = model.AddPerson("User", "A user of my software system."); 25 | SoftwareSystem softwareSystem = model.AddSoftwareSystem("Software System", "My software system."); 26 | user.Uses(softwareSystem, "Uses"); 27 | 28 | ViewSet viewSet = workspace.Views; 29 | SystemContextView contextView = viewSet.CreateSystemContextView(softwareSystem, "SystemContext", "An example of a System Context diagram."); 30 | contextView.AddAllSoftwareSystems(); 31 | contextView.AddAllPeople(); 32 | 33 | Styles styles = viewSet.Configuration.Styles; 34 | styles.Add(new ElementStyle(Tags.SoftwareSystem) { Background = "#1168bd", Color = "#ffffff" }); 35 | styles.Add(new ElementStyle(Tags.Person) { Background = "#08427b", Color = "#ffffff", Shape = Shape.Person }); 36 | 37 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 38 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 39 | } 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /Structurizr.Examples/StylingElements.cs: -------------------------------------------------------------------------------- 1 | using Structurizr.Api; 2 | 3 | namespace Structurizr.Examples 4 | { 5 | 6 | /// 7 | /// An example of how to style elements on diagrams. 8 | /// 9 | /// The live workspace is available to view at https://structurizr.com/share/36111 10 | /// 11 | class StylingElements 12 | { 13 | 14 | private const long WorkspaceId = 36111; 15 | private const string ApiKey = "key"; 16 | private const string ApiSecret = "secret"; 17 | 18 | static void Main() 19 | { 20 | Workspace workspace = new Workspace("Styling Elements", "This is a model of my software system."); 21 | Model model = workspace.Model; 22 | 23 | Person user = model.AddPerson("User", "A user of my software system."); 24 | SoftwareSystem softwareSystem = model.AddSoftwareSystem("Software System", "My software system."); 25 | Container webApplication = softwareSystem.AddContainer("Web Application", "My web application.", "Java and Spring MVC"); 26 | Container database = softwareSystem.AddContainer("Database", "My database.", "Relational database schema"); 27 | user.Uses(webApplication, "Uses", "HTTPS"); 28 | webApplication.Uses(database, "Reads from and writes to", "JDBC"); 29 | 30 | ViewSet views = workspace.Views; 31 | ContainerView containerView = views.CreateContainerView(softwareSystem, "containers", "An example of a container diagram."); 32 | containerView.AddAllElements(); 33 | 34 | Styles styles = workspace.Views.Configuration.Styles; 35 | 36 | // example 1 37 | // styles.Add(new ElementStyle(Tags.Element) { Background = "#438dd5", Color = "#ffffff" }); 38 | 39 | // example 2 40 | // styles.Add(new ElementStyle(Tags.Element) { Color = "#ffffff" }); 41 | // styles.Add(new ElementStyle(Tags.Person) { Background = "#08427b" }); 42 | // styles.Add(new ElementStyle(Tags.Container) { Background = "#438dd5" }); 43 | 44 | // example 3 45 | // styles.Add(new ElementStyle(Tags.Element) { Color = "#ffffff" }); 46 | // styles.Add(new ElementStyle(Tags.Person) { Background = "#08427b" , Shape = Shape.Person }); 47 | // styles.Add(new ElementStyle(Tags.Container) { Background = "#438dd5" }); 48 | // database.AddTags("Database"); 49 | // styles.Add(new ElementStyle("Database") { Shape = Shape.Cylinder }); 50 | 51 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 52 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 53 | } 54 | 55 | } 56 | } -------------------------------------------------------------------------------- /Structurizr.Examples/StylingRelationships.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Structurizr.Api; 3 | 4 | namespace Structurizr.Examples 5 | { 6 | 7 | /// 8 | /// An example of how to style relationships on diagrams. 9 | /// 10 | /// The live workspace is available to view at https://structurizr.com/share/36131 11 | /// 12 | class StylingRelationships 13 | { 14 | 15 | private const long WorkspaceId = 36131; 16 | private const string ApiKey = "key"; 17 | private const string ApiSecret = "secret"; 18 | 19 | static void Main() 20 | { 21 | Workspace workspace = new Workspace("Styling Relationships", "This is a model of my software system."); 22 | Model model = workspace.Model; 23 | 24 | Person user = model.AddPerson("User", "A user of my software system."); 25 | SoftwareSystem softwareSystem = model.AddSoftwareSystem("Software System", "My software system."); 26 | Container webApplication = softwareSystem.AddContainer("Web Application", "My web application.", "Java and Spring MVC"); 27 | Container database = softwareSystem.AddContainer("Database", "My database.", "Relational database schema"); 28 | user.Uses(webApplication, "Uses", "HTTPS"); 29 | webApplication.Uses(database, "Reads from and writes to", "JDBC"); 30 | 31 | ViewSet views = workspace.Views; 32 | ContainerView containerView = views.CreateContainerView(softwareSystem, "containers", "An example of a container diagram."); 33 | containerView.AddAllElements(); 34 | 35 | Styles styles = workspace.Views.Configuration.Styles; 36 | 37 | // example 1 38 | // styles.Add(new RelationshipStyle(Tags.Relationship) { Color = "#ff0000" }); 39 | 40 | // example 2 41 | // model.Relationships.Where(r => "HTTPS".Equals(r.Technology)).ToList().ForEach(r => r.AddTags("HTTPS")); 42 | // model.Relationships.Where(r => "JDBC".Equals(r.Technology)).ToList().ForEach(r => r.AddTags("JDBC")); 43 | // styles.Add(new RelationshipStyle("HTTPS") { Color = "#ff0000" }); 44 | // styles.Add(new RelationshipStyle("JDBC") { Color = "#0000ff" }); 45 | 46 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 47 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 48 | } 49 | 50 | } 51 | } -------------------------------------------------------------------------------- /Structurizr.Examples/Theme.cs: -------------------------------------------------------------------------------- 1 | using Structurizr.Api; 2 | 3 | namespace Structurizr.Examples 4 | { 5 | 6 | /// 7 | /// This is an example of how to use an external theme. 8 | /// 9 | /// The live workspace is available to view at https://structurizr.com/share/38898 10 | /// 11 | class Theme 12 | { 13 | 14 | private const long WorkspaceId = 38898; 15 | private const string ApiKey = ""; 16 | private const string ApiSecret = ""; 17 | 18 | static void Main() 19 | { 20 | Workspace workspace = new Workspace("Theme", "This is a model of my software system."); 21 | Model model = workspace.Model; 22 | 23 | Person user = model.AddPerson("User", "A user of my software system."); 24 | SoftwareSystem softwareSystem = model.AddSoftwareSystem("Software System", "My software system."); 25 | user.Uses(softwareSystem, "Uses"); 26 | 27 | ViewSet viewSet = workspace.Views; 28 | SystemContextView contextView = viewSet.CreateSystemContextView(softwareSystem, "SystemContext", "An example of a System Context diagram."); 29 | contextView.AddAllSoftwareSystems(); 30 | contextView.AddAllPeople(); 31 | 32 | // add a theme 33 | viewSet.Configuration.Theme = "https://raw.githubusercontent.com/structurizr/dotnet/master/Structurizr.Examples/Theme/theme.json"; 34 | 35 | StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret); 36 | structurizrClient.PutWorkspace(WorkspaceId, workspace); 37 | } 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /Structurizr.Examples/Theme/theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "elements": [ 3 | { 4 | "tag": "Software System", 5 | "background": "#1168bd", 6 | "color": "#ffffff" 7 | }, 8 | { 9 | "tag": "Person", 10 | "background": "#08427b", 11 | "color": "#ffffff", 12 | "shape": "Person" 13 | } 14 | ], 15 | "relationships": [] 16 | } -------------------------------------------------------------------------------- /Structurizr.Examples/structurizr-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/Structurizr.Examples/structurizr-logo.png -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | pull_requests: 3 | do_not_increment_build_number: true 4 | image: Visual Studio 2017 5 | build_script: 6 | - ps: >- 7 | dotnet restore 8 | 9 | dotnet build 10 | 11 | 12 | dotnet clean /p:Configuration=Release 13 | 14 | if ($env:APPVEYOR_REPO_TAG -Eq "true") { 15 | dotnet msbuild "/t:Restore;Pack" /p:Configuration=Release /p:Version=$env:APPVEYOR_REPO_TAG_NAME 16 | } else { 17 | dotnet msbuild "/t:Restore;Pack" /p:Configuration=Release /p:VersionSuffix=pre${env:APPVEYOR_BUILD_NUMBER}-$($env:APPVEYOR_REPO_COMMIT.Substring(0,8)) 18 | } 19 | test_script: 20 | - ps: dotnet test .\Structurizr.Core.Tests\Structurizr.Core.Tests.csproj 21 | - ps: dotnet test .\Structurizr.Client.Tests\Structurizr.Client.Tests.csproj 22 | artifacts: 23 | - path: '*\bin\Release\*.nupkg' -------------------------------------------------------------------------------- /docs/api-client.md: -------------------------------------------------------------------------------- 1 | # API client 2 | 3 | The Structurizr for .NET library includes a client for the [Structurizr web API](https://api.structurizr.com), which allows you to get and put workspaces using JSON over HTTPS. This page provides a quick overview of how to use the API client. 4 | 5 | ## Configuration 6 | 7 | To configure the API client, simply provide values for the API key and API secret programmatically when creating a ```StructurizrClient``` instance. Each workspace has its own API key and secret, the values for which can be found on [your dashboard](https://structurizr.com/dashboard). 8 | 9 | ```c# 10 | StructurizrClient structurizrClient = new StructurizrClient("key", "secret"); 11 | ``` 12 | 13 | If you're using the [on-premises installation](https://structurizr.com/help/on-premises-ui), there is a three argument version of the constructor where you can also specify the API URL. 14 | 15 | ```c# 16 | StructurizrClient structurizrClient = new StructurizrClient("url", "key", "secret"); 17 | ``` 18 | 19 | ## Usage 20 | 21 | The following operations are available on the API client. 22 | 23 | ### 1. GetWorkspace 24 | 25 | This allows you to get the content of a workspace. 26 | 27 | ```c# 28 | Workspace workspace = structurizrClient.GetWorkspace(1234); 29 | ``` 30 | 31 | By default, a copy of the workspace (as JSON) is archived to the current working directory. You can modify this behaviour by setting the ```WorkspaceArchiveLocation``` property. A ```null``` value will disable archiving. 32 | 33 | ### 2. PutWorkspace 34 | 35 | This allows you to overwrite an existing workspace. If the ```MergeFromRemote``` property (on the ```StructurizrClient``` instance) is set to ```true``` (this is the default), any layout information (i.e. the location of boxes on diagrams) is preserved where possible (i.e. where diagram elements haven't been renamed). 36 | 37 | ```c# 38 | structurizrClient.PutWorkspace(1234, workspace); 39 | ``` 40 | 41 | ### 3. LockWorkspace 42 | 43 | If your workspace supports sharing (not available with the Free Plan), you can optionally attempt to lock your workspace before writing to it, to prevent concurrent updates. 44 | 45 | ```c# 46 | structurizrClient.LockWorkspace(1234); 47 | ``` 48 | 49 | This method returns a boolean; ```true``` if the workspace could be locked, ```false``` otherwise. 50 | 51 | ### 4. UnlockWorkspace 52 | 53 | Similarly, you can unlock a workspace. 54 | 55 | ```c# 56 | structurizrClient.UnlockWorkspace(1234); 57 | ``` 58 | 59 | This method also returns a boolean; ```true``` if the workspace could be unlocked, ```false``` otherwise. 60 | 61 | -------------------------------------------------------------------------------- /docs/binaries.md: -------------------------------------------------------------------------------- 1 | # Binaries 2 | 3 | The "Structurizr for .NET" binaries are hosted on [NuGet](https://www.nuget.org/profiles/structurizr) as follows: 4 | 5 | Name | Description 6 | --------------------- | --------------------------------------------------------------------------------------------------------------------------- 7 | Structurizr.Core | The basic library that can used to create software architecture models. 8 | Structurizr.Client | The API client for publishing models on the Structurizr cloud service and on-premises installation. -------------------------------------------------------------------------------- /docs/client-side-encryption.md: -------------------------------------------------------------------------------- 1 | # Client-side encryption 2 | 3 | > Note: this page describes a feature that is not available to use with Structurizr's Free Plan. 4 | 5 | The JSON representation of your workspace is stored on the Structurizr servers using AES encryption with a 128-bit key, a random salt and a server-side passphrase. For additional peace of mind, you can choose to encrypt your workspace with your own passphrase on the client before uploading it to Structurizr. In order to view a client-side encrypted workspace, you will be asked to enter your passphrase when you open the workspace in your web browser. The passphrase is then used to decrypt the workspace in your web browser - at no point does the passphrase leave your computer. 6 | 7 | To use client-side encryption, simply create an instance of ```AesEncryptionStrategy``` and associate it with your ```StructurizrClient``` instance. For example: 8 | 9 | ```c# 10 | StructurizrClient structurizrClient = new StructurizrClient("key", "secret"); 11 | structurizrClient.EncryptionStrategy = new AesEncryptionStrategy("password"); 12 | structurizrClient.PutWorkspace(1234, workspace); 13 | ``` 14 | 15 | The default key size is 128 bits and the default iteration count is 1000. An alternative constructor for AesEncryptionStrategy takes the following parameters: 16 | 17 | - The key size (number of bits; e.g. 128, 192 or 256). 18 | - The iteration count (used when generating keys). 19 | - The passphrase. 20 | 21 | In addition, a random salt and initialization vector are generated automatically for you, using .NET's ```RandomNumberGenerator``` class. 22 | 23 | See [ClientSideEncryption.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/ClientSideEncryption.cs) for a full example, and [https://structurizr.com/share/41](https://structurizr.com/share/41) to access the workspace. -------------------------------------------------------------------------------- /docs/container-diagram.md: -------------------------------------------------------------------------------- 1 | # Container diagram 2 | 3 | Once you understand how your system fits in to the overall IT environment, a really useful next step is to illustrate the high-level technology choices with a Container diagram. A "container" is something like a web application, desktop application, mobile app, database, file system, etc. Essentially, a container is a separately deployable unit that executes code or stores data. 4 | 5 | The Container diagram shows the high-level shape of the software architecture and how responsibilities are distributed across it. It also shows the major technology choices and how the containers communicate with one another. It's a simple, high-level technology focussed diagram that is useful for software developers and support/operations staff alike. 6 | 7 | ## Example 8 | 9 | As an example, a Container diagram for a simplified, fictional Internet Banking System might look something like this. In summary, it shows that the Internet Banking System is made up a Web Application and a Database. It also shows the relationship between the Web Application and the Mainframe Banking System. 10 | 11 | ![An example Container diagram](images/container-diagram-1.png) 12 | 13 | With Structurizr for .NET, you can create this diagram with code like the following: 14 | 15 | ```c# 16 | Container webApplication = internetBankingSystem.AddContainer("Web Application", "Provides all of the Internet banking functionality to customers.", "Java and Spring MVC"); 17 | Container database = internetBankingSystem.AddContainer("Database", "Stores interesting data.", "Relational Database Schema"); 18 | 19 | customer.Uses(webApplication, "HTTPS"); 20 | webApplication.Uses(database, "Reads from and writes to", "JDBC"); 21 | webApplication.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS"); 22 | 23 | ContainerView containerView = views.CreateContainerView(internetBankingSystem, "Containers", "The container diagram for the Internet Banking System."); 24 | containerView.Add(customer); 25 | containerView.AddAllContainers(); 26 | containerView.Add(mainframeBankingSystem); 27 | ``` 28 | 29 | See [BigBankPlc.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/BigBankPlc.cs) for the full code, and [https://structurizr.com/share/36141#Containers](https://structurizr.com/share/36141#Containers) for the diagram. -------------------------------------------------------------------------------- /docs/corporate-branding.md: -------------------------------------------------------------------------------- 1 | # Corporate branding 2 | 3 | > Note: this page describes a feature that is not available to use with Structurizr's Free Plan. 4 | 5 | In addition to [styling diagram elements](styling-elements.md) and [relationships](styling-relationships.md), some corporate branding can be added to diagrams and documentation. This includes: 6 | 7 | - A font (font name and optional web font stylesheet URL). 8 | - A logo (a URL to an image file or a data URI). 9 | 10 | Here's an example diagram that hasn't been styled, aside from setting the shape of the ```Person``` elements. 11 | 12 | ![Unbranded diagram](images/corporate-branding-1.png) 13 | 14 | And here's what the documentation looks like. 15 | 16 | ![Unbranded documentation](images/corporate-branding-2.png) 17 | 18 | You can add branding to an existing workspace, as follows: 19 | 20 | ```c# 21 | Branding branding = views.Configuration.Branding; 22 | branding.Logo = ImageUtils.GetImageAsDataUri(new FileInfo("structurizr-logo.png")); 23 | ``` 24 | 25 | ## Diagrams 26 | 27 | If no colours have been specified via diagram element styles, colour pairs 1-4 will be used when rendering people, software systems, containers and components respectively. Here's the same diagram, now with added branding. Notice that the logo is now also shown in the bottom left corner. 28 | 29 | ![Branded diagram](images/corporate-branding-3.png) 30 | 31 | ## Documentation 32 | 33 | With documentation, the colour pairs are mapped onto the navigation links at the top of the page, while the first colour pair is used when rendering hyperlinks. Again, the logo is shown. 34 | 35 | ![Branded documentation](images/corporate-branding-4.png) 36 | 37 | See [CorporateBranding.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/CorporateBranding.cs) for a full example, and [https://structurizr.com/share/35031](https://structurizr.com/share/35031) to access the workspace. 38 | -------------------------------------------------------------------------------- /docs/dynamic-diagram.md: -------------------------------------------------------------------------------- 1 | # Dynamic diagram 2 | 3 | In addition to the diagrams showing static structure, you can also create a simple Dynamic diagram. This can be useful when you want to show how elements in a static model collaborate at runtime to implement a user story, use case, feature, etc. 4 | 5 | The Dynamic diagram in Structurizr is based upon a [UML communication diagram](https://en.wikipedia.org/wiki/Communication_diagram) (previously known as a "UML collaboration diagram"). This is similar to a [UML sequence diagram](https://en.wikipedia.org/wiki/Sequence_diagram) although it allows a free-form arrangement of diagram elements with numbered interactions to indicate ordering. 6 | 7 | > Note: this page describes a feature that is not available to use with Structurizr's Free Plan. You can, however, render Dynamic diagrams using the [PlantUMLWriter](plantuml.md). 8 | 9 | ## Example 10 | 11 | As an example, a Dynamic diagram describing the customer sign in process for a simplified, fictional Internet Banking System might look something like this. In summary, it shows the components involved in the sign in process, and the interactions between them. 12 | 13 | ![An example Dynamic diagram](images/dynamic-diagram-1.png) 14 | 15 | With Structurizr for .NET, you can create this diagram with code like the following: 16 | 17 | ```c# 18 | DynamicView dynamicView = views.CreateDynamicView(webApplication, "SignIn", "Summarises how the sign in feature works."); 19 | dynamicView.Add(customer, "Requests /signin from", signinController); 20 | dynamicView.Add(customer, "Submits credentials to", signinController); 21 | dynamicView.Add(signinController, "Calls isAuthenticated() on", securityComponent); 22 | dynamicView.Add(securityComponent, "select * from users u where username = ?", database); 23 | ``` 24 | 25 | See [BigBankPlc.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/BigBankPlc.cs) for the full code, and [https://structurizr.com/share/36141#SignIn](https://structurizr.com/share/36141#SignIn) for the diagram. 26 | 27 | ### Adding relationships 28 | 29 | In order to add a relationship between two elements to a dynamic view, that relationship must already exist between the two elements in the static view. 30 | 31 | ### Parallel behaviour 32 | 33 | Showing parallel behaviour is also possible using the ```startParallelSequence()``` and ```endParallelSequence()``` methods on the ```DynamicView``` class. See [MicroservicesExample.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/MicroservicesExample.cs) and [https://structurizr.com/share/4241#CustomerUpdateEvent](https://structurizr.com/share/4241#CustomerUpdateEvent) for an example. -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # Frequently asked questions 2 | 3 | ## Why are many classes sealed with internal members, and not open to extension? 4 | 5 | First and foremost, this repo is a client library for the [Structurizr cloud service and on-premises installation](https://structurizr.com). It allows you to write .NET code to create an in-memory object graph representing a software architecture model and views (a "workspace"), serialize that to JSON, and upload it via a web API. The workspace has an [OpenAPI definition](https://github.com/structurizr/json/blob/master/structurizr.yaml), but this library also implements a number of rules (think of them as the "business logic") to ensure that the workspace is valid. These rules include, for example, ensuring that all containers with a software system have unique names, and that you can't add components to a system context view. 6 | 7 | Unsealing the classes and leaving the them open for extension allows you to bypass/break these rules, which will likely lead to the serialized workspace definitions being incompatible with the Structurizr cloud service and on-premises installation. The output of this library also needs to be compatible with all of the other client libraries. 8 | 9 | You are welcome to fork this library for your own purposes. Alternatively, you can build a thin wrapper around the library, to provide your own custom functionality, or perhaps a more fluent API ... many teams have done this. 10 | 11 | ## Can I submit a pull request? 12 | 13 | It depends on the nature of the change. Please open an issue first to discuss it. 14 | -------------------------------------------------------------------------------- /docs/filtered-views.md: -------------------------------------------------------------------------------- 1 | # Filtered views 2 | 3 | A filtered view represents a view on top of another view, which can be used to include or exclude specific elements and/or relationships, based upon their tag. The benefit of using filtered views is that element and relationship positions are shared between the views. 4 | 5 | Filtered views can be created on top of static views only; i.e. Enterprise Context, System Context, Container and Component views. 6 | 7 | ## Example 8 | 9 | As an example, let's imagine an organisation where a User uses Software System A for tasks 1 and 2. 10 | 11 | ![A diagram showing the current state](images/filtered-views-1.png) 12 | 13 | And, in the future, Software System B will be introduced to fulfil task 2. 14 | 15 | ![A diagram showing the future state](images/filtered-views-2.png) 16 | 17 | With Structurizr for .NET, you can illustrate this by defining a single context diagram with two filtered views on top; one showing the current state and the other showing future state. 18 | 19 | ```c# 20 | Person user = model.AddPerson("User", "A description of the user."); 21 | SoftwareSystem softwareSystemA = model.AddSoftwareSystem("Software System A", "A description of software system A."); 22 | SoftwareSystem softwareSystemB = model.AddSoftwareSystem("Software System B", "A description of software system B."); 23 | softwareSystemB.AddTags(FutureState); 24 | 25 | user.Uses(softwareSystemA, "Uses for tasks 1 and 2").AddTags(CurrentState); 26 | user.Uses(softwareSystemA, "Uses for task 1").AddTags(FutureState); 27 | user.Uses(softwareSystemB, "Uses for task 2").AddTags(FutureState); 28 | 29 | ViewSet views = workspace.Views; 30 | EnterpriseContextView enterpriseContextView = views.CreateEnterpriseContextView("EnterpriseContext", "An example Enterprise Context diagram."); 31 | enterpriseContextView.AddAllElements(); 32 | 33 | views.CreateFilteredView(enterpriseContextView, "CurrentState", "The current context.", FilterMode.Exclude, FutureState); 34 | views.CreateFilteredView(enterpriseContextView, "FutureState", "The future state context after Software System B is live.", FilterMode.Exclude, CurrentState); 35 | ``` 36 | 37 | In summary, you create a view with all of the elements and relationships that you want to show, and then create one or more filtered views on top, specifying the tags that you'd like to include or exclude. 38 | 39 | See [FilteredViews.cs](https://github.com/structurizr/dotnet/tree/master/Structurizr.Examples/FilteredViews.cs) for the full code, and [https://structurizr.com/share/19911](https://structurizr.com/share/19911) for the diagram. -------------------------------------------------------------------------------- /docs/health-checks.md: -------------------------------------------------------------------------------- 1 | # HTTP-based health checks 2 | 3 | Structurizr's health checks feature allows you to supplement your deployment models with HTTP-based health checks to get an "at a glance" view of the health of your software systems. See [Structurizr - Health Checks](https://structurizr.com/help/health-checks) for more details. 4 | 5 | When defining your software architecture model using the client library, HTTP-based health checks can be added to the Container Instances in your deployment model. Each health check is defined by a name, an endpoint URL, a polling interval (e.g. 60 seconds), a timeout (e.g. 1000 milliseconds), and optionally one or more HTTP headers. 6 | 7 | [HttpHealthChecks.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/HttpHealthChecks.cs) shows an example of how to setup the health checks, and the result can be see online at [https://structurizr.com/share/39441/health](https://structurizr.com/share/39441/health). -------------------------------------------------------------------------------- /docs/images/basic-concepts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/basic-concepts.png -------------------------------------------------------------------------------- /docs/images/component-diagram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/component-diagram-1.png -------------------------------------------------------------------------------- /docs/images/container-diagram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/container-diagram-1.png -------------------------------------------------------------------------------- /docs/images/corporate-branding-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/corporate-branding-1.png -------------------------------------------------------------------------------- /docs/images/corporate-branding-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/corporate-branding-2.png -------------------------------------------------------------------------------- /docs/images/corporate-branding-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/corporate-branding-3.png -------------------------------------------------------------------------------- /docs/images/corporate-branding-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/corporate-branding-4.png -------------------------------------------------------------------------------- /docs/images/deployment-diagram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/deployment-diagram-1.png -------------------------------------------------------------------------------- /docs/images/documentation-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/documentation-1.png -------------------------------------------------------------------------------- /docs/images/documentation-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/documentation-2.png -------------------------------------------------------------------------------- /docs/images/documentation-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/documentation-3.png -------------------------------------------------------------------------------- /docs/images/dynamic-diagram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/dynamic-diagram-1.png -------------------------------------------------------------------------------- /docs/images/filtered-views-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/filtered-views-1.png -------------------------------------------------------------------------------- /docs/images/filtered-views-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/filtered-views-2.png -------------------------------------------------------------------------------- /docs/images/getting-started-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/getting-started-1.png -------------------------------------------------------------------------------- /docs/images/getting-started-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/getting-started-2.png -------------------------------------------------------------------------------- /docs/images/getting-started-diagram-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/getting-started-diagram-key.png -------------------------------------------------------------------------------- /docs/images/implied-relationships-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/implied-relationships-1.png -------------------------------------------------------------------------------- /docs/images/readme-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/readme-1.png -------------------------------------------------------------------------------- /docs/images/structurizr-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/structurizr-banner.png -------------------------------------------------------------------------------- /docs/images/structurizr-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/structurizr-overview.png -------------------------------------------------------------------------------- /docs/images/styling-elements-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-elements-1.png -------------------------------------------------------------------------------- /docs/images/styling-elements-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-elements-2.png -------------------------------------------------------------------------------- /docs/images/styling-elements-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-elements-3.png -------------------------------------------------------------------------------- /docs/images/styling-elements-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-elements-4.png -------------------------------------------------------------------------------- /docs/images/styling-elements-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-elements-5.png -------------------------------------------------------------------------------- /docs/images/styling-elements-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-elements-6.png -------------------------------------------------------------------------------- /docs/images/styling-relationships-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-relationships-1.png -------------------------------------------------------------------------------- /docs/images/styling-relationships-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-relationships-2.png -------------------------------------------------------------------------------- /docs/images/styling-relationships-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-relationships-3.png -------------------------------------------------------------------------------- /docs/images/styling-relationships-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/styling-relationships-4.png -------------------------------------------------------------------------------- /docs/images/system-context-diagram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/system-context-diagram-1.png -------------------------------------------------------------------------------- /docs/images/system-landscape-diagram-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structurizr/dotnet/9a7f478792c333507294e3b23863092b3d698273/docs/images/system-landscape-diagram-1.png -------------------------------------------------------------------------------- /docs/model.md: -------------------------------------------------------------------------------- 1 | # Model 2 | 3 | This is the definition of the software architecture model, consisting of people, software systems, containers, components, code elements and deployment nodes, plus the relationships between them. 4 | 5 | All of the .NET classes representing people, software systems, containers, components, etc, and the functionality related to creating a software architecture model can be found in the [Structurizr](https://github.com/structurizr/dotnet/tree/master/Structurizr.Core/Model) namespace. 6 | 7 | An empty model is created for you when you create a workspace. 8 | 9 | ```c# 10 | Workspace workspace = new Workspace("Getting Started", "This is a model of my software system."); 11 | Model model = workspace.Model; 12 | ``` 13 | 14 | Once you have a reference to a ```Model``` instance, you can add elements to it manually or automatically, using static analysis and reflection techniques. 15 | 16 | ## 1. Manual model creation 17 | 18 | Manually adding elements to the model is the simplest way to use the Structurizr for Java client library. This can be done using the various public ```Add*``` methods that you'll find on ```Model```, ```SoftwareSystem```, ```Container```, ```Component```, etc. 19 | 20 | ## 2. Automatic extraction 21 | 22 | You can also extract components (and add them to a ```Container``` instance) automatically from a given codebase, using a number of different component finder strategies. See [Component finder](https://github.com/structurizr/dotnet-extensions/blob/master/Structurizr.Analysis/Analysis/ComponentFinder.cs) for more details. 23 | 24 | Although there is nothing included in the Structurizr for .NET library to support this, you could also choose to parse an external definition of your software architecture (e.g. an AWS infrastructure topology, another Architecture Description Language, etc) and create model elements accordingly. -------------------------------------------------------------------------------- /docs/nuget.md: -------------------------------------------------------------------------------- 1 | # NuGet 2 | 3 | To create NuGet multi-target NuGet packages: 4 | 5 | 1. Open the Visual Studio Command Prompt 6 | 1. Change to the directory containing the .csproj file 7 | 1. Run (e.g.) ```msbuild /t:pack /p:Version=0.8.0 /p:Configuration=Debug``` -------------------------------------------------------------------------------- /docs/styling-relationships.md: -------------------------------------------------------------------------------- 1 | # Styling relationships 2 | 3 | By default, all relationships are rendered as dashed grey lines as shown in the example diagram below. 4 | 5 | ![Default styling](images/styling-relationships-1.png) 6 | 7 | However, the following characteristics of the relationships can be customized: 8 | 9 | - Line thickness (pixels) 10 | - Colour (HTML hex value) 11 | - Dashed (true or false) 12 | - Routing (Direct or Orthogonal; see the [Routing](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/Routing.cs) enum) 13 | - Font size (pixels) 14 | - Width (of the description, in pixels) 15 | - Position (of the description along the line, as a percentage from start to end) 16 | - Opacity (an integer between 0 and 100) 17 | 18 | ## Tagging relationships 19 | 20 | All relationships within a software architecture model can have one or more tags associated with them. A tag is simply a free-format string. By default, the Java client library adds the ```"Relationship"``` tag to relationships. As we'll see shortly, you can add your own custom tags to relationships using the ```AddTags()``` method on the relationship. 21 | 22 | ## Colour 23 | 24 | To style a relationship, simply create a [RelationshipStyle](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/RelationshipStyle.cs) for a particular tag and specify the characteristics that you would like to change. For example, you can change the colour of all relationships as follows. 25 | 26 | ```java 27 | Styles styles = workspace.Views.Configuration.Styles; 28 | styles.Add(new RelationshipStyle(Tags.Relationship) { Color = "#ff0000" }); 29 | ``` 30 | 31 | ![Colouring all relationships](images/styling-relationships-2.png) 32 | 33 | You can also change the colour of specific relationships, based upon their tag, as follows. 34 | 35 | ```java 36 | model.Relationships.Where(r => "HTTPS".Equals(r.Technology)).ToList().ForEach(r => r.AddTags("HTTPS")); 37 | model.Relationships.Where(r => "JDBC".Equals(r.Technology)).ToList().ForEach(r => r.AddTags("JDBC")); 38 | styles.Add(new RelationshipStyle("HTTPS") { Color = "#ff0000" }); 39 | styles.Add(new RelationshipStyle("JDBC") { Color = "#0000ff" }); 40 | ``` 41 | 42 | ![Colouring relationships based upon tag](images/styling-relationships-3.png) 43 | 44 | ## Diagram key 45 | 46 | Structurizr will automatically add all relationship styles to a diagram key. 47 | 48 | ![The diagram key](images/styling-relationships-4.png) 49 | 50 | You can find the code for this example at [StylingRelationships.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/StylingRelationships.cs) and the live example workspace at [https://structurizr.com/share/36131](https://structurizr.com/share/36131). -------------------------------------------------------------------------------- /docs/system-context-diagram.md: -------------------------------------------------------------------------------- 1 | # System Context diagram 2 | 3 | A System Context diagram is a good starting point for diagramming and documenting a software system, allowing you to step back and see the big picture. Draw a diagram showing your system as a box in the centre, surrounded by its users and the other systems that it interacts with. 4 | 5 | Detail isn't important here as this is your zoomed out view showing a big picture of the system landscape. The focus should be on people (actors, roles, personas, etc) and software systems rather than technologies, protocols and other low-level details. It's the sort of diagram that you could show to non-technical people. 6 | 7 | ## Example 8 | 9 | As an example, a System Context diagram for a simplified, fictional Internet Banking System might look something like this. In summary, it shows that customers of the bank use the Internet Banking System, which itself uses the internal Mainframe Banking System. 10 | 11 | ![An example System Context diagram](images/system-context-diagram-1.png) 12 | 13 | With Structurizr for .NET, you can create this diagram with code like the following: 14 | 15 | ```c# 16 | Person customer = model.AddPerson(Location.External, "Customer", "A customer of the bank."); 17 | 18 | SoftwareSystem internetBankingSystem = model.AddSoftwareSystem(Location.Internal, "Internet Banking System", "Allows customers to view information about their bank accounts and make payments."); 19 | customer.Uses(internetBankingSystem, "Uses"); 20 | 21 | SoftwareSystem mainframeBankingSystem = model.AddSoftwareSystem(Location.Internal, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc."); 22 | internetBankingSystem.Uses(mainframeBankingSystem, "Uses"); 23 | 24 | SystemContextView systemContextView = views.CreateSystemContextView(internetBankingSystem, "SystemContext", "The system context diagram for the Internet Banking System."); 25 | systemContextView.AddNearestNeighbours(internetBankingSystem); 26 | ``` 27 | 28 | See [BigBankPlc.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/BigBankPlc.cs) for the full code, and [https://structurizr.com/share/36141#SystemContext](https://structurizr.com/share/36141#SystemContext) for the diagram. -------------------------------------------------------------------------------- /docs/system-landscape-diagram.md: -------------------------------------------------------------------------------- 1 | # System Landscape diagram 2 | 3 | A System Landscape diagram is really the same as the [System Context diagram](system-context-diagram.md), without a focus on a specific software system. It can help to provide a broader view of the people and software systems that are related to and reside within a given enterprise (e.g. a business or organisation). 4 | 5 | ## Example 6 | 7 | As an example, a System Landscape diagram for a simplified, fictional Internet Banking System might look something like this. In summary, it shows more than just the immediate relationships of the Internet Banking System. 8 | 9 | ![An example System Landscape diagram](images/system-landscape-diagram-1.png) 10 | 11 | With Structurizr for .NET, you can create this diagram with code like the following: 12 | 13 | ```c# 14 | Person customer = model.AddPerson(Location.External, "Customer", "A customer of the bank."); 15 | 16 | SoftwareSystem internetBankingSystem = model.AddSoftwareSystem(Location.Internal, "Internet Banking System", "Allows customers to view information about their bank accounts and make payments."); 17 | customer.Uses(internetBankingSystem, "Uses"); 18 | 19 | SoftwareSystem mainframeBankingSystem = model.AddSoftwareSystem(Location.Internal, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc."); 20 | internetBankingSystem.Uses(mainframeBankingSystem, "Uses"); 21 | 22 | SoftwareSystem atm = model.AddSoftwareSystem(Location.Internal, "ATM", "Allows customers to withdraw cash."); 23 | atm.Uses(mainframeBankingSystem, "Uses"); 24 | customer.Uses(atm, "Withdraws cash using"); 25 | 26 | Person bankStaff = model.AddPerson(Location.Internal, "Bank Staff", "Staff within the bank."); 27 | bankStaff.Uses(mainframeBankingSystem, "Uses"); 28 | 29 | EnterpriseContextView enterpriseContextView = views.CreateSystemLandscapeView("EnterpriseContext", "The system landscape diagram for the Internet Banking System."); 30 | enterpriseContextView.AddAllElements(); 31 | ``` 32 | 33 | See [BigBankPlc.cs](https://github.com/structurizr/dotnet/blob/master/Structurizr.Examples/BigBankPlc.cs) for the full code, and [https://structurizr.com/share/36141#EnterpriseContext](https://structurizr.com/share/36141#EnterpriseContext) for the diagram. -------------------------------------------------------------------------------- /docs/usage-patterns.md: -------------------------------------------------------------------------------- 1 | # Usage patterns 2 | 3 | ## Single program 4 | 5 | The simplest way to create a software architecture model is to write a single C# program that first creates the model elements (people, software systems, containers and components) before subsequently creating the required views and uploading the workspace to Structurizr. If you have a particularly large model, or you'd like to share common elements between models, then one approach is to modularise your program appropriately. 6 | 7 | ## Multiple programs 8 | 9 | Another approach is to write a collection of C# programs, that are each responsible for creating a different part of the software architecture model. This is especially useful if you need to use the component finder with different assemblies. You can then write a script, or use your build script, to run these C# programs in sequence. Intermediate versions of the workspace can be saved to and loaded from disk using the [WorkspaceUtils](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/Util/WorkspaceUtils.cs) class. For example: 10 | 11 | 1. Program 1: Create the basic model elements (people, software systems and containers) and the relationships between them. 12 | 2. Program 2: Add components for container 1 (e.g. run the component finder). 13 | 3. Program 3: Add components for container 2 (e.g. run the component finder with a different assembly path). 14 | 4. Program 4: Create views. 15 | 5. Program 5: Add styling. 16 | 6. Program 6: Upload to Structurizr. 17 | 18 | In this example, the first program would write the initial version of the workspace to a local file on disk, which subsequent programs then load and add to, before writing the workspace back to disk. -------------------------------------------------------------------------------- /docs/views.md: -------------------------------------------------------------------------------- 1 | # Views 2 | 3 | Once you've [added elements to a model](model.md), you can create one or more views to visualise parts of the model, which can subsequently be rendered as diagrams by a number of different tools. 4 | 5 | Structurizr for .NET supports all of the view types described in the [C4 model](https://c4model.com), and the .NET classes implementing these views can be found in the [Structurizr](https://github.com/structurizr/dotnet/tree/master/Structurizr.Core/View) namespace as follows: 6 | 7 | * [SystemContextView](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/SystemContextView.cs) 8 | * [ContainerView](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/ContainerView.cs) 9 | * [ComponentView](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/ComponentView.cs) 10 | * [SystemLandscapeView](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/SystemLandscapeView.cs) 11 | * [DynamicView](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/DynamicView.cs) 12 | * [DeploymentView](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/DeploymentView.cs) 13 | 14 | ## Creating views 15 | 16 | All views are associated with a [ViewSet](https://github.com/structurizr/dotnet/blob/master/Structurizr.Core/View/ViewSet.cs), which is created for you when you create a workspace. 17 | 18 | ```java 19 | Workspace workspace = new Workspace("Getting Started", "This is a model of my software system."); 20 | ViewSet views = workspace.Views; 21 | ``` 22 | 23 | Use the various ```Create*View``` methods on the ```ViewSet``` class to create views. 24 | 25 | -------------------------------------------------------------------------------- /nuget.bat: -------------------------------------------------------------------------------- 1 | dotnet test .\Structurizr.Core.Tests\Structurizr.Core.Tests.csproj 2 | dotnet test .\Structurizr.Client.Tests\Structurizr.Client.Tests.csproj 3 | 4 | dotnet msbuild "/t:rebuild;pack" /p:Version=0.9.7 /p:Configuration=Debug .\Structurizr.Core\Structurizr.Core.csproj 5 | dotnet msbuild "/t:rebuild;pack" /p:Version=0.9.7 /p:Configuration=Debug .\Structurizr.Client\Structurizr.Client.csproj --------------------------------------------------------------------------------