diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0023a53
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+.DS_Store
+/.build
+/Packages
+xcuserdata/
+DerivedData/
+.swiftpm/configuration/registries.json
+.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
+.netrc
diff --git a/.swiftpm/WPSwift.xctestplan b/.swiftpm/WPSwift.xctestplan
new file mode 100644
index 0000000..a950784
--- /dev/null
+++ b/.swiftpm/WPSwift.xctestplan
@@ -0,0 +1,32 @@
+{
+ "configurations" : [
+ {
+ "id" : "779FA71B-8A24-4208-8B95-11435B194ED1",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "codeCoverage" : {
+ "targets" : [
+ {
+ "containerPath" : "container:",
+ "identifier" : "WPSwift",
+ "name" : "WPSwift"
+ }
+ ]
+ }
+ },
+ "testTargets" : [
+ {
+ "target" : {
+ "containerPath" : "container:",
+ "identifier" : "WPSwiftTests",
+ "name" : "WPSwiftTests"
+ }
+ }
+ ],
+ "version" : 1
+}
diff --git a/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/WPSwift.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/WPSwift.xcscheme
new file mode 100644
index 0000000..ead1f8d
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/WPSwift.xcscheme
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Package.swift b/Package.swift
new file mode 100644
index 0000000..96c2d22
--- /dev/null
+++ b/Package.swift
@@ -0,0 +1,24 @@
+// swift-tools-version: 5.9
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "WPSwift",
+ defaultLocalization: "en",
+ products: [
+ // Products define the executables and libraries a package produces, making them visible to other packages.
+ .library(
+ name: "WPSwift",
+ targets: ["WPSwift"]),
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products from dependencies.
+ .target(
+ name: "WPSwift"),
+ .testTarget(
+ name: "WPSwiftTests",
+ dependencies: ["WPSwift"]),
+ ]
+)
diff --git a/Sources/WPSwift/Localizable.swift b/Sources/WPSwift/Localizable.swift
new file mode 100644
index 0000000..6909839
--- /dev/null
+++ b/Sources/WPSwift/Localizable.swift
@@ -0,0 +1,66 @@
+//
+// File.swift
+//
+//
+// Created by Ulaş Sancak on 1.10.2023.
+//
+
+import Foundation
+
+protocol AllKeys {
+ static var allKeys: [String] { get }
+}
+
+protocol Localizable: RawRepresentable, CaseIterable, AllKeys where RawValue == String {}
+
+extension Localizable {
+ static var allKeys: [String] {
+ allCases.map { $0.rawValue }
+ }
+}
+
+public enum Localization: String, Localizable {
+ //Default cases
+ case ok
+ case yes
+ case no
+ case cancel
+ case success
+ case failure
+ case unknown
+ case unknownError = "unknown_error"
+ case error
+ case done
+ case next
+
+ //All keys as nested. This needs to be updated if another nested enum is added.
+ public static var allKeys: [String] {
+ allCases.map({ $0.rawValue })
+ + Configuration.allKeys
+ }
+
+ //Cases for specific parts
+
+ enum Configuration {
+ enum Error: String, Localizable {
+ case notSetup = "configuration.error.notSetup"
+ case route = "configuration.error.route"
+ case namespace = "configuration.error.namespace"
+ }
+
+ static var allKeys: [String] {
+ Error.allKeys
+ }
+ }
+}
+
+extension Localizable {
+ var localized: String {
+ NSLocalizedString(rawValue, bundle: Bundle.module, comment: "")
+ }
+
+ func localized(_ args: CVarArg...) -> String {
+ String(format: localized, args)
+ }
+}
+
diff --git a/Sources/WPSwift/Resources/en.lproj/Localizable.strings b/Sources/WPSwift/Resources/en.lproj/Localizable.strings
new file mode 100644
index 0000000..833dbc1
--- /dev/null
+++ b/Sources/WPSwift/Resources/en.lproj/Localizable.strings
@@ -0,0 +1,25 @@
+/*
+ Localizable.strings
+
+
+ Created by Ulaş Sancak on 1.10.2023.
+
+*/
+
+//General
+"ok" = "OK";
+"yes" = "Yes";
+"no" = "No";
+"cancel" = "Cancel";
+"success" = "Success";
+"failure" = "Failure";
+"unknown" = "Unknown";
+"unknown_error" = "Unknown error";
+"error" = "Error";
+"done" = "Done";
+"next" = "Next";
+
+//Setup Configuration
+"configuration.error.notSetup" = "Wordpress Configuration was not setup. Use WPSwift.configuration function to set it up.";
+"configuration.error.route" = "Wordpress `route` is empty. Use WPSwift.configuration function to set it up.";
+"configuration.error.namespace" = "Wordpress `namespace` is empty. Use WPSwift.configuration function to set it up.";
diff --git a/Sources/WPSwift/Resources/tr.lproj/Localizable.strings b/Sources/WPSwift/Resources/tr.lproj/Localizable.strings
new file mode 100644
index 0000000..58cdf94
--- /dev/null
+++ b/Sources/WPSwift/Resources/tr.lproj/Localizable.strings
@@ -0,0 +1,25 @@
+/*
+ Localizable.strings
+
+
+ Created by Ulaş Sancak on 1.10.2023.
+
+*/
+
+//Genel
+"ok" = "TAMAM";
+"yes" = "Evet";
+"no" = "Hayır";
+"cancel" = "İptal";
+"success" = "Başarılı";
+"failure" = "Hata";
+"unknown" = "Bilinmeyen";
+"unknown_error" = "Bilinmeyen hata";
+"error" = "Hata";
+"done" = "Bitti";
+"next" = "Sonraki";
+
+//Setup Configuration
+"configuration.error.notSetup" = "Wordpress konfigurasyonu oluşturulmamış. WPSwift.initialize fonksiyonunu kullanın.";
+"configuration.error.route" = "Wordpress `route` boş görünüyor. WPSwift.initialize fonksiyonunu kullanın.";
+"configuration.error.namespace" = "Wordpress `namespace` boş görünüyor. WPSwift.initialize fonksiyonunu kullanın.";
diff --git a/Sources/WPSwift/WPSwift.swift b/Sources/WPSwift/WPSwift.swift
new file mode 100644
index 0000000..0bf605a
--- /dev/null
+++ b/Sources/WPSwift/WPSwift.swift
@@ -0,0 +1,47 @@
+// The Swift Programming Language
+// https://docs.swift.org/swift-book
+import Foundation
+
+enum WPConfigurationError: LocalizedError {
+ case wasNotSetup
+ case route
+ case namespace
+
+ var errorDescription: String? {
+ switch self {
+ case .wasNotSetup:
+ Localization.Configuration.Error.notSetup.localized
+ case .route:
+ Localization.Configuration.Error.route.localized
+ case .namespace:
+ Localization.Configuration.Error.namespace.localized
+ }
+ }
+}
+
+struct WPConfiguration {
+ let route: String
+ let namespace: String
+}
+
+public struct WPSwift {
+ static internal var configuration: WPConfiguration {
+ get throws {
+ guard let _configuration else { throw WPConfigurationError.wasNotSetup }
+ guard !_configuration.route.isEmpty else { throw WPConfigurationError.route }
+ guard !_configuration.namespace.isEmpty else { throw WPConfigurationError.namespace }
+ return _configuration
+ }
+ }
+ static private var _configuration: WPConfiguration?
+
+ static func resetConfiguration() {
+ _configuration = nil
+ }
+}
+
+public extension WPSwift {
+ static func initialize(route: String, namespace: String) {
+ WPSwift._configuration = .init(route: route, namespace: namespace)
+ }
+}
diff --git a/Tests/WPSwiftTests/LocalizationTests.swift b/Tests/WPSwiftTests/LocalizationTests.swift
new file mode 100644
index 0000000..0d8aa7d
--- /dev/null
+++ b/Tests/WPSwiftTests/LocalizationTests.swift
@@ -0,0 +1,39 @@
+//
+// WPSwiftSetupTests.swift
+//
+//
+// Created by Ulaş Sancak on 30.09.2023.
+//
+
+import XCTest
+@testable import WPSwift
+
+class LocalizationTests: XCTestCase {
+
+ func testLocalizations() throws {
+ let localizations = Bundle.module.localizations
+ for localization in localizations {
+ guard let path = Bundle.module.path(forResource: localization, ofType: "lproj"),
+ let bundle = Bundle(path: path) else {
+ XCTAssert(false, "Localization file is missing for '" + localization + "'.")
+ return
+ }
+ guard let localizationPath = bundle.path(forResource: "Localizable", ofType: "strings") else {
+ XCTAssert(false, "Localizable.strings file is missing for " + localization + ".")
+ return
+ }
+ guard let localizationKeys = NSDictionary(contentsOfFile: localizationPath)?.allKeys as? [String] else {
+ XCTAssert(false, localization + "localization file is curropted.")
+ return
+ }
+ let allKeys = Localization.allKeys
+ for key in allKeys {
+ XCTAssert(localizationKeys.contains(key), key + " key is missing from the " + localization + " file")
+ }
+ for key in localizationKeys {
+ XCTAssert(allKeys.contains(key), "Found key '" + key + "' in localization file(" + localization + ") is not in Localization nested enum.")
+ }
+ }
+ }
+
+}
diff --git a/Tests/WPSwiftTests/WPSwiftSetupTests.swift b/Tests/WPSwiftTests/WPSwiftSetupTests.swift
new file mode 100644
index 0000000..2ec40c9
--- /dev/null
+++ b/Tests/WPSwiftTests/WPSwiftSetupTests.swift
@@ -0,0 +1,46 @@
+//
+// WPSwiftSetupTests.swift
+//
+//
+// Created by Ulaş Sancak on 30.09.2023.
+//
+
+import XCTest
+@testable import WPSwift
+
+final class WPSwiftSetupTests: XCTestCase {
+ override func setUp() async throws {
+ WPSwift.resetConfiguration()
+ }
+
+ func testSetupSuccess() throws {
+ WPSwift.initialize(route: "https://www.example.com/wp-json", namespace: "wp/v2")
+ _ = try WPSwift.configuration
+ }
+
+ func testSetupFailure() throws {
+ do {
+ _ = try WPSwift.configuration
+ } catch WPConfigurationError.wasNotSetup {
+ XCTAssertEqual(WPConfigurationError.wasNotSetup.errorDescription, "Wordpress Configuration was not setup. Use WPSwift.configuration function to set it up.", "WPConfigurationError.wasNotSetup is incorrect.")
+ }
+ }
+
+ func testRouteSetupFailure() throws {
+ WPSwift.initialize(route: "", namespace: "wp/v2")
+ do {
+ _ = try WPSwift.configuration
+ } catch WPConfigurationError.route {
+ XCTAssertEqual(WPConfigurationError.route.errorDescription, "Wordpress `route` is empty. Use WPSwift.configuration function to set it up.", "WPConfigurationError.route is incorrect.")
+ }
+ }
+
+ func testNamespaceSetupFailure() throws {
+ WPSwift.initialize(route: "https://www.example.com/wp-json", namespace: "")
+ do {
+ _ = try WPSwift.configuration
+ } catch WPConfigurationError.namespace {
+ XCTAssertEqual(WPConfigurationError.namespace.errorDescription, "Wordpress `namespace` is empty. Use WPSwift.configuration function to set it up.", "WPConfigurationError.namespace is incorrect.")
+ }
+ }
+}