Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
### Version: 2.0.0
#### Date: June-15-2026
- **Breaking:** Replaced **Newtonsoft.Json** with **System.Text.Json** across the package. The `Newtonsoft.Json` package reference is removed; add `System.Text.Json` (or rely on the BCL on supported runtimes) as needed in consuming projects.
- **Breaking:** Variant metadata APIs that previously took `JObject` / `JArray` now use `System.Text.Json.Nodes.JsonObject` and `JsonArray` (`GetVariantAliases`, `GetVariantMetadataTags`, and obsolete `GetDataCsvariantsAttribute` overloads).
- JSON serialization uses the same model attributes with `System.Text.Json.Serialization` (`JsonPropertyName`, `JsonConverter`), including custom converters for RTE/GQL-shaped JSON and **path-mapped** embedded models (`PathMappedJsonConverter<T>`).
- RTE JSON deserialization tolerates **trailing commas** when using the documented test/helper patterns (`AllowTrailingCommas`); attribute dictionaries may surface **`JsonElement`** values instead of boxed strings—use helpers or unwrap explicitly if you access `Node.attrs` directly.
- Internal: `LangVersion` set to **latest** for multi-target builds; utilities normalize attribute values where the HTML pipeline expects strings.
### Version: 2.0.0-beta.2
#### Date: June-22-2026
- **New:** Multi-region endpoint resolution via `Endpoint.GetContentstackEndpoint(region, service)` — resolves Contentstack service URLs for all 7 supported regions (NA, EU, AU, Azure-NA, Azure-EU, GCP-NA, GCP-EU) and 18 service keys (contentDelivery, contentManagement, auth, graphqlDelivery, preview, images, assets, automate, launch, developerHub, brandKit, genAI, personalizeManagement, personalizeEdge, composableStudio, assetManagement, and more).
- **New:** `Utils.GetContentstackEndpoint(region, service)` proxy — access endpoint resolution directly from the `Utils` class without importing `Contentstack.Utils.Endpoints`.
- **New:** `omitHttps` flag strips the `https://` scheme from returned URLs — pass directly to SDK host configuration (e.g. `new ContentstackOptions { Host = Endpoint.GetContentstackEndpoint("eu", "contentDelivery", omitHttps: true) }`).
- **New:** Case-insensitive region alias support — `"us"`, `"NA"`, `"AWS-NA"`, `"azure_na"` all resolve correctly to the same region.
- **New:** `regions.json` registry auto-downloaded from `artifacts.contentstack.com` on first use and cached on disk — no setup required. The SDK self-heals if the file is missing.
- **New:** `Scripts/refresh-region.cs` bundled inside the NuGet package — automatically placed in your project's `Scripts/` folder on first `dotnet build`. Run `dotnet run Scripts/refresh-region.cs` anytime to pull the latest regions from CDN.
- **New:** `Scripts/refresh-region.py` bundled inside the NuGet package — automatically placed in your project's `Scripts/` folder on first `dotnet build`. Run `python3 Scripts/refresh-region.py` (Mac/Linux) or `python Scripts/refresh-region.py` (Windows) anytime to pull the latest regions from CDN.

### Version: 2.0.0-beta.1
#### Date: April-27-2026
Expand Down
7 changes: 2 additions & 5 deletions Contentstack.Utils/Contentstack.Utils.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,10 @@
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>

<!-- Ship refresh-region.cs inside the NuGet package.
The .targets file copies it into the consumer's Scripts/ folder on first build.
Customer runs: dotnet run Scripts/refresh-region.cs -->
<ItemGroup>
<Content Include="..\Scripts\refresh-region.cs">
<Content Include="..\Scripts\refresh-region.py">
<Pack>true</Pack>
<PackagePath>contentFiles/cs/any/Scripts/refresh-region.cs</PackagePath>
<PackagePath>contentFiles/cs/any/Scripts/refresh-region.py</PackagePath>
<BuildAction>Content</BuildAction>
<CopyToOutput>false</CopyToOutput>
</Content>
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<Version>2.0.0</Version>
<Version>2.0.0-beta.2</Version>
</PropertyGroup>
</Project>
77 changes: 0 additions & 77 deletions Scripts/refresh-region.cs

This file was deleted.

73 changes: 73 additions & 0 deletions Scripts/refresh-region.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env python3
# Refresh regions.json from the Contentstack CDN.
# Usage (run from your project root):
# python3 Scripts/refresh-region.py
# python Scripts/refresh-region.py

import glob
import json
import os
import ssl
import sys
import urllib.request

REGIONS_URL = "https://artifacts.contentstack.com/regions.json"

print(f"Fetching {REGIONS_URL} ...")


def _fetch(url):
# First attempt: normal SSL verification
try:
with urllib.request.urlopen(url, timeout=30) as r:
return r.read().decode("utf-8")
except urllib.error.URLError as e:
if "CERTIFICATE_VERIFY_FAILED" not in str(e):
raise
# macOS python.org builds often lack system certs — retry without verification
print("WARNING: SSL certificate verification failed. Retrying without verification.", file=sys.stderr)
print(" To fix permanently, run: /Applications/Python*/Install\\ Certificates.command", file=sys.stderr)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
with urllib.request.urlopen(url, timeout=30, context=ctx) as r:
return r.read().decode("utf-8")


try:
raw = _fetch(REGIONS_URL)
except Exception as e:
print(f"ERROR: Could not download regions.json: {e}", file=sys.stderr)
sys.exit(1)

try:
data = json.loads(raw)
except json.JSONDecodeError as e:
print(f"ERROR: Downloaded content is not valid JSON: {e}", file=sys.stderr)
sys.exit(1)

if "regions" not in data:
print("ERROR: Downloaded JSON does not contain a 'regions' key.", file=sys.stderr)
sys.exit(1)

region_count = len(data["regions"])

# Scan bin/ for every copy of the DLL (covers Debug/Release, any TFM, any nesting).
dll_pattern = os.path.join(os.getcwd(), "**", "Contentstack.Utils.dll")
found = [
os.path.dirname(dll)
for dll in glob.glob(dll_pattern, recursive=True)
if os.sep + "bin" + os.sep in dll
]

if not found:
print("[bin] No build output found — run 'dotnet build' first, then re-run this script.")
sys.exit(1)

for bin_dir in found:
assets_dir = os.path.join(bin_dir, "Assets")
os.makedirs(assets_dir, exist_ok=True)
dest = os.path.join(assets_dir, "regions.json")
with open(dest, "w", encoding="utf-8") as f:
f.write(raw)
print(f"[bin] Wrote {region_count} regions → {dest}")
11 changes: 3 additions & 8 deletions build/contentstack.utils.targets
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
<Project>
<!--
Copies refresh-region.cs into the consuming project's Scripts/ folder
on first build. Customer then runs:
dotnet run Scripts/refresh-region.cs
-->
<PropertyGroup>
<_RefreshScriptDest>$(MSBuildProjectDirectory)/Scripts/refresh-region.cs</_RefreshScriptDest>
<_RefreshScriptSrc>$(MSBuildThisFileDirectory)../contentFiles/cs/any/Scripts/refresh-region.cs</_RefreshScriptSrc>
<_RefreshScriptDest>$(MSBuildProjectDirectory)/Scripts/refresh-region.py</_RefreshScriptDest>
<_RefreshScriptSrc>$(MSBuildThisFileDirectory)../contentFiles/cs/any/Scripts/refresh-region.py</_RefreshScriptSrc>
</PropertyGroup>

<Target Name="ContentstackUtils_PlaceRefreshScript"
AfterTargets="ResolvePackageDependenciesForBuild"
Condition="!Exists('$(_RefreshScriptDest)')">
<MakeDir Directories="$(MSBuildProjectDirectory)/Scripts" />
<Copy SourceFiles="$(_RefreshScriptSrc)" DestinationFiles="$(_RefreshScriptDest)" />
<Message Text="contentstack.utils: Scripts/refresh-region.cs added to your project. Run 'dotnet run Scripts/refresh-region.cs' to refresh regions." Importance="High" />
<Message Text="contentstack.utils: Scripts/refresh-region.py added to your project. Run 'python3 Scripts/refresh-region.py' to refresh regions." Importance="High" />
</Target>
</Project>
Loading