@onlyworlds/sdk 4.50.0 → 4.52.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,6 +5,18 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.52.0] - 2026-10-22
9
+
10
+ ### Changed
11
+
12
+ - **Every options object refuses an unknown key** the way `list()` did in 4.51.0: `draught`, `get`, `create`, `bulk`, `changes`, `changesAll`, `removeImage`, `redeemJoin`, `signInWithPassword`, `mintWorldKey`, `signInWithOnlyWorlds`, `completeSignIn`, `ask` and `sort` throw a TypeError naming the key and the known keys before anything is sent. A dropped key was never harmless: `atomc: true` ran a batch non-atomically, `idempotency_key` let a retry create twice, `afetr` read the whole feed, `mode` misspelt widened a draught to the caller's view. TypeScript callers were already refused at compile time; this is for plain JavaScript.
13
+
14
+ ## [4.51.0] - 2026-10-22
15
+
16
+ ### Changed
17
+
18
+ - **`list()` and `listAll()` refuse an unknown top-level key** with a TypeError before anything is sent, naming the key and where a wire filter goes (`filter: { name__icontains: ... }`). Until now an unknown key was dropped without a word, so a plain-JavaScript caller who wrote `list('character', { name__icontains: 'probe' })` got every Character, unfiltered, and TypeScript's compile-time check was the only fence. A cleanup script written that way deleted 99 Characters on a test world on 2026-10-22; this is the SDK's half of the lesson. A caller who passed a stray key by accident now hears about it; the known keys are `limit`, `cursor`, `ids`, `createdBy`, `expand`, `fields`, `filter`, `viewAs`.
19
+
8
20
  ## [4.50.0] - 2026-10-22
9
21
 
10
22
  ### Added
package/dist/index.d.ts CHANGED
@@ -2726,6 +2726,11 @@ interface OwFileDownload {
2726
2726
  kind: OwFileKind;
2727
2727
  size: number;
2728
2728
  }
2729
+ /**
2730
+ * The parameters of `list()` and `listAll()`. A wire filter goes under `filter`; any key not named
2731
+ * here is a TypeError before anything is sent (since 4.51.0; before, an unknown key was dropped and the
2732
+ * list came back whole).
2733
+ */
2729
2734
  interface ListParams {
2730
2735
  limit?: number;
2731
2736
  cursor?: string;
@@ -3159,8 +3164,9 @@ declare class OwV2Client {
3159
3164
  * PUT /me/character -- pick the roster Character that is you in this world, or none (keel PR 160,
3160
3165
  * #533). A person member's write key with its PIN; answers GET /me's body. 422 for a hidden
3161
3166
  * Character (`character_hidden`, `err.isCharacterHidden`), a guest's pick it did not make, or a
3162
- * taken Character (`character_taken`); 404 for one this key cannot see; 403 for an agent seat, a
3163
- * player, the owner (who sets it on the world page) or a read key. A guest's view resets once.
3167
+ * taken Character (`invalid_request`, `param` character); 404 for one this key cannot see; 403 for
3168
+ * an agent seat, a player, the owner (whose own is the world's `owner_character`, set with
3169
+ * patchWorld) or a read key. A guest's view resets once.
3164
3170
  */
3165
3171
  setMyCharacter(character: string | null): Promise<OwMe>;
3166
3172
  me(): Promise<OwMe>;
package/dist/index.js CHANGED
@@ -544,8 +544,9 @@ var OwV2Client = class {
544
544
  * PUT /me/character -- pick the roster Character that is you in this world, or none (keel PR 160,
545
545
  * #533). A person member's write key with its PIN; answers GET /me's body. 422 for a hidden
546
546
  * Character (`character_hidden`, `err.isCharacterHidden`), a guest's pick it did not make, or a
547
- * taken Character (`character_taken`); 404 for one this key cannot see; 403 for an agent seat, a
548
- * player, the owner (who sets it on the world page) or a read key. A guest's view resets once.
547
+ * taken Character (`invalid_request`, `param` character); 404 for one this key cannot see; 403 for
548
+ * an agent seat, a player, the owner (whose own is the world's `owner_character`, set with
549
+ * patchWorld) or a read key. A guest's view resets once.
549
550
  */
550
551
  async setMyCharacter(character) {
551
552
  if (this.keyKind === "account") {
@@ -574,6 +575,7 @@ var OwV2Client = class {
574
575
  // -- Element CRUD --------------------------------------------------------
575
576
  /** GET /{type}/ -- one cursor page. */
576
577
  async list(type, params = {}) {
578
+ only("list", params, LIST_PARAM_KEYS, "A wire filter (name, name__icontains, supertype, subtype, characters) goes under filter: { ... }.");
577
579
  const query = buildQuery({
578
580
  limit: params.limit ?? this.pageSize,
579
581
  cursor: params.cursor,
@@ -598,6 +600,7 @@ var OwV2Client = class {
598
600
  * empty means the serving is partial. Served `Cache-Control: private, no-store`.
599
601
  */
600
602
  async draught(characterId, policy = {}) {
603
+ only("draught", policy, ["components", "mode", "asOf", "undated", "since", "budget", "depth"]);
601
604
  const query = buildQuery({
602
605
  components: policy.components?.join(","),
603
606
  mode: policy.mode,
@@ -623,6 +626,7 @@ var OwV2Client = class {
623
626
  * #421: the owner reads as another reader; see ListParams.viewAs).
624
627
  */
625
628
  async get(type, id, opts = {}) {
629
+ only("get", opts, ["expand", "fields", "viewAs"]);
626
630
  const query = buildQuery({ expand: opts.expand?.join(","), fields: opts.fields?.join(","), as: opts.viewAs });
627
631
  return this.request("GET", `/${type}/${id}/`, { query });
628
632
  }
@@ -637,6 +641,7 @@ var OwV2Client = class {
637
641
  * `null` are accepted and stored as `''` (nameless Markers exist).
638
642
  */
639
643
  async create(type, element, opts = {}) {
644
+ only("create", opts, ["idempotencyKey"]);
640
645
  refuseKnownOf(element, "create");
641
646
  const body = sanitizePayload(element);
642
647
  if (body.id === void 0 || body.id === null || body.id === "") {
@@ -723,6 +728,7 @@ var OwV2Client = class {
723
728
  * fresh UUIDv7. Ids you supply are kept.
724
729
  */
725
730
  async bulk(items, opts = {}) {
731
+ only("bulk", opts, ["atomic", "idempotencyKey"]);
726
732
  items.forEach((it, index) => refuseKnownOf(it.element, `bulk: items[${index}]`));
727
733
  const body = {
728
734
  items: items.map((it, index) => {
@@ -764,6 +770,7 @@ var OwV2Client = class {
764
770
  * that is not a date and time is a 422 naming `after`.
765
771
  */
766
772
  async changes(opts = {}) {
773
+ only("changes", opts, ["since", "limit", "after"]);
767
774
  const query = buildQuery({ since: opts.since, limit: opts.limit ?? this.changesPageSize, after: opts.after });
768
775
  const page = await this.request("GET", "/changes/", { query });
769
776
  return { ...page, cursor: String(page.cursor) };
@@ -794,6 +801,7 @@ var OwV2Client = class {
794
801
  * `head` and `epoch`: the view epoch the walk ran under, for a guest or a contributor).
795
802
  */
796
803
  async *changesAll(since, opts = {}) {
804
+ only("changesAll", opts, ["after"]);
797
805
  let cursor = since;
798
806
  let page;
799
807
  do {
@@ -883,6 +891,7 @@ var OwV2Client = class {
883
891
  * ticket is still unspent).
884
892
  */
885
893
  async removeImage(keyOrUrl, opts = {}) {
894
+ only("removeImage", opts, ["ticket"]);
886
895
  const ticket = opts.ticket ?? await this.createRemovalTicket(keyOrUrl);
887
896
  let res;
888
897
  try {
@@ -1068,6 +1077,7 @@ var OwV2Client = class {
1068
1077
  * for one ignores `character`.
1069
1078
  */
1070
1079
  async redeemJoin(code, opts = {}) {
1080
+ only("redeemJoin", opts, ["name", "agentName", "character"]);
1071
1081
  const body = { code };
1072
1082
  if (opts.name !== void 0) body.name = opts.name;
1073
1083
  if (opts.agentName !== void 0) body.agent_name = opts.agentName;
@@ -1096,6 +1106,7 @@ var OwV2Client = class {
1096
1106
  * `failed` (anything else, with keel's message). The password is never in an error.
1097
1107
  */
1098
1108
  async signInWithPassword(opts) {
1109
+ only("signInWithPassword", opts, ["email", "username", "password", "tokenName"]);
1099
1110
  const { email, username, password, tokenName } = opts ?? {};
1100
1111
  const login = typeof email === "string" ? email.trim() : "";
1101
1112
  const user = typeof username === "string" ? username.trim() : "";
@@ -1376,6 +1387,7 @@ var OwV2Client = class {
1376
1387
  * token only; no Idempotency-Key.
1377
1388
  */
1378
1389
  async mintWorldKey(worldId, opts = {}) {
1390
+ only("mintWorldKey", opts, ["scope", "name"]);
1379
1391
  if (this.keyKind !== "account") {
1380
1392
  throw new TypeError("mintWorldKey needs an account token (ow_a_)");
1381
1393
  }
@@ -1395,6 +1407,7 @@ var OwV2Client = class {
1395
1407
  * is sent; any client, keyless included. The handoff sheet: Orrery `keel/signin-handoff.md` §3.
1396
1408
  */
1397
1409
  async signInWithOnlyWorlds(opts) {
1410
+ only("signInWithOnlyWorlds", opts, ["clientId", "redirectUri", "resume", "storage", "navigate"]);
1398
1411
  return beginSignIn(this.baseUrl, opts);
1399
1412
  }
1400
1413
  /**
@@ -1407,6 +1420,7 @@ var OwV2Client = class {
1407
1420
  * 400: used, expired, or another client's code), `rate_limited`, `offline`, `failed`.
1408
1421
  */
1409
1422
  async completeSignIn(opts) {
1423
+ only("completeSignIn", opts, ["clientId", "storage", "url"]);
1410
1424
  return completeSignIn(this.baseUrl, this.fetchImpl, opts);
1411
1425
  }
1412
1426
  // -- Ask your world (keel #159) -------------------------------------------
@@ -1421,6 +1435,7 @@ var OwV2Client = class {
1421
1435
  * them counts. 422 for a question over 500 characters or context past its limits.
1422
1436
  */
1423
1437
  async ask(req) {
1438
+ only("ask", req, ["worldId", "question", "context"]);
1424
1439
  if (this.keyKind !== "account") {
1425
1440
  throw new TypeError("ask needs an account token (ow_a_): the proxy meters per account");
1426
1441
  }
@@ -1440,6 +1455,7 @@ var OwV2Client = class {
1440
1455
  * to 200 characters, anchors up to 120.
1441
1456
  */
1442
1457
  async sort(req) {
1458
+ only("sort", req, ["worldId", "notes", "slice"]);
1443
1459
  if (this.keyKind !== "account") {
1444
1460
  throw new TypeError("sort needs an account token (ow_a_): the proxy meters per account");
1445
1461
  }
@@ -1637,6 +1653,15 @@ function objectKey(keyOrUrl) {
1637
1653
  if (!/^https?:\/\//i.test(keyOrUrl)) return keyOrUrl;
1638
1654
  return decodeURIComponent(new URL(keyOrUrl).pathname.replace(/^\/+/, ""));
1639
1655
  }
1656
+ var LIST_PARAM_KEYS = ["limit", "cursor", "ids", "createdBy", "expand", "fields", "filter", "viewAs"];
1657
+ function only(method, obj, keys, hint = "") {
1658
+ if (!obj || typeof obj !== "object") return;
1659
+ for (const k of Object.keys(obj)) {
1660
+ if (!keys.includes(k)) {
1661
+ throw new TypeError(`${method}: unknown parameter '${k}'. ${hint ? hint + " " : ""}The keys are ${keys.join(", ")}. Nothing was sent.`);
1662
+ }
1663
+ }
1664
+ }
1640
1665
  function buildQuery(params) {
1641
1666
  const q = new URLSearchParams();
1642
1667
  for (const [k, v] of Object.entries(params)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.50.0",
3
+ "version": "4.52.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {