Skip to content
Draft
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
10 changes: 10 additions & 0 deletions ContentstackSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@
672F769A2E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672F76982E55ADBE00C248D6 /* AsyncAwaitAPITest.swift */; };
672F769B2E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672F76982E55ADBE00C248D6 /* AsyncAwaitAPITest.swift */; };
6750778E2D3E256A0076A066 /* DVR in Frameworks */ = {isa = PBXBuildFile; productRef = 6750778D2D3E256A0076A066 /* DVR */; };
678CBD072EF10CBA00B72390 /* ContentstackMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678CBD062EF10CBA00B72390 /* ContentstackMessages.swift */; };
678CBD082EF10CBA00B72390 /* ContentstackMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678CBD062EF10CBA00B72390 /* ContentstackMessages.swift */; };
678CBD092EF10CBA00B72390 /* ContentstackMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678CBD062EF10CBA00B72390 /* ContentstackMessages.swift */; };
678CBD0A2EF10CBA00B72390 /* ContentstackMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678CBD062EF10CBA00B72390 /* ContentstackMessages.swift */; };
67AA38EA2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */; };
67AA38EB2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */; };
67AA38EC2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */; };
Expand Down Expand Up @@ -456,6 +460,7 @@
47B4DC612C232A8200370CFC /* TaxonomyTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxonomyTest.swift; sourceTree = "<group>"; };
47C6EFC12C0B5B9400F0D5CF /* Taxonomy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Taxonomy.swift; sourceTree = "<group>"; };
672F76982E55ADBE00C248D6 /* AsyncAwaitAPITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncAwaitAPITest.swift; sourceTree = "<group>"; };
678CBD062EF10CBA00B72390 /* ContentstackMessages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentstackMessages.swift; sourceTree = "<group>"; };
67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSDefinitionsTest.swift; sourceTree = "<group>"; };
67AA38ED2EB9D46200C0E2C0 /* QueryParameterTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryParameterTest.swift; sourceTree = "<group>"; };
67AA38F12EB9D46800C0E2C0 /* QueryOperationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryOperationTest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -807,6 +812,7 @@
0F4FBCB12420D2CA007B8CAE /* Query */,
0FFA5D60241F5561003B3AF5 /* Utilities */,
0FFA5D5B241F5134003B3AF5 /* Stack.swift */,
678CBD062EF10CBA00B72390 /* ContentstackMessages.swift */,
67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */,
0FFA5D83241F808F003B3AF5 /* Asset.swift */,
0FFA5D97241F8EB2003B3AF5 /* Entry.swift */,
Expand Down Expand Up @@ -1172,6 +1178,7 @@
0FB4CAC924332C5200A385B1 /* ImageOperation.swift in Sources */,
0F4A245C24224D3100159C24 /* ContentstackResponse.swift in Sources */,
0FFA5D93241F8214003B3AF5 /* EndPoint.swift in Sources */,
678CBD0A2EF10CBA00B72390 /* ContentstackMessages.swift in Sources */,
0FFA5DB4241F99F9003B3AF5 /* FatalError.swift in Sources */,
0F024674243217D800F72181 /* ImageTransformError.swift in Sources */,
0FFA5D74241F6BFA003B3AF5 /* Date.swift in Sources */,
Expand Down Expand Up @@ -1267,6 +1274,7 @@
0FB4CACA24332C5200A385B1 /* ImageOperation.swift in Sources */,
0F4A245D24224D3100159C24 /* ContentstackResponse.swift in Sources */,
0FFA5D94241F8214003B3AF5 /* EndPoint.swift in Sources */,
678CBD072EF10CBA00B72390 /* ContentstackMessages.swift in Sources */,
0FFA5DB6241F99F9003B3AF5 /* FatalError.swift in Sources */,
0F024675243217D800F72181 /* ImageTransformError.swift in Sources */,
0FFA5D75241F6BFA003B3AF5 /* Date.swift in Sources */,
Expand Down Expand Up @@ -1362,6 +1370,7 @@
0FB4CACB24332C5200A385B1 /* ImageOperation.swift in Sources */,
0F4A245E24224D3100159C24 /* ContentstackResponse.swift in Sources */,
0FFA5D95241F8214003B3AF5 /* EndPoint.swift in Sources */,
678CBD092EF10CBA00B72390 /* ContentstackMessages.swift in Sources */,
0FFA5DB8241F99F9003B3AF5 /* FatalError.swift in Sources */,
0F024676243217D800F72181 /* ImageTransformError.swift in Sources */,
0FFA5D76241F6BFA003B3AF5 /* Date.swift in Sources */,
Expand Down Expand Up @@ -1457,6 +1466,7 @@
0FB4CACC24332C5200A385B1 /* ImageOperation.swift in Sources */,
0F4A245F24224D3100159C24 /* ContentstackResponse.swift in Sources */,
0FFA5D96241F8214003B3AF5 /* EndPoint.swift in Sources */,
678CBD082EF10CBA00B72390 /* ContentstackMessages.swift in Sources */,
0FFA5DBA241F99F9003B3AF5 /* FatalError.swift in Sources */,
0F024677243217D800F72181 /* ImageTransformError.swift in Sources */,
0FFA5D77241F6BFA003B3AF5 /* Date.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions Sources/Asset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ extension Asset: ResourceQueryable {
/// ```
public func fetch<ResourceType>(_ completion: @escaping (Result<ResourceType, Error>, ResponseType) -> Void)
where ResourceType: EndpointAccessible, ResourceType: Decodable {
guard let uid = self.uid else { fatalError("Please provide Asset uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.assetUIDRequired) }
self.stack.fetch(endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
parameters: parameters + [QueryParameter.uid: uid],
Expand All @@ -255,7 +255,7 @@ extension Asset: ResourceQueryable {
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public func fetch<ResourceType>() async throws -> ResourceType
where ResourceType: EndpointAccessible & Decodable {
guard let uid = self.uid else { fatalError("Please provide Asset uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.assetUIDRequired) }
let response: ContentstackResponse<ResourceType> = try await self.stack.fetch(
endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
Expand Down
6 changes: 3 additions & 3 deletions Sources/ContentType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class ContentType: CachePolicyAccessible {
///```
public func entry(uid: String? = nil) -> Entry {
if self.uid == nil {
fatalError("Please provide ContentType uid")
fatalError(ContentstackMessages.contentTypeUIDRequired)
}
return Entry(uid, contentType: self)
}
Expand Down Expand Up @@ -160,7 +160,7 @@ extension ContentType: ResourceQueryable {
/// ```
public func fetch<ResourceType>(_ completion: @escaping (Result<ResourceType, Error>, ResponseType) -> Void)
where ResourceType: EndpointAccessible, ResourceType: Decodable {
guard let uid = self.uid else { fatalError("Please provide ContentType uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.contentTypeUIDRequired) }
self.stack.fetch(endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
parameters: parameters + [QueryParameter.uid: uid],
Expand All @@ -187,7 +187,7 @@ extension ContentType: ResourceQueryable {
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public func fetch<ResourceType>() async throws -> ResourceType
where ResourceType: EndpointAccessible & Decodable {
guard let uid = self.uid else { fatalError("Please provide ContentType uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.contentTypeUIDRequired) }
let response: ContentstackResponse<ResourceType> = try await self.stack.fetch(
endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
Expand Down
106 changes: 106 additions & 0 deletions Sources/ContentstackMessages.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
// ContentstackMessages.swift
// Contentstack
//
// Created by Contentstack on 16/12/25.
//

import Foundation

/// Centralized location for all user-facing messages in the Contentstack SDK.
/// This includes error messages, validation messages, and informational messages.
internal enum ContentstackMessages {

// MARK: - UID Required Messages

static let assetUIDRequired = "Asset UID is required. Provide a valid Asset UID and try again."
static let contentTypeUIDRequired = "Content Type UID is required. Provide a valid Content Type UID and try again."
static let entryUIDRequired = "Entry UID is required. Provide a valid Entry UID and try again."
static let globalFieldUIDRequired = "Global Field UID is required. Provide a valid Global Field UID and try again."

// MARK: - URL Validation Messages

static let invalidURLString = "The URL string is not valid. Provide a valid URL and try again."

// MARK: - Sync Messages

static let syncTokenConflict = "Sync Token and Pagination Token cannot be used together. Provide only one token and try again."

// MARK: - Image Transform Messages

static let qualityParameterRange = """
The value for Quality parameters can be entered in \
any whole number (taken as a percentage) between 1 and 100.
"""

static let dprParameterRange = """
The value for dpr parameter could be a whole number (between 0 and 10000) \
or any decimal number (between 0.0 and 9999.9999...).
"""

static let blurParameterRange = """
The value for blur parameter could be a whole decimal number (between 1 and 1000).
"""

static let saturationParameterRange = """
The value for saturation parameter could be a whole decimal number (between -100 and 100).
"""

static let contrastParameterRange = """
The value for contrast parameter could be a whole decimal number (between -100 and 100).
"""

static let brightnessParameterRange = """
The value for brightness parameter could be a whole decimal number (between -100 and 100).
"""

static let sharpenParameterRange = """
The value for `amount` parameter could be a whole decimal number (between 0 and 10). \
The value for `radius` parameter could be a whole decimal number (between 1 and 1000). \
The value for `threshold` parameter could be a whole decimal number (between 0 and 255).
"""

static let cropAspectRatioRequired = """
Along with the crop parameter aspect-ration, \
you also need to specify either the width or height parameter or both \
in the API request to return an output image with the correct dimensions.
"""

static let canvasAspectRatioRequired = """
Along with the canvas parameter aspect-ration, \
you also need to specify either the width or height parameter or both \
in the API request to return an output image with the correct dimensions.
"""

static let invalidHexColor = """
Invalid Hexadecimal value, \
it should be 3-digit or 6-digit hexadecimal value.
"""

static let invalidRGBColor = """
Invalid Red or Blue or Green or alpha value, \
the value ranging anywhere between 0 and 255 for each.
"""

static let invalidRGBAColor = """
Invalid Red or Blue or Green or alpha value, \
the value ranging anywhere between 0 and 255 for each \
and the alpha value with 0.0 being fully transparent \
and 1.0 being completely opaque.
"""

static let duplicateImageTransform = """
Cannot specify two instances of ImageTransform of the same case.\
i.e. `[.format(.png), .format(.jpg)]` is invalid.
"""

static let invalidImageOptions = """
The SDK was unable to generate a valid URL for the given ImageOptions. \
Please contact the maintainer on Github with a copy of the query
"""

// MARK: - Internal/Debug Messages

static let unsupportedEndpointType = "Unsupported endpoint type encountered during response decoding"
}

2 changes: 1 addition & 1 deletion Sources/ContentstackResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ where ItemType: EndpointAccessible & Decodable {
}

default:
print("sync")
ContentstackLogger.log(.error, message: ContentstackMessages.unsupportedEndpointType)
}
}
}
8 changes: 4 additions & 4 deletions Sources/Entry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class Entry: EntryQueryable, CachePolicyAccessible {
/// }
public func query() -> Query {
if self.contentType.uid == nil {
fatalError("Please provide ContentType uid")
fatalError(ContentstackMessages.contentTypeUIDRequired)
}
let query = Query(contentType: self.contentType)
if let uid = self.uid {
Expand Down Expand Up @@ -85,7 +85,7 @@ public class Entry: EntryQueryable, CachePolicyAccessible {
public func query<EntryType>(_ entry: EntryType.Type) -> QueryOn<EntryType>
where EntryType: EntryDecodable & FieldKeysQueryable {
if self.contentType.uid == nil {
fatalError("Please provide ContentType uid")
fatalError(ContentstackMessages.contentTypeUIDRequired)
}
let query = QueryOn<EntryType>(contentType: self.contentType)
if let uid = self.uid {
Expand Down Expand Up @@ -156,7 +156,7 @@ extension Entry: ResourceQueryable {
/// ```
public func fetch<ResourceType>(_ completion: @escaping (Result<ResourceType, Error>, ResponseType) -> Void)
where ResourceType: EndpointAccessible, ResourceType: Decodable {
guard let uid = self.uid else { fatalError("Please provide Entry uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.entryUIDRequired) }
self.stack.fetch(endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
parameters: parameters + [QueryParameter.uid: uid,
Expand Down Expand Up @@ -184,7 +184,7 @@ extension Entry: ResourceQueryable {
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public func fetch<ResourceType>() async throws -> ResourceType
where ResourceType: EndpointAccessible & Decodable {
guard let uid = self.uid else { fatalError("Please provide Entry uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.entryUIDRequired) }
let response: ContentstackResponse<ResourceType> = try await self.stack.fetch(
endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
Expand Down
4 changes: 2 additions & 2 deletions Sources/GlobalField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ extension GlobalField: ResourceQueryable {
/// ```
public func fetch<ResourceType>(_ completion: @escaping (Result<ResourceType, Error>, ResponseType) -> Void)
where ResourceType: EndpointAccessible & Decodable {
guard let uid = self.uid else { fatalError("Please provide Global Field uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.globalFieldUIDRequired) }
self.stack.fetch(endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
parameters: parameters + [QueryParameter.uid: uid],
Expand All @@ -89,7 +89,7 @@ extension GlobalField: ResourceQueryable {
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public func fetch<ResourceType>() async throws -> ResourceType
where ResourceType: EndpointAccessible & Decodable {
guard let uid = self.uid else { fatalError("Please provide Global Field uid") }
guard let uid = self.uid else { fatalError(ContentstackMessages.globalFieldUIDRequired) }
let response: ContentstackResponse<ResourceType> = try await self.stack.fetch(
endpoint: ResourceType.endpoint,
cachePolicy: self.cachePolicy,
Expand Down
39 changes: 7 additions & 32 deletions Sources/ImageOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,7 @@ internal enum ImageOperation: Equatable, Hashable {
case .qualiy(let quality) where quality > 0 && quality <= 100:
return [URLQueryItem(name: ImageParameter.quality, value: String(quality))]
case .qualiy:
let message = """
The value for Quality parameters can be entered in
any whole number (taken as a percentage) between 1 and 100.
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.qualityParameterRange)
case .resize(let resize):
return resize.urlQueryItem()
case .crop(let crop):
Expand Down Expand Up @@ -134,39 +130,23 @@ internal enum ImageOperation: Equatable, Hashable {
case .dpr(let dprValue) where dprValue >= 0 && dprValue < 10000:
return [URLQueryItem(name: ImageParameter.dpr, value: String(dprValue))]
case .dpr:
let message = """
The value for dpr parameter could be a whole number (between 0 and 10000)
or any decimal number (between 0.0 and 9999.9999...).
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.dprParameterRange)
case .blur(let blurvalue) where blurvalue >= 1 && blurvalue < 1000:
return [URLQueryItem(name: ImageParameter.blur, value: String(blurvalue))]
case .blur:
let message = """
The value for blur parameter could be a whole decimal number (between 1 and 1000).
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.blurParameterRange)
case .saturation(let value) where value >= -100 && value <= 100:
return [URLQueryItem(name: ImageParameter.saturation, value: value.stringValue)]
case .saturation:
let message = """
The value for saturation parameter could be a whole decimal number (between -100 and 100).
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.saturationParameterRange)
case .contrast(let value) where value >= -100 && value <= 100:
return [URLQueryItem(name: ImageParameter.contrast, value: value.stringValue)]
case .contrast:
let message = """
The value for contrast parameter could be a whole decimal number (between -100 and 100).
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.contrastParameterRange)
case .brightness(let value) where value >= -100 && value <= 100:
return [URLQueryItem(name: ImageParameter.brightness, value: value.stringValue)]
case .brightness:
let message = """
The value for brightness parameter could be a whole decimal number (between -100 and 100).
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.brightnessParameterRange)
case .fetchFirstFrame:
return [URLQueryItem(name: ImageParameter.frame, value: "1")]
case .sharpen(amount: let amount, radius: let radius, threshold: let threshold)
Expand All @@ -175,12 +155,7 @@ internal enum ImageOperation: Equatable, Hashable {
&& threshold >= 0 && threshold <= 255:
return [URLQueryItem(name: ImageParameter.sharpen, value: "a\(amount),r\(radius),t\(threshold)")]
case .sharpen:
let message = """
The value for `amount` parameter could be a whole decimal number (between 0 and 10).
The value for `radius` parameter could be a whole decimal number (between 1 and 1000).
The value for `threshold` parameter could be a whole decimal number (between 0 and 255).
"""
throw ImageTransformError(message: message)
throw ImageTransformError(message: ContentstackMessages.sharpenParameterRange)
}
}

Expand Down
Loading