Skip to content

Releases: withmarfa/marfa-swift

v0.0.23

Choose a tag to compare

@github-actions github-actions released this 20 Oct 23:31

Carries MarfaCore built from withmarfa/marfa@a8497e4.

v0.0.22

Choose a tag to compare

@github-actions github-actions released this 20 Oct 09:47

Carries MarfaCore built from withmarfa/marfa@05d14a9.

v0.0.21

Choose a tag to compare

@github-actions github-actions released this 18 Oct 19:29

Carries MarfaCore built from withmarfa/marfa@c00e0cf.

v0.0.20

Choose a tag to compare

@github-actions github-actions released this 18 Oct 18:00

Carries MarfaCore built from withmarfa/marfa@0620b2f.

v0.0.19

Choose a tag to compare

@github-actions github-actions released this 18 Oct 15:43

This release carries MarfaCore built from Marfa v0.0.11 (withmarfa/marfa@e56c09f66606e09f213eb0400bd251e0590025a2). It has one change to public API, and two additions to the generated wire types.

To update, pin 0.0.19. A server at Marfa v0.0.11 or later can list an edge type that no file writes, which the earlier core could not read, so an app talking to such a server needs this release.

Public API that changed or was removed

Before Now
EdgeEnd (source, target) EdgeWrittenAt (source, target, none). none means no file writes the edge, as for in-folder.
EdgeType.writtenAt: EdgeEnd EdgeType.writtenAt: EdgeWrittenAt. The EdgeType initializer takes writtenAt: EdgeWrittenAt, still .source by default.

An app that switches over EdgeType.writtenAt needs a case for .none. An app that compares with == .source or == .target needs no change.

Public API added

  • MarfaCore.EdgeWrittenAt, the core binding's catalog type behind EdgeType.writtenAt, with the same three cases.
  • Components.Schemas.RetentionPolicy in MarfaTypes, with feedDays (a whole number of days, or null): a type definition now carries retention_policy, which says how long the server keeps the type's feed items.
  • written_at in MarfaTypes gains the value none.

Behavior that follows from the server

These come from the server and need no code change. Marfa v0.0.11 checks each element of an array property against its items_type, so a write the earlier server accepted can now be refused invalid_properties; its source filter also narrows event streams and webhook deliveries. The Marfa v0.0.11 changelog entry has the list.

v0.0.18

Choose a tag to compare

@github-actions github-actions released this 18 Oct 01:44

This release carries MarfaCore built from Marfa v0.0.10 (withmarfa/marfa@63cb85eaa25613b447360d0b8ff65e086f236165). It has three changes to what an app writes or sees: properties cross as values, each changes() stream takes its own place in the core's watch, and a new LiveQuery keeps a SwiftUI view current. Two of them change public API, as listed below.

To update, pin 0.0.18 and change the calls in the first table below.

Public API that changed or was removed

These come from #327. The core now hands properties, bodies and answers across as JSON values, not JSON text. The records that only held them are the core's own types, and Marfa re-exports each name as a typealias, so import Marfa still names them.

Before Now
Edit(.merge(x), baseVersion:) Edit(properties: x, baseVersion:)
Edit(.replace(x), baseVersion:) Edit(properties: x, replaceProperties: true, baseVersion:)
Edit.Properties Removed. Use Edit.properties (a JSONObject) and Edit.replaceProperties (a Bool, false by default).
declareTypes(_ types: [String]) declareTypes(_ types: [JSONObject]). Pass a dictionary literal, such as ["id": "app.readinglist.entry", "fields": [...]], in place of a JSON string.
declaredTypes() -> [String] declaredTypes() -> [JSONObject]
QueuedWrite.answer: String? QueuedWrite.answer: JSONValue?. Read row.answer?.object?["item"] where you parsed the text. An answer that was not JSON, such as a gateway's page, arrives as .string.
Item, Edge, SearchHit, BinPage, Draft, Edit, ListFilters, SearchFilters, Tier, ItemState as structs and enums of this package typealiases of the core's types. Initializers keep their labels, order and defaults. Their stored properties are var. Item and Edge are Identifiable.
JSONValue and JSONObject as types of this package typealiases of the core's JsonValue and JsonObject. JSONMember is new. A JSONObject holds its pairs in members: [JSONMember], and JSONObject(members:) makes one. The cases, keys, values, lookup by key, the literals, Codable, init(json:) and json() are unchanged.

New fields and behavior that follow from the same change:

  • Item.unreadableProperties and Edge.unreadableProperties (String?) are new. A row whose stored properties are not one JSON object no longer fails a whole list, search or edge read. It comes back with empty properties and unreadableProperties saying why. Check it before you write back from properties, because the empty object is not what is stored. A list or search filtered on a property leaves such a row out. A write to that item or edge throws until a hydration replaces the row from the server.
  • A value the core cannot hold is refused invalid before anything is queued. That is a number that is not finite, a key that repeats in one object, or a write nested deeper than the server reads. The server refuses a body nested more than 64 levels, so a value inside a property may nest 62 levels, and an extension's body 63 inside its own object.
  • JSONObject equality compares keys as Swift compares strings. Two keys that differ only in Unicode normalization compare equal with ==, though a lookup by key still tells them apart by their UTF-8 bytes. A lookup scans the keys in order, and building or decoding an object takes time linear in its size.
  • A float with no fraction, such as 2.0, reads back as the integer 2, as the server writes numbers.

Public API added

From #329. A LiveQuery reads rows or one item from a working copy and reads again when the copy's changes() says something that can alter the read, so a SwiftUI view stays current with no refresh code. It uses the Observation framework only; Marfa still does not import SwiftUI.

  • LiveQuery<Value: Sendable & Equatable> is a @MainActor @Observable class. Create it on the main actor with LiveQuery(copy, reading:). It has copy, reading (assigning it reads again at once), value, isLoading, error, following and refresh(). Releasing the query ends its changes() stream.
  • Reading<Value> says what to read: .list(_:sort:), .search(_:filters:limit:), .item(_:), .queue, and Reading(placeholder:_:) for any other read.
  • Following is .live, .stopped(MarfaError) or .ended(MarfaError?). .stopped means the follow of the server failed and the stream is still open. .ended means the stream finished, and refresh() asks the copy for a new one.

An app that kept its own refresh code can replace it with one LiveQuery for each read. It no longer lists, loops over changes() or reads again after a write. A query does not page: bound a result with ListFilters.limit and grow it by assigning reading.

Changes to changes() that need no code change

From #328, which hands the watch to the core. changes(), Change, hydrate, catchUp, queue.drain(), useKey(_:) and close() have the signatures they had.

  • A held stream drains once after a drain your app started left a write undelivered, the next time the server is reached, and tells .queueDrained. An app that drained again by hand after .serverReachable can stop. A drain it starts still works.
  • A follow that ends on the server's own answer after an outage, such as a revoked key, tells .serverReachable before .stopped, because the server answered. If your app treated .stopped after .serverUnreachable as "still offline", read .serverReachable first.
  • .serverReachable after a hydration, catch-up or drain can arrive after that call's own .refreshed(.hydrated) or .answered. Do not depend on the order of the two.
  • A stream the core ended on a fault, or refused a place in the watch, is told .stopped and then finishes, so a for await loop ends. Ask changes() for a new stream. A failed follow differs: the stream is told .stopped and stays open, and the next hydration or catch-up restarts it.
  • A watch failure no longer outlives the last stream. The next changes() starts a fresh follow at once and is not told the old .stopped. With a revoked key, each new stream asks the server again and is told the refusal again.
  • A stream added when none is held starts with no memory of an earlier outage. It is told .serverUnreachable only when its own follow cannot reach the server.

What Marfa v0.0.10 changes for an app

See the Marfa v0.0.10 entry in the changelog for the full list. The ones an app on this package notices:

  • A listener is told .serverUnreachable once for each loss of the server and .serverReachable once for each return. Any request that reaches the server ends an outage: the stream ending on the server's own answer, a hydration or catch-up that succeeded, or a drain that answered a write.
  • A hydration or catch-up no longer needs your listeners stopped around it. One called from inside a listener's change handler is refused invalid.
  • A drain that left a write undelivered is finished by the first stream a watch has afterward, even after the app restarts.
  • A write whose JSON body nests more than 64 levels is refused invalid when it is queued, and nothing is queued. Before, a body only a little too deep was queued and left for the server to refuse.
  • A list or search filtered on properties no longer fails as a whole because one row's stored text is not JSON. That row matches no property condition, not_exists included.
  • A link in a body written on another device keeps naming its item after that item is renamed, and after another item takes the old title.

v0.0.17

Choose a tag to compare

@github-actions github-actions released this 16 Oct 21:04

Carries MarfaCore built from withmarfa/marfa@75434a6.

v0.0.16

Choose a tag to compare

@github-actions github-actions released this 16 Oct 16:24

Carries MarfaCore built from withmarfa/marfa@f928fcb.

v0.0.15

Choose a tag to compare

@github-actions github-actions released this 15 Oct 09:22

Carries MarfaCore built from withmarfa/marfa@6f28298.

v0.0.14

Choose a tag to compare

@github-actions github-actions released this 13 Oct 11:39

Carries MarfaCore built from withmarfa/marfa@d162acd.