{"id":32146533,"url":"https://github.com/mhayes853/swift-operation","last_synced_at":"2026-07-18T14:35:33.412Z","repository":{"id":293951187,"uuid":"936463123","full_name":"mhayes853/swift-operation","owner":"mhayes853","description":"Flexible asynchronous operation and state management for SwiftUI, Linux, WASM, and more.","archived":false,"fork":false,"pushed_at":"2026-05-03T05:41:15.000Z","size":4094,"stargazers_count":11,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-06-03T14:24:05.122Z","etag":null,"topics":["async","cache","fetch","operation","query","stale-while-revalidate","state-management","swift","update"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mhayes853.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-02-21T06:06:16.000Z","updated_at":"2026-05-13T11:32:16.000Z","dependencies_parsed_at":"2025-06-26T21:34:36.972Z","dependency_job_id":"2994a7cb-dc3a-4f50-bbb8-f88b1f7f59d5","html_url":"https://github.com/mhayes853/swift-operation","commit_stats":null,"previous_names":["mhayes853/swift-query","mhayes853/swift-operation"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/mhayes853/swift-operation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhayes853%2Fswift-operation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhayes853%2Fswift-operation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhayes853%2Fswift-operation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhayes853%2Fswift-operation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mhayes853","download_url":"https://codeload.github.com/mhayes853/swift-operation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhayes853%2Fswift-operation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35621145,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-18T02:00:07.223Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","cache","fetch","operation","query","stale-while-revalidate","state-management","swift","update"],"created_at":"2025-10-21T08:11:25.449Z","updated_at":"2026-07-18T14:35:33.407Z","avatar_url":"https://github.com/mhayes853.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swift Operation\n[![CI](https://github.com/mhayes853/swift-operation/actions/workflows/ci.yml/badge.svg)](https://github.com/mhayes853/swift-operation/actions/workflows/ci.yml)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmhayes853%2Fswift-operation%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/mhayes853/swift-operation)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmhayes853%2Fswift-operation%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/mhayes853/swift-operation)\n\nFlexible asynchronous operation and state management for SwiftUI, Linux, WASM, and more.\n\n## Motivation\nDealing with asynchronous work that interacts with external or remote resources is inherently flakey, yet most software needs to do it. Dealing with this flakiness in your application poses a number of challenges including: Tracking loading states, tracking error states, performing retries, exponential backoff, deduplicating operations, pagination, keeping state in sync across different screens, and much more.\n\nSwift Operation is a library that takes care of much of that complexity for you, and additionally allows you to configure that complexity on a per-operation basis.\n\n## Overview\n\n### Package Structure\nThis package ships a few different targets:\n- `Operation`: The core library bundled with macros and platform-specific defaults.\n- `OperationCore`: The core library that provides the basic building blocks for operations.\n- `OperationWebBrowser`: Web browser default implementations for protocols in `OperationCore`.\n- `SharingOperation`: A [swift-sharing](https://github.com/pointfreeco/swift-sharing) wrapper built on top of `Operation` that provides the `@SharedOperation` property wrapper.\n\n### Queries\nFirst, we need to define a data type to operate on, and we’ll create an operation to fetch that data. We can create an operation that performs a simple data fetch by using the `@QueryRequest` macro.\n```swift\nimport Foundation\nimport Operation\n\nstruct Post: Hashable, Identifiable, Sendable, Codable {\n  let id: Int\n  var userId: Int\n  var title: String\n  var body: String\n}\n\nextension Post {\n  static func query(for id: Int) -\u003e some QueryRequest\u003cPost?, any Error\u003e {\n    // The modifiers on the query are applied by default, they are\n    // only being shown to demonstrate how to configure operations.\n    Self.$query(for: id)\n      .retry(limit: 3)\n      .deduplicated()\n      .rerunOnChange(of: .connected(to: NWPathMonitorObserver.startingShared()))\n  }\n\n  @QueryRequest\n  private static func query(for id: Int) async throws -\u003e Post? {\n    let url = URL(string: \"https://dummyjson.com/posts/\\(id)\")!\n    let (data, resp) = try await URLSession.shared.data(from: url)\n    if (resp as? HTTPURLResponse)?.statusCode == 404 {\n      return nil\n    }\n    return try JSONDecoder().decode(Post.self, from: data)\n  }\n}\n```\n\nNow, we can track the state of the operation in a SwiftUI view using the `@SharedOperation` property wrapper.\n```swift\nimport SharingOperation\nimport SwiftUI\n\nstruct PostView: View {\n  @SharedOperation\u003cQueryState\u003cPost?, any Error\u003e\u003e var post: Post??\n\n  init(id: Int) {\n    // By default, this will begin fetching the post.\n    self._post = SharedOperation(Post.query(for: id))\n  }\n\n  var body: some View {\n    Group {\n      VStack {\n        switch self.$post.status {\n        case .result(.success(let post)):\n          if let post {\n            PostDetailView(post: post)\n          } else {\n            Text(\"Post Not Found\")\n          }\n        case .result(.failure(let error)):\n          Text(\"Error: \\(error.localizedDescription).\")\n        case .loading:\n          ProgressView()\n        default:\n          EmptyView()\n        }\n        Button(\"Reload\") {\n          Task { try await self.$post.fetch() }\n        }\n      }\n    }\n    .frame(maxWidth: .infinity, alignment: .leading)\n  }\n}\n```\n\u003e [!NOTE]\n\u003e The `@SharedOperation` property wrapper and `SharingOperation` target are built on top of the `@Shared` property wrapper from [Sharing](https://github.com/pointfreeco/swift-sharing), the same library that powers the property wrappers found in [SQLiteData](https://github.com/pointfreeco/sqlite-data). This means that you can also use it outside of SwiftUI views such as in `@Observable` models.\n\n### Mutations\nMutations are best suited for operations that create, delete, or update data on remote or external sources they use. A good example of this would be HTTP non-GET requests such as POST, PATCH, PUT, DELETE, etc.\n\nWe can create a mutation that creates a post by using the `@MutationRequest` macro. A single mutation is designed to work with multiple sets of arguments, which requires us to specify the contents of the post as the mutation’s `Arguments` type.\n```swift\nextension Post {\n  struct CreateArguments: Codable, Sendable {\n    let userId: Int\n    let title: String\n    let body: String\n  }\n\n  @MutationRequest\n  static func createMutation(arguments: CreateArguments) async throws -\u003e Post {\n    let url = URL(string: \"https://dummyjson.com/posts/add\")!\n    var request = URLRequest(url: url)\n    request.httpMethod = \"POST\"\n    request.httpBody = try JSONEncoder().encode(arguments)\n    request.addValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    let (data, _) = try await URLSession.shared.data(for: request)\n    return try JSONDecoder().decode(Post.self, from: data)\n  }\n}\n```\n\nNow let’s consume the mutation in a SwiftUI view, which allso utilizes the `@SharedOperation` property wrapper to observe the state of the mutation.\n```swift\nimport SwiftUI\nimport SharingOperation\n\nstruct CreatePostView: View {\n  @Environment(\\.dismiss) private var dismiss\n  let userId: Int\n  @State private var title = \"\"\n  @State private var postBody = \"\"\n  @SharedOperation(Post.$createMutation) private var create\n\n  var body: some View {\n    Form {\n      TextField(\"Title\", text: self.$title)\n      TextField(\"Body\", text: self.$postBody)\n\n      Button(self.$create.isLoading ? \"Creating...\" : \"Create\") {\n        Task {\n          let args = Post.CreateArguments(\n            userId: self.userId,\n            title: self.title,\n            body: self.postBody\n          )\n          try await self.$create.mutate(with: args)\n          self.dismiss()\n        }\n      }\n      .disabled(self.$create.isLoading)\n\n      if let error = self.$create.error {\n        Text(\"Error: \\(error.localizedDescription)\")\n      }\n    }\n    .navigationTitle(\"Create Post\")\n  }\n}\n```\n\nThe key difference between queries and mutations is that a single mutation instance can operate on multiple set or arguments, whereas a single query instance can only operate on the set of members it was constructed with. The `@SharedOperation` property wrapper, as well as the `OperationClient` will utilize this difference as we’ll see later.\n\n### Pagination\nPaginated operations can be implemented through the `PaginatedRequest` protocol. This time, we'll' create a struct that describes how to fetch a single page of data. In order to know what page needs to be fetched, there’s also a functional requirement that requires us to provide next `PageID` in the list of pages.\n\nLet’s create a paginated operation that provides pages for a feed of posts.\n```swift\nextension Post {\n  struct FeedPage: Codable, Sendable {\n    let posts: [Post]\n    let total: Int\n    let skip: Int\n  }\n}\n\nextension Post {\n  static let feedQuery = FeedQuery()\n\n  struct FeedQuery: PaginatedRequest, Hashable, Sendable {\n    private static let limit = 10\n\n    let initialPageId = 0\n\n    func pageId(\n      after page: Page\u003cInt, FeedPage\u003e,\n      using paging: Paging\u003cInt, FeedPage\u003e,\n      in context: OperationContext\n    ) -\u003e Int? {\n      // Nil means there's no more pages to fetch.\n      page.value.skip \u003c page.value.total ? page.id + 1 : nil\n    }\n\n    func fetchPage(\n      isolation: isolated (any Actor)?,\n      using paging: Paging\u003cInt, FeedPage\u003e,\n      in context: OperationContext,\n      with continuation: OperationContinuation\u003cFeedPage, any Error\u003e\n    ) async throws -\u003e FeedPage {\n      var url = URL(string: \"https://dummyjson.com/posts\")!\n      url.append(\n        queryItems: [\n          URLQueryItem(name: \"limit\", value: \"\\(Self.limit)\"),\n          URLQueryItem(\n            name: \"skip\",\n            value: \"\\(paging.pageId * Self.limit)\"\n          )\n        ]\n      )\n      let (data, _) = try await URLSession.shared.data(from: url)\n      return try JSONDecoder().decode(FeedPage.self, from: data)\n    }\n  }\n}\n```\n\nNow let’s once again use the `@SharedOperation` property wrapper to created a paginated feed SwiftUI view.\n```swift\nstruct PostsFeedView: View {\n  @SharedOperation(Post.feedQuery) private var feed\n\n  var body: some View {\n    ScrollView {\n      LazyVStack(spacing: 10) {\n        ForEach(self.feed) { page in\n          ForEach(page.value.posts) { post in\n            PostDetailView(post: post)\n              .frame(maxWidth: .infinity, alignment: .leading)\n          }\n        }\n        if let error = self.$feed.error {\n          Text(\"Error: \\(error.localizedDescription)\")\n        }\n        Button(self.$feed.isLoading ? \"Loading...\" : \"Load More\") {\n          Task { try await self.$feed.fetchNextPage() }\n        }\n      }\n    }\n  }\n}\n```\n\n### Modifiers\nOperations can be customized declaratively by using the `OperationModifier` protocol. The library uses this protocol to add default behaviors to your operations such as retries and deduplication.\n\nWe can conform to the protocol create a modifier that adds artificial delay to an operation. Such a modifier could be useful for SwiftUI previews where you may want to apply such a delay to simulate a long loading state.\n```swift\nimport Operation\n\nextension OperationRequest {\n  func delay(for duration: OperationDuration) -\u003e ModifiedOperation\u003cSelf, DelayModifer\u003cSelf\u003e\u003e {\n    self.modifier(DelayModifer(duration: duration))\n  }\n}\n\nstruct DelayModifer\u003cOperation: OperationRequest\u003e: OperationModifier, Sendable {\n  let duration: OperationDuration\n\n  func run(\n    isolation: isolated (any Actor)?,\n    in context: OperationContext,\n    using operation: Operation,\n    with continuation: OperationContinuation\u003cOperation.Value, Operation.Failure\u003e\n  ) async throws(Operation.Failure) -\u003e Operation.Value {\n    try? await context.operationDelayer.delay(for: self.duration)\n    return try await operation.run(isolation: isolation, in: context, with: continuation)\n  }\n}\n\n@QueryRequest\nfunc someQuery() {\n  // ...\n}\n\n@MutationRequest\nfunc someMutation() {\n  // ...\n}\n\nlet delayedQuery = $someQuery.delay(for: .seconds(1))\nlet delayedMutation = $someMutation.delay(for: .seconds(1))\n```\n\nThe modifier works regardless of the operation type because all operation types inherit from the `OperationRequest` protocol, which itself can apply modifiers.\n\n### Multiple Data Updates\nYou can use the `OperationContinuation` instance passed to your operation to yield multiple data updates before returning. For example, you may want to temporarily yield cached data from disk while fetching the real live data from your server.\n```swift\nextension Post {\n  @QueryRequest\n  static func cachedQuery(\n    id: Int,\n    continuation: OperationContinuation\u003cPost?, any Error\u003e\n  ) async throws -\u003e Post? {\n    async let post = Self.fetchPost(for: id)\n    if let cached = try PostCache.shared.post(for: id) {\n      continuation.yield(cached)\n    }\n    return try await post\n  }\n\n  // ...\n}\n```\n\u003e [!NOTE]\n\u003e To learn more about multiple data updates, checkout [MultistageOperations](https://swiftpackageindex.com/mhayes853/swift-operation/main/documentation/operationcore/multistageoperations). Additionally, you can also find usage examples such as [file downloads](https://github.com/mhayes853/swift-operation/blob/main/Examples/CaseStudies/CaseStudies/02-Downloads.swift) and [FoundationModels streaming](https://github.com/mhayes853/swift-operation/blob/main/Examples/CanIClimb/CanIClimbKit/Sources/CanIClimbKit/MountainsCore/ClimbReadiness/Mountain%2BClimbReadinessGeneration.swift) in the demos.\n\n### Sharing State\nUsing different instances of the `@SharedOperation` property wrapper with the same operation will efficiently share the state of the operation across both usages. In the following example, both `ParentView` and `ChildView` will observe state from the fetch of the post, that is the post will only be fetched a single time despite 2 instances of the property wrapper being in-memory.\n```swift\nimport SharingOperation\nimport SwiftUI\n\n// ParentView and ChildView observe the same post operation.\n// Therefore the post is only fetched a single time.\n\nstruct ParentView: View {\n  @SharedOperation(Post.query(for: 10)) private var post\n\n  var body: some View {\n    ChildView()\n  }\n}\n\nstruct ChildView: View {\n  @SharedOperation(Post.query(for: 10)) private var post\n\n  var body: some View {\n    // ...\n  }\n}\n```\n\nThe reason this works is because `@SharedOperation` uses the same `OperationStore` instance under the hood for both instances in `ParentView` and `ChildView`.\n\n`OperationStore` is the runtime of an operation, and invokes your operation whilst managing its state directly. It has a `OperationStore.subscribe` method that `@SharedOperation` wraps such that you can observe the state in SwiftUI views and more.\n\n`@SharedOperation` is able to use the same store instance under the hood due to the `OperationClient` class. `OperationClient` is a class that manages all `OperationStore` instances in your application. You can access the client through the `@Dependency(\\.defaultOperationClient)` property wrapper from [swift-dependencies](https://github.com/pointfreeco/swift-dependencies/tree/main).\n```swift\nimport SharingOperation\n\n@MutationRequest\nfunc sendFriendRequestMutation(\n  arguments: SendFriendRequestArguments\n) async throws {\n  @Dependency(\\.defaultOperationClient) var client\n  try await sendFriendRequest(userId: arguments.userId)\n\n  // Friend request succeeded, now optimistically update the state\n  // of all friends list queries in the app.\n  let stores = client.stores(\n    matching: [\"user-friends\"],\n    of: PaginatedState\u003c[User], Int\u003e.self\n  )\n  for store in stores {\n    store.withExclusiveAccess { store in\n      store.currentValue = store.currentValue.updateRelationship(\n        for: arguments.userId,\n        to: .friendRequestSent\n      )\n    }\n  }\n}\n```\n\u003e [!NOTE]\n\u003e To learn more about advanced state management practices including pattern matching using the `OperationPath` type, similar to [Tanstack Query’s query key](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) pattern matching, checkout [PatternMatchingAndStateManagement](https://swiftpackageindex.com/mhayes853/swift-operation/main/documentation/operationcore/patternmatchingandstatemanagement).\n\n### Stateless Operations\n\nIf your operation does not need managed state, use `@OperationRequest` and run it directly with `#run`.\n\n```swift\nimport Operation\n\n@OperationRequest\nfunc myOperation(\n  context: OperationContext,\n  continuation: OperationContinuation\u003cInt, any Error\u003e\n) async throws -\u003e Int {\n  continuation.yield(someValue())\n  return someOtherValue()\n}\n\nlet value = try await #run($myOperation)\n\nvar context = OperationContext()\nlet previewValue = try await #run($myOperation, context: context)\n\nlet continuation = OperationContinuation\u003cInt, any Error\u003e { result, context in\n  // Handle intermittent results.\n}\nlet streamedValue = try await #run(\n  $myOperation,\n  context: context,\n  continuation: continuation\n)\n```\n\nQueries, mutations, and paginated operations generally run through `OperationStore` because they manage state.\n\n## Traits\nThe library ships with a handful of package traits, which allow you to conditionally compile dependencies and features of the library. You can learn more about package traits from reading the official evolution [proposal](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0450-swiftpm-package-traits.md).\n- `SwiftOperationLogging` - Adds swift-log support to the library, including a `Logger` context property and the `logDuration` modifier.\n- `SwiftOperationWebBrowser` - Integrates web browser APIs with the library using JavaScriptKit. (Only enable for WASM Browser Applications).\n- `SwiftOperationNavigation` - Integrates SwiftNavigation's `UITransaction` with `@SharedOperation`.\n- `SwiftOperationUIKitNavigation` - Integrates UIKitNavigation's `UIKitAnimation` with `@SharedOperation`.\n- `SwiftOperationAppKitNavigation` - Integrates AppKitNavigation's `AppKitAnimation` with `@SharedOperation`.\n\n## Documentation\nThe documentation for releases and main are available here.\n* [main](https://swiftpackageindex.com/mhayes853/swift-operation/main/documentation/operationcore/)\n* [0.x.x](https://swiftpackageindex.com/mhayes853/swift-operation/~/documentation/operationcore/)\n\n#### SharingOperation\n* [main](https://swiftpackageindex.com/mhayes853/swift-operation/main/documentation/sharingoperation/)\n* [0.x.x](https://swiftpackageindex.com/mhayes853/swift-operation/~/documentation/sharingoperation/)\n\n## Demos\nThere are multiple demos available in the repo to see the library in action across a variety of different scenarios and platforms.\n- [**CanIClimb**](https://github.com/mhayes853/swift-operation/tree/main/Examples/CanIClimb)\n  - A moderately complex application that integrates with an HTTP API to determine whether or not you are able to climb a mountain of your choice. It implements offline support, authentication, robust testing, FoundationModels, and more.\n- [**WASM Demo**](https://github.com/mhayes853/swift-operation/tree/main/Examples/WASMDemo)\n  - A simple app that shows how to use the library in browser applications with WASM and JavaScriptKit.\n- [**Case Studies**](https://github.com/mhayes853/swift-operation/tree/main/Examples/CaseStudies/CaseStudies)\n  - An app showcasing numerous common scenarios, and how to adapt the library in those scenarios. It starts from the basics of the library, and progresses to showcase advanced concepts like custom run specifications, completely offline operations, debouncing, downloads, and much more.\n- [**Posts**](https://github.com/mhayes853/swift-operation/tree/main/Examples/Posts)\n  - Demos from this README.\n\n## Inspirations and Directions\nThis library was heavily inspired by [Tanstack Query](https://tanstack.com/query/latest/docs/framework/react/examples/basic) from the JavaScript ecosystem, as well as [SQLiteData](https://github.com/pointfreeco/sqlite-data), and [Effect](https://effect.website/) (a TypeScript library).\n\nThe original aim of the library was just to bring a powerful asynchronous state manager like Tanstack Query and SQLiteData over to Swift for general async operations. However, the possibilities of the library can be expanded to make writing and building around asynchronous operations as a whole a lot easier in the same way Effect is doing over in TypeScript. This second point is more pronounced through stateless operations that use the `OperationRequest` protocol directly.\n\nAsynchronous state management around operations is a subset of asynchronous operation management. While state management generally means tracking loading, error, and success states, operation management refers to adding behaviors to operations such as retries and deduplication from small and composable parts. The library aims to move further in this direction over time.\n\n## Installation\nYou can add Swift Operation to an Xcode project by adding it to your project as a package. Make sure to add the `SharingOperation` target to your package to get access to the `@SharedOperation` property wrapper.\n\u003e https://github.com/mhayes853/swift-operation\n\n\u003e [!NOTE] \n\u003e Xcode 26.4 is required for using traits directly in Xcode projects.\n\nIf you want to use Swift Operation in a [SwiftPM](https://swift.org/package-manager/) project, it's as simple as adding it to your `Package.swift`.\n``` swift\ndependencies: [\n  .package(\n    url: \"https://github.com/mhayes853/swift-operation\",\n    from: \"0.5.0\",\n    // To enable any traits.\n    traits: [\"SwiftOperationLogging\"]\n  ),\n]\n```\n\nAnd then adding the product to any target that needs access to the library.\n```swift\n.product(name: \"Operation\", package: \"swift-operation\"),\n\n// For the @SharedOperation property wrapper.\n.product(name: \"SharingOperation\", package: \"swift-operation\"),\n```\n\n## License\nThis library is licensed under an MIT License. See [LICENSE](https://github.com/mhayes853/swift-operation/blob/main/LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhayes853%2Fswift-operation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmhayes853%2Fswift-operation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhayes853%2Fswift-operation/lists"}