1- namespace FlowSynx . PluginCore ;
1+ using System . Text . RegularExpressions ;
22
3+ namespace FlowSynx . PluginCore ;
4+
5+ /// <summary>
6+ /// Represents metadata information about a plugin including its identity, version,
7+ /// company, descriptive details, and repository information.
8+ /// Constructs a fully-qualified plugin type identifier based on the company name, namespace, and plugin name.
9+ /// </summary>
310public class PluginMetadata
411{
5- private const string PrefixTypeName = "FlowSynx" ;
12+ private string _companyName = default ! ;
13+ private string _name = default ! ;
14+
15+ /// <summary>
16+ /// A regular expression to validate identifiers.
17+ /// Identifiers must start with a letter and contain only letters and digits.
18+ /// </summary>
19+ private static readonly Regex ValidIdentifierRegex = new ( @"^[A-Za-z][A-Za-z0-9]*$" , RegexOptions . Compiled ) ;
620
21+ /// <summary>
22+ /// Gets or sets the unique identifier of the plugin.
23+ /// </summary>
724 public required Guid Id { get ; set ; }
8- public required string Name { get ; set ; }
25+
26+ /// <summary>
27+ /// Gets or sets the name of the plugin.
28+ /// The name must start with a letter and contain only letters and digits.
29+ /// </summary>
30+ public required string Name
31+ {
32+ get => _name ;
33+ set => _name = ValidateIdentifier ( value , nameof ( Name ) ) ;
34+ }
35+
36+ /// <summary>
37+ /// Gets or sets the version of the plugin.
38+ /// </summary>
939 public required PluginVersion Version { get ; set ; }
40+
41+ /// <summary>
42+ /// Gets or sets the name of the company that created the plugin.
43+ /// The name must start with a letter and contain only letters and digits.
44+ /// </summary>
45+ public required string CompanyName
46+ {
47+ get => _companyName ;
48+ set => _companyName = ValidateIdentifier ( value , nameof ( CompanyName ) ) ;
49+ }
50+
51+ /// <summary>
52+ /// Gets or sets an optional description of the plugin.
53+ /// </summary>
1054 public string ? Description { get ; set ; }
11- public string ? Author { get ; set ; }
12- public string ? Url { get ; set ; }
55+
56+ /// <summary>
57+ /// Gets or sets the list of authors or maintainers of the plugin.
58+ /// </summary>
59+ public List < string > Authors { get ; set ; } = new List < string > ( ) ;
60+
61+ /// <summary>
62+ /// Gets or sets the license name under which the plugin is distributed.
63+ /// </summary>
64+ public string ? License { get ; set ; }
65+
66+ /// <summary>
67+ /// Gets or sets the URL to the license text or license information.
68+ /// </summary>
69+ public string ? LicenseUrl { get ; set ; }
70+
71+ /// <summary>
72+ /// Gets or sets the relative or absolute path/URL to the plugin icon.
73+ /// </summary>
74+ public string ? Icon { get ; set ; }
75+
76+ /// <summary>
77+ /// Gets or sets the URL to the project or documentation related to the plugin.
78+ /// </summary>
79+ public string ? ProjectUrl { get ; set ; }
80+
81+ /// <summary>
82+ /// Gets or sets the copyright notice for the plugin.
83+ /// </summary>
84+ public string ? Copyright { get ; set ; }
85+
86+ /// <summary>
87+ /// Gets or sets a simicolon-delimited list of tags used to categorize or describe the plugin.
88+ /// Useful for search and filtering.
89+ /// </summary>
90+ public List < string > Tags { get ; set ; } = new List < string > ( ) ;
91+
92+ /// <summary>
93+ /// Gets or sets the URL to the source code repository of the plugin.
94+ /// </summary>
95+ public string ? RepositoryUrl { get ; set ; }
96+
97+ /// <summary>
98+ /// Gets or sets the namespace the plugin belongs to.
99+ /// Used as the middle component in the plugin's type identifier.
100+ /// </summary>
13101 public required PluginNamespace Namespace { get ; set ; }
14- public string Type => $ "{ PrefixTypeName } .{ Namespace } .{ Name } ";
102+
103+ /// <summary>
104+ /// Gets the full plugin type name in the format: CompanyName.Namespace.PluginName.
105+ /// This is used for plugin resolution, identification, or registration.
106+ /// </summary>
107+ public string Type => $ "{ CompanyName } .{ Namespace } .{ Name } ";
108+
109+ /// <summary>
110+ /// Validates that an identifier is non-empty, starts with a letter,
111+ /// and contains only letters and digits.
112+ /// </summary>
113+ /// <param name="input">The string to validate.</param>
114+ /// <param name="fieldName">The name of the field being validated, used in the error message.</param>
115+ /// <returns>The validated input string.</returns>
116+ /// <exception cref="ArgumentException">
117+ /// Thrown if the input is null, whitespace, or contains invalid characters.
118+ /// </exception>
119+ private static string ValidateIdentifier ( string input , string fieldName )
120+ {
121+ if ( string . IsNullOrWhiteSpace ( input ) )
122+ throw new ArgumentException ( $ "{ fieldName } cannot be null or whitespace.") ;
123+
124+ if ( ! ValidIdentifierRegex . IsMatch ( input ) )
125+ throw new ArgumentException ( $ "{ fieldName } must start with a letter and contain only letters and " +
126+ $ "digits (no underscores, spaces, or symbols).") ;
127+
128+ return input ;
129+ }
15130}
0 commit comments