@onlyworlds/sdk 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,7 +5,25 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
- ## [4.4.0] — 2026-10-04 (staged, not published)
8
+ ## [4.5.0] — 2026-10-04 (staged, not published)
9
+
10
+ What the staging write probes found on the wire (Python package, 2026-10-04): one new getter, and
11
+ three behaviours the server has always had that no client doc said. Additive; nothing is removed.
12
+
13
+ ### Added
14
+ - **`OwApiError.isOwnerOnly`**: 403 `owner_only`, a contributor attempting a world-level change
15
+ (`patchWorld`, publishing a show page). Owners and co-builders never see it. keel's OpenAPI
16
+ document does not name the code yet (Skeld has that to close); the wire returns it.
17
+
18
+ ### Documented
19
+ - **An atomic `/bulk` rollback still returns 201 slots** for the items that would have
20
+ succeeded, with the ids and timestamps they would have had (keel spec: "counterfactual 201s").
21
+ After `atomic: true` with `errors: true`, nothing was written. On `bulk()`, `OwBulkItemResult`
22
+ and the README.
23
+ - **`name` is required as a key only**: `''` and `null` are accepted and stored as `''` (keel
24
+ ruling 2026-09-28, spec §6; nameless Markers exist). On `create()` and the README.
25
+
26
+ ## [4.4.0] — 2026-10-04
9
27
 
10
28
  Membership, as far as the server has shipped it: who created an element, and the refusal a
11
29
  contributor meets on someone else's. Additive; nothing is removed or narrows.
package/README.md CHANGED
@@ -45,6 +45,8 @@ const location = await writer.create('location', {
45
45
  name: 'Dragon Peak',
46
46
  description: 'A treacherous mountain peak where dragons nest',
47
47
  }); // id minted client-side when omitted (retries stay idempotent)
48
+ // name is the one required field, and required means the key is present:
49
+ // '' and null are accepted and stored as '' (nameless Markers exist).
48
50
 
49
51
  const dragon = await writer.create('creature', {
50
52
  name: 'Vorrath the Ember-Scaled',
@@ -84,6 +86,8 @@ if (res.errors) {
84
86
  }
85
87
  }
86
88
  // Pass { atomic: true } for all-or-nothing instead. res.wasReplay flags idempotent replays.
89
+ // After a failed atomic batch NOTHING was written, but the slots that would have succeeded
90
+ // still say 201 (keel's counterfactual 201s): do not record those ids as created.
87
91
  ```
88
92
 
89
93
  ## Sync
package/dist/index.d.ts CHANGED
@@ -1912,6 +1912,9 @@ interface OwBulkItem {
1912
1912
  * created_at/updated_at, error slots carry an OwErrorBody under `error`.
1913
1913
  * A contributor's write on someone else's element fails in its slot as
1914
1914
  * `{status: 403, error: {code: 'not_author'}}` (keel D72), never as a thrown error.
1915
+ * After an `atomic: true` request with `errors` true NOTHING was written, yet the slots of
1916
+ * the items that would have succeeded still say 201 (keel's "counterfactual 201s"): do not
1917
+ * record their ids as created.
1915
1918
  */
1916
1919
  interface OwBulkItemResult {
1917
1920
  status: number;
@@ -2043,6 +2046,12 @@ declare class OwApiError extends Error {
2043
2046
  * slot `{status: 403, error: {code: 'not_author'}}`. Owners and co-builders never see it.
2044
2047
  */
2045
2048
  get isNotAuthor(): boolean;
2049
+ /**
2050
+ * A contributor tried a world-level change: `patchWorld`, or publishing a show page
2051
+ * (403 `owner_only`, keel D72 membership phase 2). Retrying will not help; only the
2052
+ * owner may. Owners and co-builders never see it.
2053
+ */
2054
+ get isOwnerOnly(): boolean;
2046
2055
  }
2047
2056
  /** Network-level failure (fetch rejected) -- no envelope to parse. */
2048
2057
  declare class OwNetworkError extends Error {
@@ -2126,6 +2135,8 @@ declare class OwV2Client {
2126
2135
  * POST /{type}/ -- create. Mints an RFC 9562 UUIDv7 for element.id when the
2127
2136
  * caller omits one (design ruling D29d) so a retry carrying the same
2128
2137
  * Idempotency-Key is structurally safe. Callers MAY still supply their own id.
2138
+ * `name` is the one required field, and required means the key is present: `''` and
2139
+ * `null` are accepted and stored as `''` (nameless Markers exist; keel ruling 2026-09-28).
2129
2140
  */
2130
2141
  create(type: ElementType | string, element: OwElement | Record<string, unknown>, opts?: {
2131
2142
  idempotencyKey?: string;
@@ -2159,6 +2170,9 @@ declare class OwV2Client {
2159
2170
  * Success slots echo server-authoritative timestamps: set your sync baseline
2160
2171
  * from this response alone. When an idempotencyKey is replayed, the returned
2161
2172
  * response carries wasReplay:true (read from the Idempotent-Replay header).
2173
+ * After an atomic:true request with errors:true NOTHING was written, yet the slots of
2174
+ * the items that would have succeeded still say 201 with the ids and timestamps they
2175
+ * would have had (keel's "counterfactual 201s"): do not record those ids as created.
2162
2176
  */
2163
2177
  bulk(items: OwBulkItem[], opts?: {
2164
2178
  atomic?: boolean;
package/dist/index.js CHANGED
@@ -48,6 +48,14 @@ var OwApiError = class extends Error {
48
48
  get isNotAuthor() {
49
49
  return this.status === 403 && this.code === "not_author";
50
50
  }
51
+ /**
52
+ * A contributor tried a world-level change: `patchWorld`, or publishing a show page
53
+ * (403 `owner_only`, keel D72 membership phase 2). Retrying will not help; only the
54
+ * owner may. Owners and co-builders never see it.
55
+ */
56
+ get isOwnerOnly() {
57
+ return this.status === 403 && this.code === "owner_only";
58
+ }
51
59
  };
52
60
  var OwNetworkError = class extends Error {
53
61
  constructor(message, cause) {
@@ -182,6 +190,8 @@ var OwV2Client = class {
182
190
  * POST /{type}/ -- create. Mints an RFC 9562 UUIDv7 for element.id when the
183
191
  * caller omits one (design ruling D29d) so a retry carrying the same
184
192
  * Idempotency-Key is structurally safe. Callers MAY still supply their own id.
193
+ * `name` is the one required field, and required means the key is present: `''` and
194
+ * `null` are accepted and stored as `''` (nameless Markers exist; keel ruling 2026-09-28).
185
195
  */
186
196
  async create(type, element, opts = {}) {
187
197
  const body = sanitizePayload(element);
@@ -231,6 +241,9 @@ var OwV2Client = class {
231
241
  * Success slots echo server-authoritative timestamps: set your sync baseline
232
242
  * from this response alone. When an idempotencyKey is replayed, the returned
233
243
  * response carries wasReplay:true (read from the Idempotent-Replay header).
244
+ * After an atomic:true request with errors:true NOTHING was written, yet the slots of
245
+ * the items that would have succeeded still say 201 with the ids and timestamps they
246
+ * would have had (keel's "counterfactual 201s"): do not record those ids as created.
234
247
  */
235
248
  async bulk(items, opts = {}) {
236
249
  const body = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {