diff --git a/.config/npm-packages.json b/.config/npm-packages.json
new file mode 100644
index 0000000..6a030e9
--- /dev/null
+++ b/.config/npm-packages.json
@@ -0,0 +1,6 @@
+{
+ "chart.js": "4.5.1",
+ "chartjs-chart-geo": "4.3.6",
+ "luxon": "3.7.2",
+ "world-atlas": "2.0.2"
+}
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 15e41ef..ba59dae 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,9 +1,10 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MissingMethodException.slnx b/MissingMethodException.slnx
index 3fb3aa6..6f71738 100644
--- a/MissingMethodException.slnx
+++ b/MissingMethodException.slnx
@@ -33,4 +33,10 @@
+
+
+
+
+
+
diff --git a/NpmRegistry.Wrapper/Models/Attestations.cs b/NpmRegistry.Wrapper/Models/Attestations.cs
new file mode 100644
index 0000000..d2e163b
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/Attestations.cs
@@ -0,0 +1,13 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+public class Attestations
+{
+ [JsonPropertyName("url")]
+#pragma warning disable CA1056 // URI-like properties should not be strings
+ public string Url { get; set; } = string.Empty;
+#pragma warning restore CA1056 // URI-like properties should not be strings
+
+ [JsonPropertyName("provenance")]
+ public Provenance Provenance { get; set; } = new Provenance();
+}
diff --git a/NpmRegistry.Wrapper/Models/BinScript.cs b/NpmRegistry.Wrapper/Models/BinScript.cs
new file mode 100644
index 0000000..5aff3df
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/BinScript.cs
@@ -0,0 +1,6 @@
+namespace NpmRegistry.Wrapper.Models;
+public class BinScript
+{
+ public string Name { get; set; } = string.Empty;
+ public string Path { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/BinScriptCollection.cs b/NpmRegistry.Wrapper/Models/BinScriptCollection.cs
new file mode 100644
index 0000000..0cf8b6e
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/BinScriptCollection.cs
@@ -0,0 +1,11 @@
+namespace NpmRegistry.Wrapper.Models;
+#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
+public class BinScriptCollection
+#pragma warning restore CA1711 // Identifiers should not have incorrect suffix
+{
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List BinScripts { get; set; } = [];
+#pragma warning restore CA2227 // Collection properties should be read only
+#pragma warning restore CA1002 // Do not expose generic lists
+}
diff --git a/NpmRegistry.Wrapper/Models/Dependency.cs b/NpmRegistry.Wrapper/Models/Dependency.cs
new file mode 100644
index 0000000..6730ad5
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/Dependency.cs
@@ -0,0 +1,6 @@
+namespace NpmRegistry.Wrapper.Models;
+public class Dependency
+{
+ public string Name { get; set; } = string.Empty;
+ public string Version { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/DependencyList.cs b/NpmRegistry.Wrapper/Models/DependencyList.cs
new file mode 100644
index 0000000..8e66feb
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/DependencyList.cs
@@ -0,0 +1,9 @@
+namespace NpmRegistry.Wrapper.Models;
+public class DependencyList
+{
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List Dependencies { get; set; } = [];
+#pragma warning restore CA2227 // Collection properties should be read only
+#pragma warning restore CA1002 // Do not expose generic lists
+}
diff --git a/NpmRegistry.Wrapper/Models/Dist.cs b/NpmRegistry.Wrapper/Models/Dist.cs
new file mode 100644
index 0000000..bd347e0
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/Dist.cs
@@ -0,0 +1,34 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+public class Dist
+{
+ [JsonPropertyName("integrity")]
+ public string Integrity { get; set; } = string.Empty;
+
+ [JsonPropertyName("shasum")]
+ public string Shasum { get; set; } = string.Empty;
+
+ [JsonPropertyName("tarball")]
+ public string Tarball { get; set; } = string.Empty;
+
+ [JsonPropertyName("fileCount")]
+ public int FileCount { get; set; }
+
+ [JsonPropertyName("unpackedSize")]
+ public int UnpackedSize { get; set; }
+
+ [JsonPropertyName("signatures")]
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List Signatures { get; set; } = [];
+#pragma warning restore CA2227 // Collection properties should be read only
+#pragma warning restore CA1002 // Do not expose generic lists
+
+ [JsonPropertyName("npm-signature")]
+ public string NpmSignature { get; set; } = string.Empty;
+
+ [JsonPropertyName("attestations")]
+ public Attestations? Attestations { get; set; }
+}
diff --git a/NpmRegistry.Wrapper/Models/DistTags.cs b/NpmRegistry.Wrapper/Models/DistTags.cs
new file mode 100644
index 0000000..48dce50
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/DistTags.cs
@@ -0,0 +1,11 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+public class DistTags
+{
+ [JsonPropertyName("next")]
+ public string Next { get; set; } = string.Empty;
+ [JsonPropertyName("latest")]
+ public string Latest { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/ModelsSerializerContext.cs b/NpmRegistry.Wrapper/Models/ModelsSerializerContext.cs
new file mode 100644
index 0000000..a276877
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/ModelsSerializerContext.cs
@@ -0,0 +1,28 @@
+using NpmRegistry.Wrapper.Serialization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+//[JsonSerializable(typeof(VersionList))]
+//[JsonSerializable(typeof(Person))]
+//[JsonSerializable(typeof(DistTags))]
+//[JsonSerializable(typeof(NpmPackage))]
+//[JsonSourceGenerationOptions(AllowTrailingCommas = true,
+// Converters = [typeof(VersionListJsonConverter), typeof(PersonJsonConverter)],
+// GenerationMode = JsonSourceGenerationMode.Default,
+// IgnoreReadOnlyFields = false,
+// IgnoreReadOnlyProperties = false,
+// IncludeFields = false,
+// MaxDepth = 15,
+// NumberHandling = JsonNumberHandling.Strict,
+// PreferredObjectCreationHandling = JsonObjectCreationHandling.Replace,
+// ReadCommentHandling = JsonCommentHandling.Skip,
+// RespectNullableAnnotations = true,
+// UnknownTypeHandling = JsonUnknownTypeHandling.JsonElement,
+// UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
+// UseStringEnumConverter = true,
+// WriteIndented = false)]
+//internal sealed partial class ModelsSerializerContext : JsonSerializerContext
+//{
+//}
diff --git a/NpmRegistry.Wrapper/Models/NpmOperationalInternal.cs b/NpmRegistry.Wrapper/Models/NpmOperationalInternal.cs
new file mode 100644
index 0000000..b18b72c
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/NpmOperationalInternal.cs
@@ -0,0 +1,12 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+public class NpmOperationalInternal
+{
+ [JsonPropertyName("host")]
+ public string Host { get; set; } = string.Empty;
+
+ [JsonPropertyName("tmp")]
+ public string Tmp { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/NpmPackage.cs b/NpmRegistry.Wrapper/Models/NpmPackage.cs
new file mode 100644
index 0000000..febd489
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/NpmPackage.cs
@@ -0,0 +1,47 @@
+using NpmRegistry.Wrapper.Serialization;
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+
+public class NpmPackage
+{
+ [JsonPropertyName("_id")]
+ public string Id { get; set; } = string.Empty;
+
+ [JsonPropertyName("name")]
+ public string Name { get; set; } = string.Empty;
+
+ [JsonPropertyName("dist-tags")]
+ public DistTags? DistTags { get; set; }
+
+ [JsonPropertyName("versions")]
+ [JsonConverter(typeof(VersionListJsonConverter))]
+ public VersionList? Versions { get; set; }
+
+ [JsonPropertyName("time")]
+ public NpmTime? Time { get; set; }
+
+ [JsonPropertyName("maintainers")]
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List Maintainers { get; set; } = [];
+#pragma warning restore CA2227 // Collection properties should be read only
+#pragma warning restore CA1002 // Do not expose generic lists
+
+ [JsonPropertyName("description")]
+ public string Description { get; set; } = string.Empty;
+
+ [JsonPropertyName("author")]
+ [JsonConverter(typeof(PersonJsonConverter))]
+ public Person? Author { get; set; }
+
+ [JsonPropertyName("license")]
+ public string License { get; set; } = string.Empty;
+
+ [JsonPropertyName("readme")]
+ public string Readme { get; set; } = string.Empty;
+
+ [JsonPropertyName("readmeFilename")]
+ public string ReadmeFilename { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/NpmTime.cs b/NpmRegistry.Wrapper/Models/NpmTime.cs
new file mode 100644
index 0000000..0ee8ba9
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/NpmTime.cs
@@ -0,0 +1,28 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+public class NpmTime
+{
+ [JsonPropertyName("created")]
+ public string Created { get; set; } = string.Empty;
+
+ [JsonPropertyName("modified")]
+ public string Modified { get; set; } = string.Empty;
+
+ [JsonPropertyName("unpublished")]
+ public UnpublishedTime? Unpublished { get; set; }
+}
+
+public class UnpublishedTime
+{
+ [JsonPropertyName("time")]
+ public string Time { get; set; } = string.Empty;
+
+ [JsonPropertyName("versions")]
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List Versions { get; set; } = [];
+#pragma warning restore CA1002 // Do not expose generic lists
+#pragma warning restore CA2227 // Collection properties should be read only
+}
diff --git a/NpmRegistry.Wrapper/Models/PackageVersion.cs b/NpmRegistry.Wrapper/Models/PackageVersion.cs
new file mode 100644
index 0000000..02ee6ca
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/PackageVersion.cs
@@ -0,0 +1,66 @@
+using NpmRegistry.Wrapper.Serialization;
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+public class PackageVersion
+{
+ [JsonPropertyName("name")]
+ public string Name { get; set; } = string.Empty;
+
+ [JsonPropertyName("version")]
+ public string Version { get; set; } = string.Empty;
+
+ [JsonPropertyName("description")]
+ public string Description { get; set; } = string.Empty;
+
+ [JsonPropertyName("main")]
+ public string Main { get; set; } = string.Empty;
+
+ [JsonPropertyName("bin")]
+ [JsonConverter(typeof(BinScriptConverter))]
+ public BinScriptCollection? BinScripts { get; set; }
+
+ [JsonPropertyName("scripts")]
+ [JsonConverter(typeof(ScriptListJsonConverter))]
+ public ScriptList? Scripts { get; set; }
+
+ [JsonPropertyName("author")]
+ [JsonConverter(typeof(PersonJsonConverter))]
+ public Person? Author { get; set; }
+
+ [JsonPropertyName("license")]
+ public string License { get; set; } = string.Empty;
+
+ [JsonPropertyName("_id")]
+ public string Id { get; set; } = string.Empty;
+
+ [JsonPropertyName("_nodeVersion")]
+ public string NodeVersion { get; set; } = string.Empty;
+
+ [JsonPropertyName("_npmVersion")]
+ public string NpmVersion { get; set; } = string.Empty;
+
+ [JsonPropertyName("dist")]
+ public Dist? Dist { get; set; }
+
+ [JsonPropertyName("_npmUser")]
+ public Person? NpmUser { get; set; }
+
+ [JsonPropertyName("maintainers")]
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List Maintainers { get; set; } = [];
+#pragma warning restore CA1002 // Do not expose generic lists
+#pragma warning restore CA2227 // Collection properties should be read only
+
+ [JsonPropertyName("_npmOperationalInternal")]
+ public NpmOperationalInternal? NpmOperationalInternal { get; set; }
+
+ [JsonPropertyName("_hasShrinkwrap")]
+ public bool HasShrinkwrap { get; set; }
+
+ [JsonPropertyName("dependencies")]
+ [JsonConverter(typeof(DependencyListJsonConverter))]
+ public DependencyList Dependencies { get; set; } = new();
+}
diff --git a/NpmRegistry.Wrapper/Models/Person.cs b/NpmRegistry.Wrapper/Models/Person.cs
new file mode 100644
index 0000000..e1f2009
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/Person.cs
@@ -0,0 +1,12 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+
+public class Person
+{
+ [JsonPropertyName("name")]
+ public string Name { get; set; } = string.Empty;
+
+ [JsonPropertyName("email")]
+ public string Email { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/Provenance.cs b/NpmRegistry.Wrapper/Models/Provenance.cs
new file mode 100644
index 0000000..1b5e6c3
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/Provenance.cs
@@ -0,0 +1,8 @@
+using System.Text.Json.Serialization;
+
+namespace NpmRegistry.Wrapper.Models;
+public class Provenance
+{
+ [JsonPropertyName("predicateType")]
+ public string PredicateType { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/Script.cs b/NpmRegistry.Wrapper/Models/Script.cs
new file mode 100644
index 0000000..fcd77df
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/Script.cs
@@ -0,0 +1,7 @@
+namespace NpmRegistry.Wrapper.Models;
+
+public class Script
+{
+ public string Operation { get; set; } = string.Empty;
+ public string Content { get; set; } = string.Empty;
+}
diff --git a/NpmRegistry.Wrapper/Models/ScriptList.cs b/NpmRegistry.Wrapper/Models/ScriptList.cs
new file mode 100644
index 0000000..f564180
--- /dev/null
+++ b/NpmRegistry.Wrapper/Models/ScriptList.cs
@@ -0,0 +1,10 @@
+namespace NpmRegistry.Wrapper.Models;
+
+public class ScriptList
+{
+#pragma warning disable CA1002 // Do not expose generic lists
+#pragma warning disable CA2227 // Collection properties should be read only
+ public List