Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
33dda4a
Merge branch 'develop' into feature/217-empty-billing
mindgraffiti Aug 7, 2018
ad1f177
Make the shipping address optional. Add a check to see if an order ha…
mindgraffiti Aug 7, 2018
3274400
Handle the shipping address as optional
mindgraffiti Aug 8, 2018
6baed4f
Substitute the billing address if the shipping address doesn't exist
mindgraffiti Aug 8, 2018
4df8dde
Move function to correct class
mindgraffiti Aug 8, 2018
1052987
Display billing address if there is no shipping address
mindgraffiti Aug 8, 2018
f6c1d10
Merge branch 'develop' into feature/217-empty-shipping
mindgraffiti Aug 8, 2018
40cce24
OrderDetailsViewController: Notice Helper
jleandroperez Aug 8, 2018
0949c51
OrderDetailsViewController: Wiring EntityListener
jleandroperez Aug 8, 2018
2ed20aa
Update Address in Networking to throw an error upon parsing a field w…
mindgraffiti Aug 8, 2018
8eb36cb
Dashboard WIP: Added pager and VC stubs
bummytime Aug 8, 2018
8062dee
Adjusted pager view
bummytime Aug 9, 2018
7555f09
WIP tweaks to StoreStatsViewController
bummytime Aug 9, 2018
836cab0
Dashboard: UITweaks based on design docs
bummytime Aug 9, 2018
41327e6
Unwrap optional shipping addresses before unit testing
mindgraffiti Aug 9, 2018
c831f77
country.isEmpty is the main determinate for an empty address
mindgraffiti Aug 9, 2018
6895137
Dashboard: borders
bummytime Aug 9, 2018
ef3c1ca
Force-unwrap shipping address if it has a country property that is no…
mindgraffiti Aug 9, 2018
e6cd39c
Dashboard layout updates
bummytime Aug 9, 2018
379cdf1
Dashboard updates to period child VCs
bummytime Aug 9, 2018
9045e9f
Dashboard: StatGranularity tweaks
bummytime Aug 9, 2018
38ca742
Set billingAddress to an optional.
mindgraffiti Aug 9, 2018
653819f
Update to unwrap billingAddress in unit tests
mindgraffiti Aug 9, 2018
3bcfb6e
Fix whitespace
mindgraffiti Aug 9, 2018
82fb928
NetworkError: Updates Enum
jleandroperez Aug 9, 2018
b5179a1
MockupNetwork: Fixing NetworkError usage
jleandroperez Aug 9, 2018
534d9b0
RemoteTests: Fixing Tests
jleandroperez Aug 9, 2018
9acd68b
Remote: Removes unneeded nil coalescing OP's
jleandroperez Aug 9, 2018
f3d5e2e
Implements HTTPStatusCode
jleandroperez Aug 9, 2018
03e1f6c
AlamofireNetwork: Wrapping StatusCode 404
jleandroperez Aug 9, 2018
29a5287
MockupNetwork: Support for Simulated Errors
jleandroperez Aug 10, 2018
c06bc2d
OrderStore: Nuking Orders upon statusCode 404
jleandroperez Aug 10, 2018
d79b81b
OrderStoreTests: New Unit Test
jleandroperez Aug 10, 2018
fba7bc8
Dashboard: added WIP data fetching for basic stats
bummytime Aug 10, 2018
15a4d38
Merge branch 'develop' of github.com:woocommerce/woocommerce-ios into…
bummytime Aug 10, 2018
609825d
Updated unit tests
bummytime Aug 10, 2018
a6162af
Dashboard: updated field reloading on PeriodDataVC
bummytime Aug 10, 2018
5c0dd78
Display an alert message to confirm a user wants to log out, before l…
mindgraffiti Aug 10, 2018
b422945
Dashboard: currencySymbol fix
bummytime Aug 10, 2018
61b1eeb
Lint fix
bummytime Aug 10, 2018
a1957a2
Change the log out button to destructive style
mindgraffiti Aug 10, 2018
b98b74c
Remove title, change message phrasing to match Android, make WPBot happy
mindgraffiti Aug 10, 2018
1b195f2
Added Double.friendlyString()
bummytime Aug 10, 2018
089dfcf
Updated dashboard revenue formatting
bummytime Aug 10, 2018
41b46eb
Fixed Double+Woo extension error
bummytime Aug 10, 2018
47e3e80
Updated field reloading.
bummytime Aug 10, 2018
0a669c0
Alter the alert to conform to design iteration 6
mindgraffiti Aug 10, 2018
bac0747
Style tweaks
bummytime Aug 10, 2018
b28057b
Updated doc comment.
bummytime Aug 11, 2018
62b3ccb
Lint updates
bummytime Aug 11, 2018
9b0d514
Cleaned up code
bummytime Aug 11, 2018
8be7e17
Added constants enum to PeriodDataViewController
bummytime Aug 11, 2018
bf7db96
Updated default text color to WooSecondary
bummytime Aug 13, 2018
c499066
Merge branch 'develop' of github.com:woocommerce/woocommerce-ios into…
bummytime Aug 13, 2018
27142d8
Some quick formatting changes to Style.swift
bummytime Aug 13, 2018
c72eccd
Set the 'Log out' button to be the preferred action
mindgraffiti Aug 13, 2018
536a3f5
Code review changes - move customization to the correct function
mindgraffiti Aug 13, 2018
b847691
Added handbook constants for colors
bummytime Aug 13, 2018
694e2cb
Merge pull request #234 from woocommerce/fix/text-color
bummytime Aug 13, 2018
9ff9725
Merge branch 'develop' of github.com:woocommerce/woocommerce-ios into…
bummytime Aug 13, 2018
c4dc96d
Code review updates
bummytime Aug 13, 2018
04c0460
Merge pull request #229 from woocommerce/feature/200-logout-confirm
mindgraffiti Aug 14, 2018
af3215f
Merge branch 'develop' into feature/217-empty-shipping
mindgraffiti Aug 14, 2018
07cab08
Updated layout for PeriodDataVC
bummytime Aug 14, 2018
71227dd
Merge branch 'develop' of github.com:woocommerce/woocommerce-ios into…
bummytime Aug 14, 2018
17fae81
Style updates
bummytime Aug 14, 2018
2777667
Title and headline style updates
bummytime Aug 14, 2018
7509551
Added missing space
bummytime Aug 14, 2018
f3a91c1
Merge pull request #230 from woocommerce/feature/177-dashboard-mark5
bummytime Aug 14, 2018
9d121b2
Merge branch 'develop' of github.com:woocommerce/woocommerce-ios into…
bummytime Aug 14, 2018
9b47d08
Fixes warnings in XIB
bummytime Aug 14, 2018
7113d20
Merge pull request #225 from woocommerce/issue/224-wiring-entity-list…
bummytime Aug 14, 2018
47fd3d0
Dashboard: Removed some superfluous height constraints
bummytime Aug 14, 2018
05e3a91
Code review changes
mindgraffiti Aug 14, 2018
42e34a2
Handle a double-optionals situation
mindgraffiti Aug 14, 2018
f230fd8
Merge pull request #226 from woocommerce/feature/217-empty-shipping
mindgraffiti Aug 14, 2018
06d4838
Merge pull request #237 from woocommerce/fix/236-revenue-labels
bummytime Aug 14, 2018
c332119
Added Charts pod
bummytime Aug 14, 2018
d43e14d
Added bar chart view to PeriodDataVC
bummytime Aug 14, 2018
9c24116
Order: Simplifies parsing
jleandroperez Aug 15, 2018
dfc3d61
AlamofireNetwork: Nukes extra space
jleandroperez Aug 15, 2018
1840373
MockupNetwork: Nukes extra dot
jleandroperez Aug 15, 2018
539f2bd
SettingsViewController: Simplifies downcasting
jleandroperez Aug 15, 2018
505ab42
OrderStoreTests: Fixing Typo
jleandroperez Aug 15, 2018
a946da3
AppDelegate: Nukes unneeded self
jleandroperez Aug 15, 2018
2b19638
Dashboard: Revenue value now uses totalSales instead of totalGrossSales
bummytime Aug 15, 2018
21a6c5e
Charting WIP
bummytime Aug 15, 2018
d16ef2a
Order List: Improve custom payment labels
mindgraffiti Aug 15, 2018
cf297aa
Removed zero bars in chart
bummytime Aug 15, 2018
17eca4e
Dashboard: chart tweaks
bummytime Aug 15, 2018
24accac
WIP chart labels
bummytime Aug 15, 2018
37478fe
Merge pull request #238 from woocommerce/issue/addressing-prs-feedback
jleandroperez Aug 15, 2018
f9cd72b
Code review changes: make it swift-y
mindgraffiti Aug 16, 2018
eccd79a
Merge pull request #241 from woocommerce/fix/88-custom-payment
mindgraffiti Aug 16, 2018
d39508e
Merge branch 'develop' into issue/240-support-empty-addresses
mindgraffiti Aug 16, 2018
e863e06
`pod update`
mindgraffiti Aug 16, 2018
add0dca
Merge pull request #243 from woocommerce/issue/pod-update
mindgraffiti Aug 16, 2018
2752f5c
Support empty addresses
mindgraffiti Aug 16, 2018
f089c5f
Merge branch 'develop' into issue/240-support-empty-addresses
mindgraffiti Aug 16, 2018
7494daf
Missed a whitespace
mindgraffiti Aug 16, 2018
bf62664
Adding Architecture Document
jleandroperez Aug 16, 2018
78b7318
Architecture: Fixing typos
jleandroperez Aug 16, 2018
a82a02a
Architecture: Adds missing space
jleandroperez Aug 16, 2018
d5f10f9
Architecture: Updating Format
jleandroperez Aug 16, 2018
41cf3b9
Architecture: Updating Format II
jleandroperez Aug 16, 2018
8ca0d5b
Updating Authenticator to Mark 1.0.6
jleandroperez Aug 17, 2018
5719dce
Code review changes: `public` declaration not needed for cell variabl…
mindgraffiti Aug 17, 2018
c872e57
Merge pull request #244 from woocommerce/issue/240-support-empty-addr…
mindgraffiti Aug 17, 2018
c5e97e8
Merge pull request #246 from woocommerce/issue/updating-authenticator
jleandroperez Aug 17, 2018
2076ee3
Cleaned up YAxis on charts
bummytime Aug 18, 2018
a0fbc0f
WIP date formatting for charting
bummytime Aug 19, 2018
a31062d
Added side padding to chart
bummytime Aug 19, 2018
ae57df7
Added style to chart
bummytime Aug 19, 2018
eb77873
Chart: code cleanup
bummytime Aug 19, 2018
1a8a909
Cleaned up dates
bummytime Aug 19, 2018
76e0563
Dashboard: defaulting 'year' history to 10 previous years
bummytime Aug 19, 2018
2ddf05f
Merge branch 'develop' of github.com:woocommerce/woocommerce-ios into…
bummytime Aug 19, 2018
70bedfc
Added chart markers
bummytime Aug 19, 2018
6dc76cd
Now clears chart markers on viewDidDisappear
bummytime Aug 20, 2018
31de689
bg color update
bummytime Aug 21, 2018
6998fe8
Merge pull request #251 from woocommerce/fix/bg-colors
bummytime Aug 21, 2018
896cbfd
Code review updates
bummytime Aug 21, 2018
43a7cc5
Add core data entity methods
mindgraffiti Aug 21, 2018
7c7d36a
Expose custom core data method
mindgraffiti Aug 21, 2018
f2b9e1e
Set keyPath when init'ing resultsController
mindgraffiti Aug 21, 2018
02ab02f
Updated Chartmarker drawing logic
bummytime Aug 21, 2018
5971fc4
Merge pull request #247 from woocommerce/feature/177-dashboard-mark6
bummytime Aug 21, 2018
871c009
Change required for something a VC needs, so these changes belong in …
mindgraffiti Aug 21, 2018
0d0a964
Set the sectionNameKeyPath to "sectionIdentifier"
mindgraffiti Aug 21, 2018
6699ed2
Add a .normalizeDate() to date helpers
mindgraffiti Aug 21, 2018
f89bfe6
Move sectionIdentifier method to the CoreDataClass, because Order+Woo…
mindgraffiti Aug 21, 2018
e848bf6
Move the human-readable string function to Order+Woo. Translate compu…
mindgraffiti Aug 21, 2018
eca1c19
Merge branch 'develop' into feature/138-section-dates
mindgraffiti Aug 22, 2018
0e97586
Title label and body label table view cell for Settings
mindgraffiti Aug 23, 2018
a9bd3aa
Revert "Title label and body label table view cell for Settings"
mindgraffiti Aug 23, 2018
13f9fbc
Code review changes - move the section identifier to an extension in …
mindgraffiti Aug 23, 2018
cc3cf9f
Update enum to Swift 4 standards
mindgraffiti Aug 23, 2018
7915bf7
Restore original spacing
mindgraffiti Aug 23, 2018
975ab32
Remove duplicate code, revert enum to string
mindgraffiti Aug 23, 2018
a49ce10
Merge pull request #257 from woocommerce/feature/138-section-dates
mindgraffiti Aug 23, 2018
741c3bb
Architecture: Addressing Feedback
jleandroperez Aug 27, 2018
fac8e05
Merge pull request #245 from woocommerce/issue/documenting-architecture
jleandroperez Aug 27, 2018
34b5dd4
Updating version to Mark 0.6
jleandroperez Aug 27, 2018
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
326 changes: 326 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
# Architecture


WooCommerce iOS's architecture is the result of a **massive team effort** which involves lots of brainstorming sessions, extremely fun
coding rounds, and most of all: the sum of past experiences on the platform.

The goal of the current document is to discuss several principles that strongly influenced our current architecture approach, along with providing
details on how each one of the layers work internally.




## **Design Principles**

Throughout the entire architecture design process, we've priorized several key concepts which guided us all the way:


1. **Do NOT Reinvent the Wheel**

Our main goal is to exploit as much as possible all of the things the platform already offers through its SDK,
for obvious reasons.

The -non extensive- list of tools we've built upon include: [CoreData, NotificationCenter, KVO]


2. **Separation of concerns**

We've emphasized a clean separation of concerns at the top level, by splitting our app into four targets:

1. Storage.framework:
Wraps up all of the actual CoreData interactions, and exposes a framework-agnostic Public API.

2. Networking.framework:
In charge of providing a Swift API around the WooCommerce REST Endpoints.

3. Yosemite.framework:
Encapsulates our Business Logic: is in charge of interacting with the Storage and Networking layers.

4. WooCommerce:
Our main target, which is expected to **only** interact with the entire stack thru the Yosemite.framework.


3. **Immutability**

For a wide variety of reasons, we've opted for exposing Mutable Entities **ONLY** to our Service Layer (Yosemite.framework).
The main app's ViewControllers can gain access to [Remote, Cached] Entities only through ReadOnly instances.

(A) Thread Safe: We're shielded from known CoreData Threading nightmares
(B) A valid object will always remain valid. This is not entirely true with plain NSManagedObjects!
(C) Enforces, at the compiler level, not to break the architecture.


4. **Testability**

Every class in the entire stack (Storage / Networking / Services) has been designed with testability in mind.
This enabled us to test every single key aspect, without requiring third party tools to do so.


5. **Keeping it Simple**

Compact code is amazing. But readable code is even better. Anything and everything must be easy to understand
by everyone, including the committer, at a future time.




## **Storage.framework**

CoreData interactions are contained within the Storage framework. A set of protocols has been defined, which would, in theory, allow us to
replace CoreData with any other database. Key notes:


1. **CoreDataManager**

In charge of bootstrapping the entire CoreData stack: contains a NSPersistentContainer instance, and
is responsible for loading both the Data Model and the actual `.sqlite` file.

2. **StorageManagerType**

Defines the public API that's expected to be conformed by any actual implementation that intends to contain
and grant access to StorageType instances.

**Conformed by CoreDataManager.**

3. **StorageType**

Defines a set of framework-agnostic API's for CRUD operations over collections of Objects.
Every instance of this type is expected to be associated with a particular GCD Queue (Thread).

**Conformed by NSManagedObjectContext**

4. **Object**

Defines required methods / properties, to be implemented by Stored Objects.

**Conformed by NSManagedObject.**

5. **StorageType+Extensions**

The extension `StorageType+Extensions` defines a set of convenience methods, aimed at easing out WC specific
tasks (such as: `loadOrder(orderID:)`).




## **Networking.framework**

Our Networking framework offers a Swift API around the WooCommerce's RESTful endpoints. In this section we'll do a walkthru around several
key points.



### Model Entities

ReadOnly Model Entities live at the Networking Layer level. This effectively translates into: **none** of the Models at this level is expected to have
even a single mutable property.

Each one of the concrete structures conforms to Swift's `Decodable` protocol, which is heavily used for JSON Parsing purposes.



### Parsing Model Entities!

In order to maximize separation of concerns, parsing backend responses into Model Entities is expected to be performed (only) by means of
a concrete `Mapper` implementation:

```
protocol Mapper {
associatedtype Output
func map(response: Data) throws -> Output
}
```

Since our Model entities conform to `Decodable`, this results in small-footprint-mappers, along with clean and compact Unit Tests.



### Network Access

The networking layer is **entirely decoupled** from third party frameworks. We rely upon component injection to actually perform network requests:

1. **NetworkType**

Defines a set of API's, to be implemented by any class that offers actual Network Access.

2. **AlamofireNetwork**

Thin wrapper around the Alamofire library.

3. **MockupNetwork**

As the name implies, the Mockup Network is extensively used in Unit Tests. Allows us to simulate backend
responses without requiring third party tools. No more NSURLSession swizzling!



### Building Requests

Rather than building URL instances in multiple spots, we've opted for implementing three core tools, that, once fully initialized, are capable
of performing this task for us:

1. **DotcomRequest**

Represents a WordPress.com request. Set the proper API Version, method, path and parameters, and this structure
will generate a URLRequest for you.

2. **JetpackRequest**

Analog to DotcomRequest, this structure represents a Jetpack Endpoint request. Capable of building a ready-to-use
URLRequest for a "Jetpack Tunneled" endpoint.

3. **AuthenticatedRequest**

Injects a set of Credentials into anything that conforms to the URLConvertible protocol. Usually wraps up
a DotcomRequest (OR) JetpackRequest.



### Remote Endpoints

Related Endpoints are expected to be accessible by means of a concrete `Remote` implementation. The `Remote` base class offers few
convenience methods for enqueuing requests and parsing responses in a standard and cohesive way `(Mappers)`.

`Remote(s)` receive a Network concrete instance via its initializer. This allows us to Unit Test it's behavior, by means of the `MockupNetwork`
tool, which was designed to simulate Backend Responses.




## **Yosemite.framework**

The Yosemite framework is the keystone of our architecture. Encapsulates all of the Business Logic of our app, and interacts with both, the Networking and
Storage layers.



### Main Concepts

We've borrowed several concepts from the [WordPress FluxC library](https://github.com/wordpress-mobile/WordPress-FluxC-Android), and tailored them down
for the iOS platform (and our specific requirements):


1. **Actions**

Lightweight entities expected to contain anything required to perform a specific task.
Usually implemented by means of Swift enums, but can be literally any type that conforms to the Action protocol.

*Allowed* to have a Closure Callback to indicate Success / Failure scenarios.

**NOTE:** Success callbacks can return data, but the "preferred" mechanism is via the EntityListener or
ResultsController tools.

2. **Stores**

Stores offer sets of related API's that allow you to perform related tasks. Typically each Model Entity will have an
associated Store.

References to the `Network` and `StorageManager` instances are received at build time. This allows us to inject Mockup
Storage and Network layers, for unit testing purposes.

Differing from our Android counterpart, Yosemite.Stores are *only expected process Actions*, and do not expose
Public API's to retrieve / observe objects. The name has been kept *for historic reasons*.

3. **Dispatcher**

Binds together Actions and ActionProcessors (Stores), with key differences from FluxC:

- ActionProcessors must register themselves to handle a specific ActionType.
- Each ActionType may only have one ActionProcessor associated.
- Since each ActionType may be only handled by a single ActionProcessor, a Yosemite.Action is *allowed* to have
a Callback Closure.

4. **ResultsController**

Associated with a Stored.Entity, allows you to query the Storage layer, but grants you access to the *ReadOnly* version
of the Observed Entities.
Internally, implemented as a thin wrapper around NSFetchedResultsController.

5. **EntityListener**

Allows you to observe changes performed over DataModel Entities. Whenever the observed entity is Updated / Deleted,
callbacks will be executed.



### Main Flows

1. Performing Tasks

SomeAction >> Dispatcher >> SomeStore

A. [Main App] SomeAction is built and enqueued in the main dispatcher
B. [Yosemite] The dispatcher looks up for the processor that support SomeAction.Type, and relays the Action.
C. [Yosemite] SomeStore receives the action, and performs a task
D. [Yosemite] Upon completion, SomeStore *may* (or may not) run the Action's callback (if any).

2. Observing a Collection of Entities

ResultsController >> Observer

A. [Main App] An observer (typically a ViewController) initializes a ResultsController, and subscribes to its callbacks
B. [Yosemite] ResultsController listens to Storage Layer changes that match the target criteria (Entity / Predicate)
C. [Yosemite] Whenever there are changes, the observer gets notified
D. [Yosemite] ResultsController *grants ReadOnly Access* to the stored entities

3. Observing a Single Entity

EntityListener >> Observer

A. [Main App] An observer initializes an EntityListener instance with a specific ReadOnly Entity.
B. [Yosemite] EntityListener hooks up to the Storage Layer, and listens to changes matching it's criteria.
C. [Yosemite] Whenever an Update / Deletion OP is performed on the target entity, the Observer is notified.



### Model Entities

It's important to note that in the proposed architecture Model Entities must be defined in two spots:

A. **Storage.framework**

New entities are defined in the CoreData Model, and its code is generated thru the Model Editor.

B. **Networking.framework**

Entities are typically implemented as `structs` with readonly properties, and Decodable conformance.

In order to avoid code duplication we've taken a few shortcuts:

* All of the 'Networking Entities' are typealiased as 'Yosemite Entities', and exposed publicly (Model.swift).
This allows us to avoid the need for importing `Networking` in the main app, and also lets us avoid reimplementing, yet again,
the same entities that have been defined twice.

* Since ResultsController uses internally a FRC, the Storage.Model *TYPE* is required for its initialization.
We may revisit and fix this shortcoming in upcoming iterations.

As a workaround to prevent the need for `import Storage` statements, all of the Storage.Entities that are used in
ResultsController instances through the main app have been re-exported by means of a typealias.



### Mapping: Storage.Entity <> Yosemite.Entity

It's important to note that the Main App is only expected to interact with ReadOnly Entities (Yosemite). We rely on two main protocols to convert a Mutable Entity
into a ReadOnly instance:


* **ReadOnlyConvertible**

Protocol implemented by all of the Storage.Entities, allows us to obtain a ReadOnly Type matching the Receiver's Payload.
Additionally, this protocol defines an API to update the receiver's fields, given a ReadOnly instance (potentially a Backend
response we've received from the Networking layer)

* **ReadOnlyType**

Protocol implemented by *STRONG* Storage.Entities. Allows us to determine if a ReadOnly type represents a given Mutable instance.
Few notes that led us to this approach:

A. Why is it only supported by *Strong* stored types?: because in order to determine if A represents B, a
primaryKey is needed. Weak types might not have a pK accessible.

B. We've intentionally avoided adding a objectID field to the Yosemite.Entities, because in order to do this in a clean
way, we would have ended up defining Model structs x3 (instead of simply re-exporting the Networking ones).

C. "Weak Entities" are okay not to conform to this protocol. In turn, their parent (strong entities) can be observed.

4 changes: 4 additions & 0 deletions Networking/Networking.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
B518662420A099BF00037A38 /* AlamofireNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518662320A099BF00037A38 /* AlamofireNetwork.swift */; };
B518662A20A09C6F00037A38 /* OrdersRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518662920A09C6F00037A38 /* OrdersRemoteTests.swift */; };
B518663520A0A2E800037A38 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518663320A0A2E800037A38 /* Constants.swift */; };
B556FD69211CE2EC00B5DAE7 /* HTTPStatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = B556FD68211CE2EC00B5DAE7 /* HTTPStatusCode.swift */; };
B557D9ED209753AA005962F4 /* Networking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B557D9E3209753AA005962F4 /* Networking.framework */; };
B557D9F4209753AA005962F4 /* Networking.h in Headers */ = {isa = PBXBuildFile; fileRef = B557D9E6209753AA005962F4 /* Networking.h */; settings = {ATTRIBUTES = (Public, ); }; };
B557DA0220975500005962F4 /* JetpackRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B557D9FF209754FF005962F4 /* JetpackRequest.swift */; };
Expand Down Expand Up @@ -154,6 +155,7 @@
B518662920A09C6F00037A38 /* OrdersRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrdersRemoteTests.swift; sourceTree = "<group>"; };
B518663320A0A2E800037A38 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
B518663420A0A2E800037A38 /* Loader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Loader.swift; sourceTree = "<group>"; };
B556FD68211CE2EC00B5DAE7 /* HTTPStatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStatusCode.swift; sourceTree = "<group>"; };
B557D9E3209753AA005962F4 /* Networking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Networking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B557D9E6209753AA005962F4 /* Networking.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Networking.h; sourceTree = "<group>"; };
B557D9E7209753AA005962F4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -260,6 +262,7 @@
B518662120A097C200037A38 /* Network.swift */,
B518662320A099BF00037A38 /* AlamofireNetwork.swift */,
B518662620A09BCC00037A38 /* MockupNetwork.swift */,
B556FD68211CE2EC00B5DAE7 /* HTTPStatusCode.swift */,
);
path = Network;
sourceTree = "<group>";
Expand Down Expand Up @@ -686,6 +689,7 @@
B557DA0220975500005962F4 /* JetpackRequest.swift in Sources */,
B56C1EB820EA76F500D749F9 /* Site.swift in Sources */,
B505F6CD20BEE37E00BB1B69 /* AccountMapper.swift in Sources */,
B556FD69211CE2EC00B5DAE7 /* HTTPStatusCode.swift in Sources */,
B557DA0D20975DB1005962F4 /* WordPressAPIVersion.swift in Sources */,
74A1D26F21189EA100931DFA /* SiteVisitStatsRemote.swift in Sources */,
B557DA1D20979E7D005962F4 /* Order.swift in Sources */,
Expand Down
Loading