diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 00000000..0083aacf --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,23 @@ +# Cursor Rules – Contentstack Swift CDA SDK + +This directory contains Cursor AI rules that apply when working in this repository. Rules provide persistent context so the AI follows project conventions and Contentstack CDA patterns. + +## How rules are applied + +- **File-specific rules** use the `globs` frontmatter: they apply when you open or edit files matching that pattern. +- **Always-on rules** use `alwaysApply: true`: they are included in every conversation in this project. + +## Rule index + +| File | Applies when | Purpose | +|------|--------------|---------| +| **dev-workflow.md** | (Reference only; no glob) | Core development workflow: branches, running tests, PR expectations. Read for process guidance. | +| **swift.mdc** | Editing any `**/*.swift` file | Swift standards: naming, `Sources`/`Tests` layout, module **ContentstackSwift**, logging, optionals and error style. | +| **contentstack-swift-cda.mdc** | Editing `Sources/**/*.swift` | CDA-specific patterns: Stack/ContentstackConfig, host/version/region/branch, URLSession, `Result`/`ResultsHandler`, alignment with Content Delivery API. | +| **testing.mdc** | Editing `Tests/**/*.swift` | Testing patterns: XCTest, unit vs integration tests, fixtures, DVR where used. | +| **code-review.mdc** | Always | PR/review checklist: API stability, error handling, backward compatibility, dependencies and security (e.g. SCA). | + +## Related + +- **AGENTS.md** (repo root) – Main entry point for AI agents: project overview, entry points, and pointers to rules and skills. +- **skills/** – Reusable skill docs (Contentstack Swift CDA, testing, code review, framework) for deeper guidance on specific tasks. diff --git a/.cursor/rules/code-review.mdc b/.cursor/rules/code-review.mdc new file mode 100644 index 00000000..e7c91881 --- /dev/null +++ b/.cursor/rules/code-review.mdc @@ -0,0 +1,36 @@ +--- +description: PR and code review checklist – API stability, errors, compatibility, security +alwaysApply: true +--- + +# Code Review Checklist – Contentstack Swift CDA SDK + +Use this checklist when reviewing pull requests or before opening a PR. + +## API design and stability + +- [ ] **Public API:** New or changed public types/methods/properties are necessary and clearly documented (Swift documentation comments where the project documents public API). +- [ ] **Backward compatibility:** No breaking changes to public API unless explicitly called out and justified (e.g. major version). +- [ ] **Naming:** Names are consistent with existing SDK style and CDA terminology. + +## Error handling and robustness + +- [ ] **Errors:** API failures surface through the SDK **`Error`** type and existing **`Result` / `ResultsHandler`** patterns (or `async`/`throws` where the API already uses them). +- [ ] **Optionals:** No unintended force-unwraps; optional values are handled or documented; public contracts use optionals intentionally. +- [ ] **Throws:** Thrown errors are appropriate for the API; callers can distinguish failure modes where the SDK promises it. + +## Dependencies and security + +- [ ] **Dependencies:** No new dependencies without justification; version bumps are intentional and do not introduce known vulnerabilities. +- [ ] **SCA:** Address any security findings (e.g. from Snyk or similar) in the scope of the PR or in a follow-up. + +## Testing + +- [ ] **Coverage:** New or modified behavior is covered by unit and/or integration tests as appropriate. +- [ ] **Test quality:** Tests are readable, stable (no flakiness), and follow project conventions (see **testing.mdc**). + +## Severity (optional) + +- **Blocker:** Must fix before merge (e.g. breaking public API without approval, security issue, no tests for new code). +- **Major:** Should fix (e.g. inconsistent error handling, missing documentation on new public API). +- **Minor:** Nice to fix (e.g. style, minor docs). diff --git a/.cursor/rules/contentstack-swift-cda.mdc b/.cursor/rules/contentstack-swift-cda.mdc new file mode 100644 index 00000000..4380b55f --- /dev/null +++ b/.cursor/rules/contentstack-swift-cda.mdc @@ -0,0 +1,35 @@ +--- +description: Contentstack CDA patterns – Stack/ContentstackConfig, URLSession, callbacks, Content Delivery API +globs: "Sources/**/*.swift" +--- + +# Contentstack Swift CDA – SDK Rules + +Apply when editing the SDK core (`Sources/`). Keep behavior aligned with the [Content Delivery API](https://www.contentstack.com/docs/apis/content-delivery-api/). + +## Stack and ContentstackConfig + +- **Entry point:** `Contentstack.stack(apiKey:deliveryToken:environment:region:host:apiVersion:branch:config:)` returns a **`Stack`**. Pass **`ContentstackConfig`** for optional settings. +- **Default host:** `Host.delivery` → **`cdn.contentstack.io`**; non-US regions adjust the host (see `Contentstack.stack` implementation). +- **API version:** Default **`v3`** via the `apiVersion` parameter. +- **Config:** `URLSessionConfiguration` (headers merged with SDK auth headers), `dateDecodingStrategy`, `timeZone`, `earlyAccess`, `urlSessionDelegate` for SSL pinning / session customization. +- **Region / branch:** Use `ContentstackRegion` and optional `branch` on `stack(...)`; branch is sent as the `branch` header when set. + +## HTTP layer + +- **Requests** use **`URLSession`** created in **`Stack`** from `ContentstackConfig`. Do not bypass it for CDA calls. +- **Headers:** Preserve `User-Agent` / `X-User-Agent` and authorization-related headers the SDK sets; additional headers may come from `sessionConfiguration.httpAdditionalHeaders`. +- **Errors:** Map API failures to the SDK **`Error`** type and deliver them via **`Result`** / **`ResultsHandler`** (or existing async patterns). + +## Retry and resilience + +- The Swift SDK does not mirror the Java SDK’s **`RetryOptions` / interceptor** stack; resilience is primarily **`URLSession`** behavior and configuration. If adding retry or backoff, keep it configurable via **`ContentstackConfig`** / session and document defaults; align semantics with other CDA SDKs where practical. + +## Callbacks and async + +- Use existing completion types (**`ResultsHandler`**, `Result<..., Error>` closures) for async results. Do not introduce incompatible callback shapes without considering backward compatibility. +- When adding `async` APIs, mirror existing naming and error mapping. + +## CDA concepts + +- **Entry, Query, Asset, Content Type, Sync, Taxonomy, Global Field** – follow existing types and method names and CDA semantics (query parameters, response models). When adding CDA features, align with the official Content Delivery API documentation. diff --git a/.cursor/rules/dev-workflow.md b/.cursor/rules/dev-workflow.md new file mode 100644 index 00000000..ab87fa37 --- /dev/null +++ b/.cursor/rules/dev-workflow.md @@ -0,0 +1,29 @@ +# Development Workflow – Contentstack Swift CDA SDK + +Use this as the standard workflow when contributing to the Swift CDA SDK. + +## Branches + +- Use feature branches for changes (e.g. `feat/...`, `fix/...`). +- Base work off the appropriate long-lived branch (e.g. `staging`, `development`, `main`) per team norms. + +## Running tests + +- **SPM (from repo root):** `swift test` +- **SPM build only:** `swift build` +- **Xcode:** Open `ContentstackSwift.xcodeproj`, select a scheme (e.g. **ContentstackSwift iOS Tests**), and run tests (⌘U). +- **xcodebuild (example):** + `xcodebuild -project ContentstackSwift.xcodeproj -scheme "ContentstackSwift iOS" -destination 'platform=iOS Simulator,name=iPhone 16' test` + Adjust scheme and destination for macOS or tvOS as needed. + +Run tests before opening a PR. Tests that call the live CDA may require stack credentials (e.g. `Tests/config.json` or environment-specific setup—do not commit real tokens). + +## Pull requests + +- Ensure the build passes: `swift test` and/or Xcode tests for affected platforms. +- Follow the **code-review** rule (see `.cursor/rules/code-review.mdc`) for the PR checklist. +- Keep changes backward-compatible for public API; call out any breaking changes clearly. + +## Optional: TDD + +If the team uses TDD, follow RED–GREEN–REFACTOR when adding behavior: write a failing test first, then implement to pass, then refactor. The **testing** rule and **skills/testing** skill describe test structure and naming. diff --git a/.cursor/rules/swift.mdc b/.cursor/rules/swift.mdc new file mode 100644 index 00000000..7d4339ac --- /dev/null +++ b/.cursor/rules/swift.mdc @@ -0,0 +1,45 @@ +--- +description: Swift standards and ContentstackSwift module conventions for the CDA SDK +globs: "**/*.swift" +--- + +# Swift Standards – Contentstack Swift CDA SDK + +Apply these conventions when editing Swift code in this repository. + +## Language and tooling + +- Match the **Swift** language version expected by `Package.swift` (swift-tools-version) and the Xcode project; avoid APIs that require a newer OS/SDK than declared platforms unless the change is intentional. +- Prefer clear, idiomatic Swift over Objective-C patterns. + +## Module and layout + +- Library code lives under **`Sources/`** and builds the **`ContentstackSwift`** module. +- Tests live under **`Tests/`** and depend on **ContentstackSwift** (see **testing.mdc** for test-specific rules). + +## Naming + +- **Types:** PascalCase (e.g. `Stack`, `ContentstackConfig`, `ContentstackResponse`). +- **Methods and variables:** camelCase. +- **Cases in enums:** lowerCamelCase unless matching external API raw values. + +## SDK structure + +- **`Contentstack`** is the factory; **`Stack`** owns networking and resource accessors (`contentType`, `asset`, `sync`, `taxonomy`, etc.). +- Keep public surface area minimal; use `internal` for implementation details unless a wider API is required. + +## Logging + +- Use **`ContentstackLogger`** (or existing logging helpers in the SDK) consistently with current call sites. +- Avoid `print` in library code unless that is already the established pattern for a specific diagnostic path. + +## Optionals and errors + +- Prefer **`Result`** and **`ResultsHandler`** for async completion APIs where that is the existing pattern. +- Avoid force unwraps (`!`); use `guard let` / `if let` or explicit error handling. +- When adding `throws`, document which errors callers should handle. + +## General + +- Prefer value types where appropriate; reference types (`class`) are used where identity or inheritance is required (e.g. `Stack`). +- Document public API with `///` comments where the project already documents symbols; keep examples aligned with real usage (`Contentstack.stack(...)`, `ContentstackConfig`). diff --git a/.cursor/rules/testing.mdc b/.cursor/rules/testing.mdc new file mode 100644 index 00000000..135ee577 --- /dev/null +++ b/.cursor/rules/testing.mdc @@ -0,0 +1,34 @@ +--- +description: XCTest patterns, unit vs integration, fixtures and config for Contentstack Swift tests +globs: "Tests/**/*.swift" +--- + +# Testing Rules – Contentstack Swift CDA SDK + +Apply when writing or editing tests. The project uses **XCTest** via SPM (`Tests/`) and Xcode test bundles. + +## Test naming and layout + +- **Unit tests:** Prefer descriptive type names ending in **`Test`** or **`Tests`** (e.g. `EntryTest`, `StackTest`, `QueryTest`) matching existing files under `Tests/`. +- **Integration / API tests:** Classes that perform live HTTP against Contentstack often end in **`APITest`** or **`Test`** with network setup—follow existing peers (`*APITest.swift`, sync/asset/entry API tests). Use shared helpers (e.g. stack builders, `Tests/config.json`) where the suite already does. + +## XCTest usage + +- Subclass **`XCTestCase`** (or use extensions on it where the project does). +- Use **`XCTAssert*`** macros; prefer specific assertions over generic truth checks. +- Use **`XCTestExpectation`** for asynchronous completion handlers when not using async test methods. + +## Test data and credentials + +- **Fixtures:** JSON and resources under `Tests/` (e.g. `*.json`) are copied into test bundles via the Xcode project; keep them in sync when changing test expectations. +- **Live stack:** Do not commit real API keys or delivery tokens. Use local `Tests/config.json` or CI secrets per team practice. Document required keys for integration tests in README or internal docs. + +## Unit vs integration + +- **Unit:** Mocked or offline data, fast, no network dependency where possible (DVR-cassette tests may apply). +- **Integration:** Real `Stack` and CDA calls—gate on credentials and use reasonable timeouts to avoid hanging CI. + +## Quality + +- Keep tests deterministic; avoid time- and order-dependent assumptions unless documented. +- When changing production behavior, update or add tests in the same area (query, entry, asset, sync, etc.). diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..1b493775 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,51 @@ +# Contentstack Swift CDA SDK – Agent Guide + +This document is the main entry point for AI agents working in this repository. + +## Project + +- **Name:** Contentstack Swift CDA SDK (contentstack-swift) +- **Purpose:** Swift client for the Contentstack **Content Delivery API (CDA)**. It fetches content (entries, assets, content types, sync, taxonomy, global fields) from Contentstack for iOS, macOS, tvOS, watchOS, and Swift Package Manager consumers. +- **Repo:** [contentstack-swift](https://github.com/contentstack/contentstack-swift) + +## Tech stack + +- **Language:** Swift (SPM minimum **swift-tools-version 5.6**; align with Xcode requirements in README) +- **Build:** Swift Package Manager (`Package.swift`), **Xcode** (`ContentstackSwift.xcodeproj`) for multi-platform frameworks and CocoaPods (`ContentstackSwift.podspec`) +- **Testing:** **XCTest** (`Tests/`), optional **DVR** (HTTP recording) for some tests; integration-style tests may use `Tests/config.json` / stack credentials +- **HTTP:** **URLSession** (configured via `ContentstackConfig.sessionConfiguration`), optional **`CSURLSessionDelegate`** (SSL pinning / customization) +- **Other:** [contentstack-utils-swift](https://github.com/contentstack/contentstack-utils-swift) (Rich text rendering) + +## Main entry points + +- **`Contentstack`** – Static factory: `Contentstack.stack(apiKey:deliveryToken:environment:region:host:apiVersion:branch:config:)` returns a `Stack`. +- **`Stack`** – Main API surface: content types, entries, assets, sync, taxonomy, queries, cache policy, JSON decoding. +- **`ContentstackConfig`** – Optional configuration: `URLSessionConfiguration`, date/time zone decoding, early access headers, `urlSessionDelegate`, user agent. +- **Paths:** `Sources/` (library target **ContentstackSwift**), `Tests/` (test target **ContentstackTests**). + +## Commands + +- **SPM build:** `swift build` +- **SPM tests:** `swift test` +- **Xcode:** Open `ContentstackSwift.xcodeproj`, then build/test schemes such as **ContentstackSwift iOS**, **ContentstackSwift macOS**, **ContentstackSwift tvOS** (and matching test targets). +- **xcodebuild (example – adjust simulator/OS):** + `xcodebuild -project ContentstackSwift.xcodeproj -scheme "ContentstackSwift iOS" -destination 'platform=iOS Simulator,name=iPhone 16' build test` + +Run tests before opening a PR. API/integration tests that hit a live stack need valid credentials (see test helpers and `Tests/config.json` where applicable); do not commit secrets. + +## Rules and skills + +- **`.cursor/rules/`** – Cursor rules for this repo: + - **README.md** – Index of all rules and when each applies (globs / always-on). + - **dev-workflow.md** – Development workflow (branches, tests, PR expectations). + - **swift.mdc** – Applies to `**/*.swift`: Swift style, module layout, logging, optionals. + - **contentstack-swift-cda.mdc** – Applies to `Sources/**/*.swift`: CDA patterns, Stack/Config, host/version/region/branch, callbacks, alignment with Content Delivery API. + - **testing.mdc** – Applies to `Tests/**/*.swift`: test naming, unit vs integration, XCTest. + - **code-review.mdc** – Always applied: PR/review checklist (aligned with other Contentstack CDA SDKs). +- **`skills/`** – Reusable skill docs: + - Use **contentstack-swift-cda** when implementing or changing CDA API usage or SDK core behavior. + - Use **testing** when adding or refactoring tests. + - Use **code-review** when reviewing PRs or before opening one. + - Use **framework** when changing config, URL session setup, or HTTP-related behavior (`ContentstackConfig`, `Stack` networking). + +Refer to `.cursor/rules/README.md` for when each rule applies and to `skills/README.md` for skill details. diff --git a/ContentstackSwift.xcodeproj/project.pbxproj b/ContentstackSwift.xcodeproj/project.pbxproj index f4e09899..072274c7 100644 --- a/ContentstackSwift.xcodeproj/project.pbxproj +++ b/ContentstackSwift.xcodeproj/project.pbxproj @@ -88,9 +88,6 @@ 0F4C0A82243C470F006604B7 /* ContentstackLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F4C0A80243C470F006604B7 /* ContentstackLogger.swift */; }; 0F4C0A83243C470F006604B7 /* ContentstackLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F4C0A80243C470F006604B7 /* ContentstackLogger.swift */; }; 0F4C0A84243C470F006604B7 /* ContentstackLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F4C0A80243C470F006604B7 /* ContentstackLogger.swift */; }; - 0F4C0A87243C6990006604B7 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = 0F4C0A86243C6990006604B7 /* config.json */; }; - 0F4C0A88243C6990006604B7 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = 0F4C0A86243C6990006604B7 /* config.json */; }; - 0F4C0A89243C6990006604B7 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = 0F4C0A86243C6990006604B7 /* config.json */; }; 0F4FBCA02420B0E4007B8CAE /* DateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F4FBC9F2420B0E4007B8CAE /* DateTest.swift */; }; 0F4FBCA12420B0E4007B8CAE /* DateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F4FBC9F2420B0E4007B8CAE /* DateTest.swift */; }; 0F4FBCA22420B0E4007B8CAE /* DateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F4FBC9F2420B0E4007B8CAE /* DateTest.swift */; }; @@ -309,6 +306,9 @@ 67AA39162EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */; }; 67AA39172EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */; }; 67AA39182EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */; }; + 67BA83032F6D36F3005006B8 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = 67BA83022F6D36ED005006B8 /* config.json */; }; + 67BA83042F6D36F3005006B8 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = 67BA83022F6D36ED005006B8 /* config.json */; }; + 67BA83052F6D36F3005006B8 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = 67BA83022F6D36ED005006B8 /* config.json */; }; 67EE21DF2DDB4013005AC119 /* CSURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */; }; 67EE21E02DDB4013005AC119 /* CSURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */; }; 67EE21E12DDB4013005AC119 /* CSURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */; }; @@ -391,7 +391,6 @@ 0F4A7641241BB3C600E3A024 /* ContentstackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentstackTests.swift; sourceTree = ""; }; 0F4C0A7B243C4579006604B7 /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; 0F4C0A80243C470F006604B7 /* ContentstackLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentstackLogger.swift; sourceTree = ""; }; - 0F4C0A86243C6990006604B7 /* config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = config.json; sourceTree = ""; }; 0F4FBC9A2420A17F007B8CAE /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; 0F4FBC9F2420B0E4007B8CAE /* DateTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTest.swift; sourceTree = ""; }; 0F4FBCA32420B5F4007B8CAE /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; @@ -473,6 +472,7 @@ 67AA390D2EB9D49600C0E2C0 /* CSDefinitionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSDefinitionsTest.swift; sourceTree = ""; }; 67AA39112EBA063300C0E2C0 /* TaxonomyUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxonomyUnitTest.swift; sourceTree = ""; }; 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackInitializationTest.swift; sourceTree = ""; }; + 67BA83022F6D36ED005006B8 /* config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = config.json; sourceTree = ""; }; 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSURLSessionDelegate.swift; sourceTree = ""; }; 67EE222B2DE4868F005AC119 /* GlobalField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalField.swift; sourceTree = ""; }; 67EE22302DE58B51005AC119 /* GlobalFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalFieldModel.swift; sourceTree = ""; }; @@ -643,7 +643,7 @@ 0F4C0A85243C6781006604B7 /* Cofig */ = { isa = PBXGroup; children = ( - 0F4C0A86243C6990006604B7 /* config.json */, + 67BA83022F6D36ED005006B8 /* config.json */, ); name = Cofig; sourceTree = ""; @@ -1089,12 +1089,12 @@ buildActionMask = 2147483647; files = ( 0F359995257BE30A00B3DB89 /* SyncTest.json in Resources */, + 67BA83042F6D36F3005006B8 /* config.json in Resources */, 0F359993257BE2D100B3DB89 /* Entry.json in Resources */, 0F359994257BE2EE00B3DB89 /* QueryOn.json in Resources */, 0F359991257BE29B00B3DB89 /* Asset.json in Resources */, 0F359992257BE2A700B3DB89 /* ContentType.json in Resources */, 67EE22692DE719B6005AC119 /* GlobalField.json in Resources */, - 0F4C0A87243C6990006604B7 /* config.json in Resources */, 0F5794C2266A37120082815C /* Paragraph.Json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1112,12 +1112,12 @@ buildActionMask = 2147483647; files = ( 0F1DCC7A243D9BD400EED404 /* SyncTest.json in Resources */, + 67BA83052F6D36F3005006B8 /* config.json in Resources */, 0F244F9E244062B4003C3F26 /* ContentType.json in Resources */, 0FFBB4482446F9A4000D2795 /* Asset.json in Resources */, 0F50EA17244ED7F500E5D705 /* QueryOn.json in Resources */, 0F796C532449EA8700EA04D5 /* Entry.json in Resources */, 67EE22652DE719B6005AC119 /* GlobalField.json in Resources */, - 0F4C0A88243C6990006604B7 /* config.json in Resources */, 0F5794C3266A37120082815C /* Paragraph.Json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1135,12 +1135,12 @@ buildActionMask = 2147483647; files = ( 0F1DCC7B243D9BD400EED404 /* SyncTest.json in Resources */, + 67BA83032F6D36F3005006B8 /* config.json in Resources */, 0F244F9F244062B4003C3F26 /* ContentType.json in Resources */, 0FFBB4492446F9A4000D2795 /* Asset.json in Resources */, 0F50EA18244ED7F500E5D705 /* QueryOn.json in Resources */, 0F796C542449EA8700EA04D5 /* Entry.json in Resources */, 67EE22672DE719B6005AC119 /* GlobalField.json in Resources */, - 0F4C0A89243C6990006604B7 /* config.json in Resources */, 0F5794C4266A37120082815C /* Paragraph.Json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift iOS Tests.xcscheme b/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift iOS Tests.xcscheme new file mode 100644 index 00000000..3fd1a138 --- /dev/null +++ b/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift iOS Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift iOS.xcscheme b/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift iOS.xcscheme new file mode 100644 index 00000000..d821a067 --- /dev/null +++ b/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift iOS.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift tvOS.xcscheme b/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift tvOS.xcscheme new file mode 100644 index 00000000..a567e77a --- /dev/null +++ b/ContentstackSwift.xcodeproj/xcshareddata/xcschemes/ContentstackSwift tvOS.xcscheme @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/config.json b/Tests/config.json new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Tests/config.json @@ -0,0 +1 @@ + diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 00000000..0d51b5eb --- /dev/null +++ b/skills/README.md @@ -0,0 +1,21 @@ +# Skills – Contentstack Swift CDA SDK + +This directory contains **skills**: reusable guidance for AI agents (and developers) on specific tasks. Each skill is a folder with a `SKILL.md` file. + +## When to use which skill + +| Skill | Use when | +|-------|----------| +| **contentstack-swift-cda** | Implementing or changing CDA features: Stack/ContentstackConfig, entries, assets, content types, sync, taxonomy, global fields, URLSession usage, callbacks, error handling. | +| **testing** | Writing or refactoring tests: XCTest, unit vs integration layout, fixtures, `Tests/config.json`, DVR where applicable. | +| **code-review** | Reviewing a PR or preparing your own: API design, optionals/errors, backward compatibility, dependencies/security, test coverage. | +| **framework** | Touching configuration or HTTP session behavior: `ContentstackConfig`, `URLSession`/`URLSessionConfiguration`, `CSURLSessionDelegate`, headers, cache. | + +## How agents should use skills + +- **contentstack-swift-cda:** Apply when editing SDK core (`Sources/`) or adding CDA-related behavior. Follow Stack/Config, CDA API alignment, and existing `Result` / completion-handler patterns. +- **testing:** Apply when creating or modifying test types under `Tests/`. Follow existing naming (`*Test`, `*APITest`) and shared test utilities. +- **code-review:** Apply when performing or simulating a PR review. Go through the checklist (API stability, errors, compatibility, dependencies, tests) and optional severity levels. +- **framework:** Apply when changing `ContentstackConfig`, session creation in `Stack`, or delegate/cache behavior. Keep networking consistent across the SDK. + +Each skill’s `SKILL.md` contains more detailed instructions and references. diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 00000000..c8c9ab10 --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,60 @@ +--- +name: code-review +description: Use when reviewing PRs or before opening a PR – API design, optionals/errors, backward compatibility, dependencies, security, and test quality +--- + +# Code Review – Contentstack Swift CDA SDK + +Use this skill when performing or preparing a pull request review for the Swift CDA SDK. + +## When to use + +- Reviewing someone else’s PR. +- Self-reviewing your own PR before submission. +- Checking that changes meet project standards (API, errors, compatibility, tests, security). + +## Instructions + +Work through the checklist below. Optionally tag items with severity: **Blocker**, **Major**, **Minor**. + +### 1. API design and stability + +- [ ] **Public API:** New or changed public types/methods are necessary and documented (`///` where the project documents public symbols, with parameters/returns as appropriate). +- [ ] **Backward compatibility:** No breaking changes to public API unless explicitly agreed (e.g. major version). Deprecations should use `@available` / messaging with alternatives where Swift allows. +- [ ] **Naming:** Consistent with existing SDK style and CDA terminology (`Stack`, `Entry`, `Query`, `ContentstackConfig`). + +**Severity:** Breaking public API without approval = Blocker. Missing docs on new public API = Major. + +### 2. Error handling and robustness + +- [ ] **Errors:** Failures map to the SDK `Error` type and existing `Result` / completion patterns. +- [ ] **Optionals:** No inappropriate force unwraps; optionals are meaningful and handled. +- [ ] **Throws:** `throws` APIs document failure modes; callers can handle errors predictably. + +**Severity:** Wrong or missing error handling in new code = Major. + +### 3. Dependencies and security + +- [ ] **Dependencies:** New or upgraded Swift packages / pods are justified; versions do not introduce known vulnerabilities. +- [ ] **SCA:** Security findings (e.g. Snyk, Dependabot) in the change set are addressed or explicitly deferred with a ticket. + +**Severity:** New critical/high vulnerability = Blocker. + +### 4. Testing + +- [ ] **Coverage:** New or modified behavior has corresponding unit and/or integration tests. +- [ ] **Conventions:** Tests follow existing naming and layout under `Tests/`. +- [ ] **Quality:** Tests are readable, deterministic (no flakiness), and assert meaningful behavior. + +**Severity:** No tests for new behavior = Blocker. Flaky or weak tests = Major. + +### 5. Optional severity summary + +- **Blocker:** Must fix before merge (e.g. breaking API without approval, security issue, no tests for new code). +- **Major:** Should fix (e.g. inconsistent error handling, missing documentation on new public API, flaky tests). +- **Minor:** Nice to fix (e.g. style, minor docs, redundant code). + +## References + +- Project rule: `.cursor/rules/code-review.mdc` +- Testing skill: `skills/testing/SKILL.md` for test standards diff --git a/skills/contentstack-swift-cda/SKILL.md b/skills/contentstack-swift-cda/SKILL.md new file mode 100644 index 00000000..dd6c4d5a --- /dev/null +++ b/skills/contentstack-swift-cda/SKILL.md @@ -0,0 +1,51 @@ +--- +name: contentstack-swift-cda +description: Use when implementing or changing CDA features – Stack/ContentstackConfig, entries, assets, sync, taxonomy, URLSession, callbacks, and Content Delivery API alignment +--- + +# Contentstack Swift CDA SDK – CDA Implementation + +Use this skill when implementing or changing Content Delivery API (CDA) behavior in the Swift SDK. + +## When to use + +- Adding or modifying Stack, Entry, Query, Asset, Content Type, Sync, Taxonomy, or Global Field behavior. +- Changing `Contentstack.stack(...)` parameters or regional/host/branch handling. +- Working with URLSession-backed requests, response decoding, or `Result` / `ResultsHandler` error delivery. + +## Instructions + +### Stack and ContentstackConfig + +- **Entry point:** `Contentstack.stack(apiKey:deliveryToken:environment:region:host:apiVersion:branch:config:)`. Optional **`ContentstackConfig`** controls session configuration, decoding, early access, and `urlSessionDelegate`. +- **Defaults:** `Host.delivery` (`cdn.contentstack.io`), `apiVersion` default `v3`, `ContentstackRegion.us` unless overridden. +- **Reference:** `Sources/Contentstack.swift`, `Sources/Stack.swift`, `Sources/ContentstackConfig.swift`. + +### CDA resources + +- **Entries / content types:** `Stack.contentType(uid:)`, `Entry`, `Query`, models such as `EntryModel`, `ContentTypeModel`. +- **Assets:** `Stack.asset`, asset query/fetch patterns and `AssetModel`. +- **Sync:** `SyncStack` and sync endpoint usage under `Endpoint.sync`. +- **Taxonomy / global fields:** `Taxonomy`, `GlobalField`, related models and queries. +- **Official API:** Align with [Content Delivery API](https://www.contentstack.com/docs/apis/content-delivery-api/) for parameters, response shape, and semantics. + +### HTTP and session + +- **HTTP:** CDA calls go through **`Stack`**’s **`URLSession`**, built from **`ContentstackConfig.sessionConfiguration`** (with SDK headers applied). Do not duplicate ad-hoc sessions for standard CDA traffic. +- **Retry:** There is no separate retry framework like the Java SDK’s `RetryInterceptor`; if you add retries, integrate via config/session and document behavior (see **framework** skill). + +### Errors and callbacks + +- **Errors:** Use the SDK **`Error`** type and surface failures via **`Result`** and **`ResultsHandler`** (or existing async APIs). +- **Callbacks:** Preserve completion-handler signatures for public API; additive overloads (e.g. `async`) should map to the same error and response semantics. + +## Key types + +- **Entry points:** `Contentstack`, `Stack`, `ContentstackConfig` +- **CDA:** `Entry`, `Query`, `Asset`, `ContentType`, `SyncStack`, `Taxonomy`, `GlobalField`, `Endpoint` +- **Responses / errors:** `ContentstackResponse`, `Error`, `ResponseType` + +## References + +- [Content Delivery API – Contentstack Docs](https://www.contentstack.com/docs/apis/content-delivery-api/) +- Project rules: `.cursor/rules/contentstack-swift-cda.mdc`, `.cursor/rules/swift.mdc` diff --git a/skills/framework/SKILL.md b/skills/framework/SKILL.md new file mode 100644 index 00000000..0bd42935 --- /dev/null +++ b/skills/framework/SKILL.md @@ -0,0 +1,53 @@ +--- +name: framework +description: Use when touching ContentstackConfig, URLSession, CSURLSessionDelegate, headers, cache – configuration and HTTP transport layer +--- + +# Framework – Contentstack Swift CDA SDK + +Use this skill when changing configuration, URL session setup, or transport-level behavior (not CDA resource semantics). + +## When to use + +- Modifying **`ContentstackConfig`** (session configuration, decoding, early access, delegate hook). +- Changing how **`Stack`** builds **`URLSession`** or merges headers with `URLSessionConfiguration`. +- Adjusting **`CSURLSessionDelegate`**, SSL pinning, or cache usage (`URLCache`, cache policy on `Stack`). +- Introducing or changing timeouts, additional headers, or retry behavior at the session level. + +## Instructions + +### ContentstackConfig + +- Holds **`URLSessionConfiguration`** (default `.default`), optional **`dateDecodingStrategy`** and **`timeZone`**, **`earlyAccess`**, **`urlSessionDelegate`**, and helpers for user agent / SDK version strings. +- SDK code sets **`httpAdditionalHeaders`** (e.g. `User-Agent`, `X-User-Agent`, `branch`); preserve merge semantics so caller-supplied headers are not dropped unintentionally. +- **Reference:** `Sources/ContentstackConfig.swift`. + +### URLSession in Stack + +- **`Stack`** initializes **`URLSession`** with `config.sessionConfiguration` and optional **`CSURLSessionDelegate`**. +- **`URLCache.shared`** is applied to the session configuration in current code paths—understand impact before changing cache defaults. +- **Reference:** `Sources/Stack.swift`. + +### CSURLSessionDelegate + +- Used for SSL pinning and session customization; changes should remain backward compatible for adopters implementing the delegate. +- **Reference:** `Sources/CSURLSessionDelegate.swift`. + +### Retry and resilience + +- Unlike the Java SDK, retry is not centralized in an interceptor. Prefer **`URLSessionConfiguration`** (timeouts, waits for connectivity) or explicit documented retry in the SDK if adding it—coordinate with **contentstack-swift-cda** skill for API surface. + +### Error handling + +- Transport failures should still surface as SDK **`Error`** instances through existing **`Result`** / handler paths after session tasks complete. + +## Key types + +- **Config / session:** `ContentstackConfig`, `URLSessionConfiguration`, `URLSession` +- **Delegate / cache:** `CSURLSessionDelegate`, `URLCache`, `CachePolicy` (on `Stack`) +- **Errors:** `Error` (SDK), mapping from `URLError` / HTTP status as implemented in request code + +## References + +- Project rules: `.cursor/rules/contentstack-swift-cda.mdc`, `.cursor/rules/swift.mdc` +- CDA skill: `skills/contentstack-swift-cda/SKILL.md` for how Stack uses the session for CDA calls diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md new file mode 100644 index 00000000..8a98f544 --- /dev/null +++ b/skills/testing/SKILL.md @@ -0,0 +1,51 @@ +--- +name: testing +description: Use when writing or refactoring tests – XCTest, unit vs integration, fixtures, config.json, and test naming +--- + +# Testing – Contentstack Swift CDA SDK + +Use this skill when adding or refactoring tests in the Swift CDA SDK. + +## When to use + +- Writing new unit or integration/API tests. +- Refactoring test helpers, builders, or shared session/stack setup. +- Adding fixtures or updating JSON used by tests. + +## Instructions + +### XCTest and layout + +- Use **XCTest** (`import XCTest`, `XCTestCase`). +- Place tests under **`Tests/`**; the SPM target is **ContentstackTests** (see `Package.swift`). +- **Unit-style files:** Names like `*Test.swift` (e.g. `EntryTest`, `QueryTest`) for offline or focused behavior. +- **API / integration-style files:** Names like `*APITest.swift` or existing network tests (`EntryAPITest`, `SyncAPITest`, etc.). Reuse patterns from sibling files for stack initialization and expectations. + +### Asynchronous tests + +- Use **`XCTestExpectation`** and **`waitForExpectations`** for completion-handler-based APIs. +- Prefer **`XCTAssertThrowsError`** / **`try XCTUnwrap`** where appropriate; avoid unbounded waits. + +### Test data and credentials + +- **config / credentials:** Integration tests may read **`Tests/config.json`** or environment-specific setup. Never commit real tokens; document required fields for local/CI runs. +- **Fixtures:** JSON bundles (e.g. `Entry.json`, `Asset.json`) and DVR cassettes where the project uses **DVR**—keep paths and Xcode resource membership aligned when adding files. + +### Naming and structure + +- Mirror production areas: query tests near `Query*Test`, entry tests near `Entry*Test`, etc. +- Keep one primary concern per test case method; use descriptive `test*` names. + +### Execution + +- **SPM:** `swift test` from repo root. +- **Xcode:** Run the platform-specific test scheme that includes `Tests/` sources. + +Maintain or improve meaningful coverage when changing production code; add tests for new or modified CDA behavior. + +## References + +- `Package.swift` – test target definition +- `Tests/` – existing patterns (`SutBuilder`, extensions, `*APITest`) +- Project rule: `.cursor/rules/testing.mdc`