@onlyworlds/sdk 4.0.0 → 4.1.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 +91 -0
- package/README.md +4 -1
- package/SCHEMA.md +7 -7
- package/dist/index.d.ts +415 -405
- package/dist/index.js +47 -50
- package/package.json +63 -61
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,97 @@
|
|
|
3
3
|
All notable changes to `@onlyworlds/sdk`. Maintained from 3.1.0 onward (Kael, Assembly);
|
|
4
4
|
earlier history lives in git log only.
|
|
5
5
|
|
|
6
|
+
## [4.1.0] — 2026-07-29
|
|
7
|
+
|
|
8
|
+
Public-surface hygiene. Nothing breaks; one member is now marked for removal, and one
|
|
9
|
+
piece of long-standing speculation is retired by measurement.
|
|
10
|
+
|
|
11
|
+
⚑ **4.0.2 was tagged in git and superseded before it reached npm.** Everything in it ships
|
|
12
|
+
here — the tag stays as a record rather than being moved or deleted.
|
|
13
|
+
|
|
14
|
+
### Deprecated
|
|
15
|
+
- **`FieldType.integer_max` and `FieldInfo.max`** — removal scheduled for **5.0.0**. No
|
|
16
|
+
`FIELD_SCHEMA` entry has ever carried either, in this repository's entire history. They
|
|
17
|
+
existed to surface the schema's `maximum:` constraint, and that constraint is **advisory**:
|
|
18
|
+
keel declares no `MaxValueValidator`, and a `charisma: 9999` write against a `maximum: 100`
|
|
19
|
+
field returns 201 and stores it verbatim. The canonical schema walk therefore stays silent
|
|
20
|
+
on bounds permanently. There is no source to wire them to and no promise they could keep —
|
|
21
|
+
and a public type member meaning "hint the wire ignores" is one consumers read as
|
|
22
|
+
validation. Deprecating now rather than at the major so the signal arrives early; the
|
|
23
|
+
`@deprecated` tags surface in editors via the shipped `.d.ts`.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- **`TokenResource` is confirmed staying.** RFC-001 §5 asked the platform owner whether the
|
|
27
|
+
token routes were carried long-term or deprecated wire-side, and the question was never
|
|
28
|
+
answered in writing — so this package's own barrel carried "wire fate under review; may be
|
|
29
|
+
removed in a later 4.x" for months, on nobody's authority. Probed against production:
|
|
30
|
+
`GET /api/v2/tokens/status/` and `/tokens/encryption-info/` both return **200**, with a 404
|
|
31
|
+
control on a nonexistent route proving the check meant something. The wire carries it. The
|
|
32
|
+
speculation is retired and the comment now records the evidence instead.
|
|
33
|
+
|
|
34
|
+
## [4.0.2] — 2026-07-29
|
|
35
|
+
|
|
36
|
+
Re-pinned to `v0.30.1-dist.13` (canonical **00.30.01**). No field shape changed and no
|
|
37
|
+
`FIELD_SCHEMA` entry changed — the schema walk is byte-identical between the two pins, so
|
|
38
|
+
nothing about decoding moved. Three things changed and nothing else.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- **`construct.relations` and `event.languages` shipped with no description at all** — in
|
|
42
|
+
`types.generated.ts` and in `SCHEMA.md`. Their descriptions were nested one level too deep
|
|
43
|
+
inside `items:` in the canonical YAML, which made them invisible to every consumer that reads
|
|
44
|
+
field descriptions, this package included. `SCHEMA.md` is the package's AI-legibility artifact,
|
|
45
|
+
so the gap landed where it did the most harm.
|
|
46
|
+
- **Five description typos** corrected in published JSDoc and `SCHEMA.md`: `beapplied`,
|
|
47
|
+
`phyiscal`, `relating the`, `object grant`, `eventuated`. The rendered docs site had already
|
|
48
|
+
fixed all five by hand — the downstream copy was the correct one, and nobody noticed because
|
|
49
|
+
the fix went where it was visible rather than where it was true.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
- `ONLYWORLDS_VERSION` `'00.30.00'` → `'00.30.01'`. It is a public `as const`, so its **literal
|
|
53
|
+
type** changes. Depending on that literal is pathological, but it is a type-level change and
|
|
54
|
+
should not be discovered rather than announced.
|
|
55
|
+
- The pin now carries canonical's numeric-bounds correction: the `maximum: 0` sentinel is gone
|
|
56
|
+
from 26 fields, 8 fields gained `minimum: 0`, and `rulings.yaml` carries the numeric-bounds
|
|
57
|
+
row. Nothing in this package consumes bounds — `maximum:` is **advisory** (keel does not
|
|
58
|
+
enforce it; a `charisma: 9999` write returns 201 and stores verbatim) and the walk stays
|
|
59
|
+
silent on bounds permanently. `integer_max` / `max` therefore remain declared no-ops here.
|
|
60
|
+
|
|
61
|
+
## [4.0.1] — 2026-07-29
|
|
62
|
+
|
|
63
|
+
**Metadata correction release.** No wire-path change: the client's reads and writes never
|
|
64
|
+
consulted `FIELD_SCHEMA`, and the generated interfaces carried the correct targets throughout.
|
|
65
|
+
The exposure is anything that builds UI or validation by **iterating `FIELD_SCHEMA`**.
|
|
66
|
+
|
|
67
|
+
⚑ **One way this can surface as a compile error**: `relation.relations` is removed, so
|
|
68
|
+
`FIELD_SCHEMA.relation.relations` is now a TypeScript error rather than a value. That is the
|
|
69
|
+
intended outcome — the field does not exist in the standard and the API rejects it — but it can
|
|
70
|
+
break a build rather than only a behaviour.
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
- **`FIELD_SCHEMA.collective.equipment` targeted `construct`; the standard says `object`.**
|
|
74
|
+
This is the founding case of the schema ruling table
|
|
75
|
+
(`collective-equipment-target`, ruled 2026-07-23): the v1 implementation used
|
|
76
|
+
Construct, v1 is decommissioned, and keel serves per YAML. The generated code path
|
|
77
|
+
in this repo was corrected the same week. The hand-maintained `FIELD_SCHEMA` copy of
|
|
78
|
+
the same fact, in the same package, kept shipping the decommissioned value on
|
|
79
|
+
`latest` — the fix went where someone happened to be looking.
|
|
80
|
+
- **`FIELD_SCHEMA.relation.relations` removed** — a `multi_link` to `relation` that does
|
|
81
|
+
not exist in `relation.yaml`. A phantom field, publicly exported, that consumers
|
|
82
|
+
building forms from this table would have sent to an API that 422s unknown keys.
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
- **`FIELD_SCHEMA` is now GENERATED** from the pinned schema distribution and gated by
|
|
86
|
+
`codegen:check`, joining `ELEMENT_ICONS` / `ELEMENT_SECTIONS` / `ELEMENT_FAMILIES`. It
|
|
87
|
+
was ~650 hand-maintained lines whose test compared nothing to the schema. Regenerating
|
|
88
|
+
it changed exactly 2 of 467 entries — the two above. Runtime shape and the deeply
|
|
89
|
+
readonly public types (`as const`) are unchanged.
|
|
90
|
+
Two declared deviations from a naive schema read are now stated in the generated file:
|
|
91
|
+
`pin.element` (a `generic-link`) splits into `element_type` + `element_id`, as the wire
|
|
92
|
+
serves it; and `integer_max` / `max` remain in the `FieldType` union unused, because
|
|
93
|
+
the walk does not surface the schema's `maximum:` constraint (41 across 17 types).
|
|
94
|
+
- `codegen/generate_types.py` imports the vendored schema walk instead of carrying its
|
|
95
|
+
own copy of it. Output byte-identical.
|
|
96
|
+
|
|
6
97
|
## [4.0.0] — 2026-07-23
|
|
7
98
|
|
|
8
99
|
**v2-native only.** See `docs/migrating-3-to-4.md`. 3.x stays published forever for
|
package/README.md
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
The canonical typed client for the [OnlyWorlds](https://onlyworlds.github.io) v2 API, plus the
|
|
7
7
|
canonical constants (element types, icons, colour families, field schema) — generated from the
|
|
8
|
-
|
|
8
|
+
canonical OnlyWorlds schema, obtained through the public
|
|
9
|
+
[schema distribution](https://github.com/OnlyWorlds/schema-dist) at a pinned, hash-verified
|
|
10
|
+
tag. The generated files carry that tag and commit in their header, so what these types were
|
|
11
|
+
built from is checkable rather than asserted.
|
|
9
12
|
|
|
10
13
|
**4.x is v2-native and ESM-only (Node 18+).** If you need the legacy v1 API dialect
|
|
11
14
|
(`OnlyWorldsClient`) or CommonJS `require()`, stay on 3.x — it remains published and the v1 API
|
package/SCHEMA.md
CHANGED
|
@@ -149,7 +149,7 @@ Families (colour semantics; icon carries the type): agents · world · abstract
|
|
|
149
149
|
- `phenomena` (multi link → phenomenon) — Phenomena relevant to the construct
|
|
150
150
|
- `languages` (multi link → language) — Languages relevant to the construct
|
|
151
151
|
- `families` (multi link → family) — Families relevant to the construct
|
|
152
|
-
- `relations` (multi link → relation)
|
|
152
|
+
- `relations` (multi link → relation) — Relations relevant to the construct
|
|
153
153
|
- `titles` (multi link → title) — Titles relevant to the construct
|
|
154
154
|
- `constructs` (multi link → construct) — Other constructs relevant to the construct
|
|
155
155
|
- `events` (multi link → event) — Events relevant to the construct
|
|
@@ -200,7 +200,7 @@ Families (colour semantics; icon carries the type): agents · world · abstract
|
|
|
200
200
|
- `consequences` (text) — Outcomes and impacts resulting from the event
|
|
201
201
|
- `start_date` (integer) — Date on which the event began
|
|
202
202
|
- `end_date` (integer) — Date on which the event concluded
|
|
203
|
-
- `triggers` (multi link → event) — Events that
|
|
203
|
+
- `triggers` (multi link → event) — Events that precipitated this event
|
|
204
204
|
|
|
205
205
|
### Involves
|
|
206
206
|
|
|
@@ -215,7 +215,7 @@ Families (colour semantics; icon carries the type): agents · world · abstract
|
|
|
215
215
|
- `zones` (multi link → zone) — Zones relevant to the event
|
|
216
216
|
- `abilities` (multi link → ability) — Abilities relevant to the event
|
|
217
217
|
- `phenomena` (multi link → phenomenon) — Natural or supernatural phenomena relevant to the event
|
|
218
|
-
- `languages` (multi link → language)
|
|
218
|
+
- `languages` (multi link → language) — Languages relevant to the event
|
|
219
219
|
- `families` (multi link → family) — Families relevant to the event
|
|
220
220
|
- `relations` (multi link → relation) — Interpersonal or political relations relevant to the event
|
|
221
221
|
- `titles` (multi link → title) — Titles relevant to the event
|
|
@@ -294,7 +294,7 @@ Families (colour semantics; icon carries the type): agents · world · abstract
|
|
|
294
294
|
- `purpose` (text) — The intent, motivation, or justification for the law's creation
|
|
295
295
|
- `date` (integer) — Date the law was formally established, in world TIME units
|
|
296
296
|
- `parent_law` (single link → law) — A law that this law derives from, modifies, or enhances
|
|
297
|
-
- `penalties` (multi link → construct) — Consequences intended to
|
|
297
|
+
- `penalties` (multi link → construct) — Consequences intended to be applied when the law is contravened
|
|
298
298
|
|
|
299
299
|
### World
|
|
300
300
|
|
|
@@ -436,14 +436,14 @@ Families (colour semantics; icon carries the type): agents · world · abstract
|
|
|
436
436
|
- `weight` (integer) — Approximate or exact mass of the object, defined by world MASS units
|
|
437
437
|
- `amount` (integer) — The number of identical units in this object entry
|
|
438
438
|
- `parent_object` (single link → object) — Larger object that this one is part of or contained within
|
|
439
|
-
- `materials` (multi link → construct) — The
|
|
440
|
-
- `technology` (multi link → construct) — Mechanisms relating the object's design or operation
|
|
439
|
+
- `materials` (multi link → construct) — The physical matter that constitutes the object
|
|
440
|
+
- `technology` (multi link → construct) — Mechanisms relating to the object's design or operation
|
|
441
441
|
|
|
442
442
|
### Function
|
|
443
443
|
|
|
444
444
|
- `utility` (text) — Intended purpose or primary use of the object
|
|
445
445
|
- `effects` (multi link → phenomenon) — Phenomena potentially triggered or emitted on object use
|
|
446
|
-
- `abilities` (multi link → ability) — Abilities that the object
|
|
446
|
+
- `abilities` (multi link → ability) — Abilities that the object grants or enables
|
|
447
447
|
- `consumes` (multi link → construct) — What might be used or depleted on object use
|
|
448
448
|
|
|
449
449
|
### World
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/** Every element carries these. The extension index signature admits namespaced
|
|
2
|
-
* pass-through fields (atlas_* / shadow_* / x_*) returned verbatim by the server.
|
|
2
|
+
* pass-through fields (atlas_* / shadow_* / x_*) returned verbatim by the server.
|
|
3
|
+
* Derived from base_properties.yaml: `World` is dropped (the API rejects it in
|
|
4
|
+
* bodies -- the key determines the world) and the four server-managed fields are
|
|
5
|
+
* added, since they ride every wire body and appear in no element YAML. */
|
|
3
6
|
interface OwElementBase {
|
|
4
7
|
/** Element type slug (server-managed, read-only). */
|
|
5
8
|
type: string;
|
|
6
|
-
/** Unique identifier, uuidv7 format. */
|
|
9
|
+
/** Unique identifier for the element, uuidv7 format. */
|
|
7
10
|
id: string;
|
|
8
11
|
/** Name of the element. */
|
|
9
12
|
name: string;
|
|
@@ -26,15 +29,17 @@ interface OwElementBase {
|
|
|
26
29
|
}
|
|
27
30
|
type ElementType = 'ability' | 'character' | 'collective' | 'construct' | 'creature' | 'event' | 'family' | 'institution' | 'language' | 'law' | 'location' | 'map' | 'marker' | 'narrative' | 'object' | 'phenomenon' | 'pin' | 'relation' | 'species' | 'title' | 'trait' | 'zone';
|
|
28
31
|
declare const ELEMENT_TYPES: ElementType[];
|
|
29
|
-
/** Canonical OnlyWorlds schema version. Source: canonical
|
|
30
|
-
|
|
32
|
+
/** Canonical OnlyWorlds schema version. Source: the `canonical:` value of the pinned
|
|
33
|
+
* distribution's VERSION file (see the provenance block at the top of this file). */
|
|
34
|
+
declare const ONLYWORLDS_VERSION: "00.30.01";
|
|
31
35
|
/** The four semantic families (colour carries the family; ELEMENT_ICONS carries the type). */
|
|
32
36
|
type ElementFamily = 'agents' | 'world' | 'abstract' | 'temporal';
|
|
33
|
-
/** Per-type semantic family. Source:
|
|
34
|
-
* (first-party rendering
|
|
35
|
-
*
|
|
37
|
+
/** Per-type semantic family. Source: the distribution's `presentation.json` sidecar
|
|
38
|
+
* (first-party rendering DEFAULTS — NOT part of the council-governed OnlyWorlds
|
|
39
|
+
* standard, and explicitly overridable by any consumer). The colour values are
|
|
40
|
+
* NOT in the sidecar: FAMILY_COLORS is hand-authored here in src/v2/palette.ts. */
|
|
36
41
|
declare const ELEMENT_FAMILIES: Record<ElementType, ElementFamily>;
|
|
37
|
-
/** Material Symbols icon name per type. Source:
|
|
42
|
+
/** Material Symbols icon name per type. Source: the distribution's `presentation.json` sidecar. */
|
|
38
43
|
declare const ELEMENT_ICONS: Record<ElementType, string>;
|
|
39
44
|
/** Field grouping for display. DERIVED from the canonical schema's own document
|
|
40
45
|
* structure (top-level property groups, document order = display order). */
|
|
@@ -44,402 +49,28 @@ interface SectionInfo {
|
|
|
44
49
|
fields: string[];
|
|
45
50
|
}
|
|
46
51
|
declare const ELEMENT_SECTIONS: Record<ElementType, SectionInfo[]>;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
50
|
-
* wire-corrected against live staging fixtures 2026-07-18.
|
|
51
|
-
*
|
|
52
|
-
* OnlyWorlds v2 (keel) wire types -- the NON-generated, hand-owned wire shapes
|
|
53
|
-
* (envelopes, pages, bulk, changes, config). Per-type element field typing is
|
|
54
|
-
* generated (types.generated.ts). One-shape principle: a field reads the way it
|
|
55
|
-
* writes -- links are UUID arrays (or UUID/null), same name both directions.
|
|
56
|
-
* No `_ids` suffix in v2.
|
|
57
|
-
*/
|
|
58
|
-
|
|
59
|
-
/** An element as read from / written to the v2 API. Loose base + extension keys. */
|
|
60
|
-
type OwElement = OwElementBase;
|
|
61
|
-
/** Spatial types live under spatial/ in the OW Folder Format. */
|
|
62
|
-
declare const SPATIAL_TYPES: readonly ElementType[];
|
|
63
|
-
interface OwWorldMeta {
|
|
64
|
-
id: string;
|
|
65
|
-
name: string;
|
|
66
|
-
updated_at?: string;
|
|
67
|
-
public_read?: boolean;
|
|
68
|
-
[field: string]: unknown;
|
|
69
|
-
}
|
|
70
|
-
/** List envelope: cursor-paginated. */
|
|
71
|
-
interface OwPage<T = OwElement> {
|
|
72
|
-
data: T[];
|
|
73
|
-
has_more: boolean;
|
|
74
|
-
next_cursor: string | null;
|
|
75
|
-
}
|
|
76
|
-
/** /changes feed -- discriminated union on `op`. Apply in order -> convergence. */
|
|
77
|
-
type OwChange = {
|
|
78
|
-
op: 'upsert';
|
|
79
|
-
id: string;
|
|
80
|
-
type: string;
|
|
81
|
-
element: OwElement;
|
|
82
|
-
updated_at: string;
|
|
83
|
-
[k: string]: unknown;
|
|
84
|
-
} | {
|
|
85
|
-
op: 'delete';
|
|
86
|
-
id: string;
|
|
87
|
-
type: string;
|
|
88
|
-
deleted_at: string;
|
|
89
|
-
[k: string]: unknown;
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* /changes response. Wire shape verified in keel source (core/changes.py) and
|
|
93
|
-
* pinned here: {cursor, changes, has_more, head}.
|
|
94
|
-
*/
|
|
95
|
-
interface OwChangesPage {
|
|
96
|
-
/** Opaque compound cursor -- persist verbatim, never parse, never expires. */
|
|
97
|
-
cursor: string;
|
|
98
|
-
changes: OwChange[];
|
|
99
|
-
has_more: boolean;
|
|
100
|
-
/**
|
|
101
|
-
* World's current change_seq. If a persisted cursor is ever AHEAD of head,
|
|
102
|
-
* the server rewound (disaster restore) -- re-baseline from cursor zero
|
|
103
|
-
* instead of assuming caught-up.
|
|
104
|
-
*/
|
|
105
|
-
head: number;
|
|
106
|
-
}
|
|
107
|
-
interface OwBulkItem {
|
|
108
|
-
type: ElementType | string;
|
|
109
|
-
element: OwElement | Record<string, unknown>;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* One slot of a /bulk response. WIRE-CORRECTED (fixtures P2a/P2c): `status` is
|
|
113
|
-
* the NUMERIC HTTP status of that slot (201/400/...), success slots echo
|
|
114
|
-
* created_at/updated_at, error slots carry an OwErrorBody under `error`.
|
|
115
|
-
*/
|
|
116
|
-
interface OwBulkItemResult {
|
|
117
|
-
status: number;
|
|
118
|
-
id?: string;
|
|
119
|
-
created_at?: string;
|
|
120
|
-
updated_at?: string;
|
|
121
|
-
error?: OwErrorBody;
|
|
122
|
-
}
|
|
123
|
-
/** The wire error envelope carried in error slots and thrown errors. */
|
|
124
|
-
interface OwErrorBody {
|
|
125
|
-
type?: string;
|
|
126
|
-
code?: string;
|
|
127
|
-
message?: string;
|
|
128
|
-
param?: string | null;
|
|
129
|
-
doc_url?: string;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* /bulk response. WIRE-CORRECTED (fixtures P2a/P2c): the array key is `items`,
|
|
133
|
-
* not `results`. `wasReplay` is populated by the client from the (lowercase on
|
|
134
|
-
* the wire) Idempotent-Replay response header (fixture P2b) -- not a wire field.
|
|
135
|
-
*/
|
|
136
|
-
interface OwBulkResponse {
|
|
137
|
-
errors: boolean;
|
|
138
|
-
items: OwBulkItemResult[];
|
|
139
|
-
/** Client-derived: true when the server replayed a prior Idempotency-Key. */
|
|
140
|
-
wasReplay?: boolean;
|
|
141
|
-
[k: string]: unknown;
|
|
142
|
-
}
|
|
143
|
-
interface OwLinkEdit {
|
|
144
|
-
add?: string[];
|
|
145
|
-
remove?: string[];
|
|
146
|
-
}
|
|
147
|
-
interface ListParams {
|
|
148
|
-
limit?: number;
|
|
149
|
-
cursor?: string;
|
|
150
|
-
/** One-level stub expansion, e.g. ['friends', 'location']. */
|
|
151
|
-
expand?: string[];
|
|
152
|
-
/** Sparse include-set of field names. */
|
|
153
|
-
fields?: string[];
|
|
154
|
-
/**
|
|
155
|
-
* Blessed Django-style filters: __icontains, __in, __gte, __lte, __isnull,
|
|
156
|
-
* supertype/subtype equality. Unknown params 422 loudly server-side -- the
|
|
157
|
-
* client passes them through and lets the platform name the typo.
|
|
158
|
-
*/
|
|
159
|
-
filter?: Record<string, string | number | boolean>;
|
|
160
|
-
}
|
|
161
|
-
interface OwClientConfig {
|
|
162
|
-
/** ow_w_ / ow_r_ / ow_a_ prefixed key, or grandfathered 10-digit legacy key. */
|
|
163
|
-
apiKey: string;
|
|
164
|
-
/**
|
|
165
|
-
* Optional. Required for writes when the world has a PIN, and for legacy-key
|
|
166
|
-
* reads of private worlds. Prefixed keys read PIN-less. String, not number --
|
|
167
|
-
* '0123' !== 123.
|
|
168
|
-
*/
|
|
169
|
-
apiPin?: string;
|
|
170
|
-
/** Default: https://www.onlyworlds.com/api/v2 */
|
|
171
|
-
baseUrl?: string;
|
|
172
|
-
/**
|
|
173
|
-
* Page size for element lists. Default 100 (server default; max 1000).
|
|
174
|
-
* Deliberately visible in config: page size is a citizenship property.
|
|
175
|
-
*/
|
|
176
|
-
pageSize?: number;
|
|
177
|
-
/**
|
|
178
|
-
* Page size for /changes pulls. Default 100. Live precedents: Obsidian 100,
|
|
179
|
-
* Atlas 250, MCP 25. /changes is the platform's heaviest route -- be polite.
|
|
180
|
-
*/
|
|
181
|
-
changesPageSize?: number;
|
|
182
|
-
/** Injectable for tests / fake-keel harnesses. Defaults to globalThis.fetch. */
|
|
183
|
-
fetch?: typeof globalThis.fetch;
|
|
184
|
-
}
|
|
185
|
-
|
|
52
|
+
/** Field type definitions for OnlyWorlds elements. */
|
|
53
|
+
type FieldType = 'text' | 'integer'
|
|
186
54
|
/**
|
|
187
|
-
*
|
|
188
|
-
* wire-corrected against live staging fixtures 2026-07-18.
|
|
55
|
+
* @deprecated Emitted by nothing, and scheduled for removal in 5.0.0.
|
|
189
56
|
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
57
|
+
* No `FIELD_SCHEMA` entry has ever carried this type, in the entire history of
|
|
58
|
+
* this repository. It was meant to surface the schema's `maximum:` constraint,
|
|
59
|
+
* and that constraint is **advisory**: keel declares no `MaxValueValidator` and
|
|
60
|
+
* the wire stores `charisma: 9999` against a `maximum: 100` field (201, verbatim).
|
|
61
|
+
* The canonical schema walk therefore stays silent on bounds permanently, so
|
|
62
|
+
* there is no source to wire this to and no promise it could keep. A public type
|
|
63
|
+
* member meaning "hint the wire ignores" is one consumers read as validation.
|
|
195
64
|
*/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
/** Offending field/param named by the envelope (422/400), else null. */
|
|
205
|
-
readonly param: string | null;
|
|
206
|
-
/** Documentation link from the envelope -- show it to users/logs verbatim. */
|
|
207
|
-
readonly docUrl: string | null;
|
|
208
|
-
/** Raw parsed envelope (or body text when the body wasn't JSON). */
|
|
209
|
-
readonly detail: unknown;
|
|
210
|
-
constructor(status: number, code: string | null, message: string, docUrl: string | null, detail: unknown, type?: string | null, param?: string | null);
|
|
211
|
-
get isAuthError(): boolean;
|
|
212
|
-
/** 422s/400s name the offending param/field -- typos error loudly platform-wide. */
|
|
213
|
-
get isValidationError(): boolean;
|
|
214
|
-
/** Same Idempotency-Key replayed with a different payload. */
|
|
215
|
-
get isIdempotencyConflict(): boolean;
|
|
216
|
-
}
|
|
217
|
-
/** Network-level failure (fetch rejected) -- no envelope to parse. */
|
|
218
|
-
declare class OwNetworkError extends Error {
|
|
219
|
-
readonly cause2: unknown;
|
|
220
|
-
constructor(message: string, cause: unknown);
|
|
65
|
+
| 'integer_max' | 'single_link' | 'multi_link';
|
|
66
|
+
/** Field metadata structure. */
|
|
67
|
+
interface FieldInfo {
|
|
68
|
+
type: FieldType;
|
|
69
|
+
target?: string;
|
|
70
|
+
/** @deprecated Never populated; removed in 5.0.0. See `FieldType.integer_max`. */
|
|
71
|
+
max?: number;
|
|
72
|
+
required?: boolean;
|
|
221
73
|
}
|
|
222
|
-
/** Parse a wire envelope into OwApiError parts (exported for the error type-tests). */
|
|
223
|
-
/** Parse the platform ERROR envelope into an OwApiError. (Renamed from parseEnvelope in 4.0 —
|
|
224
|
-
* distinct from the world-export envelope, which is a different artifact entirely.) */
|
|
225
|
-
declare function parseErrorEnvelope(status: number, body: unknown): OwApiError;
|
|
226
|
-
/** Build an OwApiError from a non-2xx response, tolerating non-JSON bodies. */
|
|
227
|
-
declare function errorFromResponse(res: Response): Promise<OwApiError>;
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
231
|
-
* wire-corrected against live staging fixtures 2026-07-18.
|
|
232
|
-
*
|
|
233
|
-
* OnlyWorlds key-kind detection. Prefixes make leaked keys grep-scannable
|
|
234
|
-
* (Stripe/GitHub precedent) -- and tell a client what auth shape to expect.
|
|
235
|
-
*/
|
|
236
|
-
type OwKeyKind =
|
|
237
|
-
/** ow_w_ -- world key, read + write. Writes need the world's PIN if it has one. */
|
|
238
|
-
'write'
|
|
239
|
-
/** ow_r_ -- world key, read-only, works bare (no PIN). The share-with-players primitive. */
|
|
240
|
-
| 'read'
|
|
241
|
-
/** ow_a_ -- account Bearer token for /account/* routes; can mint world keys. */
|
|
242
|
-
| 'account'
|
|
243
|
-
/** Grandfathered 10-digit key. Needs PIN to read private worlds. */
|
|
244
|
-
| 'legacy' | 'unknown';
|
|
245
|
-
/** Demo range 0000000000-0000000009: read-only aliases, safe as live read gates. */
|
|
246
|
-
declare function isDemoKey(key: string): boolean;
|
|
247
|
-
declare function detectKeyKind(key: string): OwKeyKind;
|
|
248
|
-
/** Can this key kind ever perform world writes? (PIN is a separate, per-world question.) */
|
|
249
|
-
declare function kindCanWrite(kind: OwKeyKind): boolean;
|
|
250
|
-
/**
|
|
251
|
-
* Should a credential UI ask for a PIN with this key?
|
|
252
|
-
* Prefixed keys read PIN-less; legacy keys may need it; writes on pinned
|
|
253
|
-
* worlds always need it. 'optional' means: show the field, don't require it.
|
|
254
|
-
*/
|
|
255
|
-
declare function pinExpectation(kind: OwKeyKind): 'never' | 'optional' | 'required-for-private-reads';
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
259
|
-
* wire-corrected against live staging fixtures 2026-07-18.
|
|
260
|
-
*
|
|
261
|
-
* OwV2Client -- thin typed fetch client for the keel v2 API.
|
|
262
|
-
*
|
|
263
|
-
* Deliberately thin: no caching, no sync state, no retry policy -- those belong
|
|
264
|
-
* to callers (sync engines, tools, games). What IS encoded here is the wire
|
|
265
|
-
* contract and its safety rails: payload read-only-field stripping, opaque
|
|
266
|
-
* cursors, idempotency headers, doc_url-bearing errors, polite page sizes, and
|
|
267
|
-
* client-side UUID minting so idempotent retries are structurally safe.
|
|
268
|
-
*/
|
|
269
|
-
|
|
270
|
-
declare class OwV2Client {
|
|
271
|
-
readonly baseUrl: string;
|
|
272
|
-
readonly keyKind: OwKeyKind;
|
|
273
|
-
readonly pageSize: number;
|
|
274
|
-
readonly changesPageSize: number;
|
|
275
|
-
private readonly apiKey;
|
|
276
|
-
private readonly apiPin;
|
|
277
|
-
private readonly fetchImpl;
|
|
278
|
-
constructor(config: OwClientConfig);
|
|
279
|
-
/** GET /health -- unauthenticated liveness pulse. */
|
|
280
|
-
health(): Promise<unknown>;
|
|
281
|
-
/**
|
|
282
|
-
* GET /world -- world meta (name, calendar/time fields, public_read).
|
|
283
|
-
* GOTCHA (by server design): world-meta edits do NOT appear in /changes and
|
|
284
|
-
* do not bump change_seq. Poll getWorld().updated_at for meta freshness.
|
|
285
|
-
*/
|
|
286
|
-
getWorld(): Promise<OwWorldMeta>;
|
|
287
|
-
/** PATCH /world -- partial world-meta update. */
|
|
288
|
-
patchWorld(partial: Record<string, unknown>): Promise<OwWorldMeta>;
|
|
289
|
-
/** GET /{type}/ -- one cursor page. */
|
|
290
|
-
list(type: ElementType | string, params?: ListParams): Promise<OwPage>;
|
|
291
|
-
/** Cursor-walk every page of a type. Politeness: uses config pageSize. */
|
|
292
|
-
listAll(type: ElementType | string, params?: Omit<ListParams, 'cursor'>): AsyncGenerator<OwElement>;
|
|
293
|
-
/** GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields. */
|
|
294
|
-
get(type: ElementType | string, id: string, opts?: Pick<ListParams, 'expand' | 'fields'>): Promise<OwElement>;
|
|
295
|
-
/**
|
|
296
|
-
* POST /{type}/ -- create. Mints an RFC-4122 UUID for element.id when the
|
|
297
|
-
* caller omits one (design ruling D29d) so a retry carrying the same
|
|
298
|
-
* Idempotency-Key is structurally safe. Callers MAY still supply their own id.
|
|
299
|
-
*/
|
|
300
|
-
create(type: ElementType | string, element: OwElement | Record<string, unknown>, opts?: {
|
|
301
|
-
idempotencyKey?: string;
|
|
302
|
-
}): Promise<OwElement>;
|
|
303
|
-
/** PUT /{type}/{id}/ -- upsert-by-client-id. The local-first write primitive. */
|
|
304
|
-
upsert(type: ElementType | string, id: string, element: OwElement | Record<string, unknown>): Promise<OwElement>;
|
|
305
|
-
/**
|
|
306
|
-
* PATCH /{type}/{id}/ -- partial update. DESTRUCTIVE on sent fields: arrays
|
|
307
|
-
* replace wholesale, omitted fields stay untouched. For link arrays prefer
|
|
308
|
-
* editLinks() -- atomic server-side merge, no read-before-write.
|
|
309
|
-
*/
|
|
310
|
-
patch(type: ElementType | string, id: string, partial: Record<string, unknown>): Promise<OwElement>;
|
|
311
|
-
/**
|
|
312
|
-
* DELETE /{type}/{id}/ -- idempotent (204 on absent). Server writes a
|
|
313
|
-
* tombstone AND scrubs the id from every other element's links in the same
|
|
314
|
-
* transaction -- no client-side unlink pass needed, ever.
|
|
315
|
-
*/
|
|
316
|
-
delete(type: ElementType | string, id: string): Promise<void>;
|
|
317
|
-
/**
|
|
318
|
-
* POST /{type}/{id}/links/{field} with {add, remove} -- atomic link merge.
|
|
319
|
-
* Dedupes, tolerates already-present/already-absent ids. Returns the FULL
|
|
320
|
-
* updated element (fixture P5). Use this for all relationship editing; it
|
|
321
|
-
* retires the read-merge-PATCH dance.
|
|
322
|
-
*/
|
|
323
|
-
editLinks(type: ElementType | string, id: string, field: string, edit: OwLinkEdit): Promise<OwElement>;
|
|
324
|
-
/**
|
|
325
|
-
* POST /bulk -- up to ~1000 items. Partial success by default (HTTP 200
|
|
326
|
-
* always; inspect per-slot numeric `status` + top-level `errors` flag);
|
|
327
|
-
* atomic:true for all-or-nothing. Link validation runs against batch U
|
|
328
|
-
* database -- send in any order, cycles included; no client topo-sort.
|
|
329
|
-
* Success slots echo server-authoritative timestamps: set your sync baseline
|
|
330
|
-
* from this response alone. When an idempotencyKey is replayed, the returned
|
|
331
|
-
* response carries wasReplay:true (read from the Idempotent-Replay header).
|
|
332
|
-
*/
|
|
333
|
-
bulk(items: OwBulkItem[], opts?: {
|
|
334
|
-
atomic?: boolean;
|
|
335
|
-
idempotencyKey?: string;
|
|
336
|
-
}): Promise<OwBulkResponse>;
|
|
337
|
-
/**
|
|
338
|
-
* GET /changes -- one page of the world's ordered change feed.
|
|
339
|
-
* Cursor is OPAQUE and never expires: persist verbatim, never parse.
|
|
340
|
-
* Zero/absent cursor = full export (byte-aligned with the Folder Format).
|
|
341
|
-
* Rewind rule: if your persisted position is ahead of page.head, the server
|
|
342
|
-
* was restored -- re-baseline from cursor zero; do not assume caught-up.
|
|
343
|
-
* Citizenship: heaviest route on the platform; default page size is polite.
|
|
344
|
-
*/
|
|
345
|
-
changes(opts?: {
|
|
346
|
-
since?: string;
|
|
347
|
-
limit?: number;
|
|
348
|
-
}): Promise<OwChangesPage>;
|
|
349
|
-
/**
|
|
350
|
-
* Walk the feed from `since` (or from zero = full export) to the current
|
|
351
|
-
* tail, yielding ops in order. Returns the final cursor via the generator's
|
|
352
|
-
* return value; persist it for the next incremental pull.
|
|
353
|
-
*/
|
|
354
|
-
changesAll(since?: string): AsyncGenerator<OwChange, {
|
|
355
|
-
cursor: string;
|
|
356
|
-
head: number;
|
|
357
|
-
}>;
|
|
358
|
-
/**
|
|
359
|
-
* Raw authenticated request against this client's baseUrl. Public since 4.0
|
|
360
|
-
* so auxiliary resources can ride the same transport — it structurally
|
|
361
|
-
* satisfies `TokenTransport` (`new TokenResource(client)`). Prefer the typed
|
|
362
|
-
* methods for element CRUD; this is the escape hatch, and it does NOT apply
|
|
363
|
-
* sanitizePayload — callers own their body shape.
|
|
364
|
-
*/
|
|
365
|
-
request<T = unknown>(method: string, path: string, opts?: {
|
|
366
|
-
query?: string;
|
|
367
|
-
body?: unknown;
|
|
368
|
-
idempotencyKey?: string;
|
|
369
|
-
auth?: boolean;
|
|
370
|
-
allowEmpty?: boolean;
|
|
371
|
-
replayAware?: boolean;
|
|
372
|
-
}): Promise<T>;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Canonical element colour palette — four semantic families.
|
|
377
|
-
*
|
|
378
|
-
* Ruled by Captain 2026-07-22 after Skeld's measurement pass (Orrery
|
|
379
|
-
* `product/schema/element-palette-measurements.md`): 22 mutually-separable
|
|
380
|
-
* hues is structurally impossible; four families is the ceiling that passes
|
|
381
|
-
* all-pairs CVD separation in both modes. **Colour carries the FAMILY; the
|
|
382
|
-
* icon (`ELEMENT_ICONS`) carries the TYPE.** Dark-mode pairs land in the 6–8
|
|
383
|
-
* CVD floor band, so secondary encoding (icon + label) is REQUIRED alongside
|
|
384
|
-
* colour, not optional.
|
|
385
|
-
*
|
|
386
|
-
* The type→family map is GENERATED: `ELEMENT_FAMILIES` is emitted by
|
|
387
|
-
* `codegen/generate_types.py` from the `family:` key in keel's schema YAML
|
|
388
|
-
* (added 2026-07-23, keel c69366b) — a keel PRESENTATION-WRAPPER key
|
|
389
|
-
* (first-party rendering metadata, not part of the council-governed
|
|
390
|
-
* OnlyWorlds standard). It cannot drift from the schema; membership and hex
|
|
391
|
-
* invariants stay test-gated in `test/palette.test.mjs`.
|
|
392
|
-
*
|
|
393
|
-
* The hexes below are design constants, hand-authored beside the generated
|
|
394
|
-
* map. Do not change any value without re-running the CVD validation (every
|
|
395
|
-
* brighter World green collides with Temporal amber for protan viewers — the
|
|
396
|
-
* green is pinned BY the accessibility budget).
|
|
397
|
-
*
|
|
398
|
-
* Provenance: first proven live in atlas (`src/core/element-colors.ts`) and
|
|
399
|
-
* council (`src/cosmos/element-families.ts`) — both become re-exports of this
|
|
400
|
-
* module.
|
|
401
|
-
*/
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* Family → validated hex per surface mode. `light` assumes near-white
|
|
405
|
-
* surfaces, `dark` assumes near-black (measured against #0a0a0a).
|
|
406
|
-
* World green is identical in both modes and sits at its low-contrast end
|
|
407
|
-
* deliberately — see module header before "fixing" it.
|
|
408
|
-
*/
|
|
409
|
-
declare const FAMILY_COLORS: Record<ElementFamily, {
|
|
410
|
-
light: string;
|
|
411
|
-
dark: string;
|
|
412
|
-
}>;
|
|
413
|
-
/** Semantic family for an element type slug. */
|
|
414
|
-
declare function familyOf(type: ElementType): ElementFamily;
|
|
415
|
-
/**
|
|
416
|
-
* The convenience most callers want: canonical colour for an element type.
|
|
417
|
-
* Name matches the live atlas/council implementations so their SDK swap is a
|
|
418
|
-
* re-export, not a rename. Defaults to `dark` (both current consumers are
|
|
419
|
-
* dark-surface).
|
|
420
|
-
*/
|
|
421
|
-
declare function elementColor(type: ElementType, mode?: 'light' | 'dark'): string;
|
|
422
|
-
/** All four families, in ruling order (the order IS the CVD-safety mechanism of the source palette). */
|
|
423
|
-
declare const FAMILY_ORDER: readonly ElementFamily[];
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Current OnlyWorlds version
|
|
427
|
-
* Synced with https://github.com/OnlyWorlds/OnlyWorlds/blob/main/VERSION
|
|
428
|
-
*/
|
|
429
|
-
/**
|
|
430
|
-
* Field type definitions for OnlyWorlds elements
|
|
431
|
-
*/
|
|
432
|
-
type FieldType = 'text' | 'integer' | 'integer_max' | 'single_link' | 'multi_link';
|
|
433
|
-
/**
|
|
434
|
-
* Field metadata structure
|
|
435
|
-
*/
|
|
436
|
-
interface FieldInfo {
|
|
437
|
-
type: FieldType;
|
|
438
|
-
target?: string;
|
|
439
|
-
max?: number;
|
|
440
|
-
required?: boolean;
|
|
441
|
-
}
|
|
442
|
-
declare const ELEMENT_LABELS: Record<ElementType, string>;
|
|
443
74
|
declare const FIELD_SCHEMA: {
|
|
444
75
|
readonly ability: {
|
|
445
76
|
readonly name: {
|
|
@@ -681,7 +312,7 @@ declare const FIELD_SCHEMA: {
|
|
|
681
312
|
};
|
|
682
313
|
readonly equipment: {
|
|
683
314
|
readonly type: "multi_link";
|
|
684
|
-
readonly target: "
|
|
315
|
+
readonly target: "object";
|
|
685
316
|
};
|
|
686
317
|
readonly activity: {
|
|
687
318
|
readonly type: "text";
|
|
@@ -1892,10 +1523,6 @@ declare const FIELD_SCHEMA: {
|
|
|
1892
1523
|
readonly type: "multi_link";
|
|
1893
1524
|
readonly target: "family";
|
|
1894
1525
|
};
|
|
1895
|
-
readonly relations: {
|
|
1896
|
-
readonly type: "multi_link";
|
|
1897
|
-
readonly target: "relation";
|
|
1898
|
-
};
|
|
1899
1526
|
readonly titles: {
|
|
1900
1527
|
readonly type: "multi_link";
|
|
1901
1528
|
readonly target: "title";
|
|
@@ -2223,6 +1850,389 @@ declare const FIELD_SCHEMA: {
|
|
|
2223
1850
|
};
|
|
2224
1851
|
};
|
|
2225
1852
|
};
|
|
1853
|
+
|
|
1854
|
+
/**
|
|
1855
|
+
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
1856
|
+
* wire-corrected against live staging fixtures 2026-07-18.
|
|
1857
|
+
*
|
|
1858
|
+
* OnlyWorlds v2 (keel) wire types -- the NON-generated, hand-owned wire shapes
|
|
1859
|
+
* (envelopes, pages, bulk, changes, config). Per-type element field typing is
|
|
1860
|
+
* generated (types.generated.ts). One-shape principle: a field reads the way it
|
|
1861
|
+
* writes -- links are UUID arrays (or UUID/null), same name both directions.
|
|
1862
|
+
* No `_ids` suffix in v2.
|
|
1863
|
+
*/
|
|
1864
|
+
|
|
1865
|
+
/** An element as read from / written to the v2 API. Loose base + extension keys. */
|
|
1866
|
+
type OwElement = OwElementBase;
|
|
1867
|
+
/** Spatial types live under spatial/ in the OW Folder Format. */
|
|
1868
|
+
declare const SPATIAL_TYPES: readonly ElementType[];
|
|
1869
|
+
interface OwWorldMeta {
|
|
1870
|
+
id: string;
|
|
1871
|
+
name: string;
|
|
1872
|
+
updated_at?: string;
|
|
1873
|
+
public_read?: boolean;
|
|
1874
|
+
[field: string]: unknown;
|
|
1875
|
+
}
|
|
1876
|
+
/** List envelope: cursor-paginated. */
|
|
1877
|
+
interface OwPage<T = OwElement> {
|
|
1878
|
+
data: T[];
|
|
1879
|
+
has_more: boolean;
|
|
1880
|
+
next_cursor: string | null;
|
|
1881
|
+
}
|
|
1882
|
+
/** /changes feed -- discriminated union on `op`. Apply in order -> convergence. */
|
|
1883
|
+
type OwChange = {
|
|
1884
|
+
op: 'upsert';
|
|
1885
|
+
id: string;
|
|
1886
|
+
type: string;
|
|
1887
|
+
element: OwElement;
|
|
1888
|
+
updated_at: string;
|
|
1889
|
+
[k: string]: unknown;
|
|
1890
|
+
} | {
|
|
1891
|
+
op: 'delete';
|
|
1892
|
+
id: string;
|
|
1893
|
+
type: string;
|
|
1894
|
+
deleted_at: string;
|
|
1895
|
+
[k: string]: unknown;
|
|
1896
|
+
};
|
|
1897
|
+
/**
|
|
1898
|
+
* /changes response. Wire shape verified in keel source (core/changes.py) and
|
|
1899
|
+
* pinned here: {cursor, changes, has_more, head}.
|
|
1900
|
+
*/
|
|
1901
|
+
interface OwChangesPage {
|
|
1902
|
+
/** Opaque compound cursor -- persist verbatim, never parse, never expires. */
|
|
1903
|
+
cursor: string;
|
|
1904
|
+
changes: OwChange[];
|
|
1905
|
+
has_more: boolean;
|
|
1906
|
+
/**
|
|
1907
|
+
* World's current change_seq. If a persisted cursor is ever AHEAD of head,
|
|
1908
|
+
* the server rewound (disaster restore) -- re-baseline from cursor zero
|
|
1909
|
+
* instead of assuming caught-up.
|
|
1910
|
+
*/
|
|
1911
|
+
head: number;
|
|
1912
|
+
}
|
|
1913
|
+
interface OwBulkItem {
|
|
1914
|
+
type: ElementType | string;
|
|
1915
|
+
element: OwElement | Record<string, unknown>;
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* One slot of a /bulk response. WIRE-CORRECTED (fixtures P2a/P2c): `status` is
|
|
1919
|
+
* the NUMERIC HTTP status of that slot (201/400/...), success slots echo
|
|
1920
|
+
* created_at/updated_at, error slots carry an OwErrorBody under `error`.
|
|
1921
|
+
*/
|
|
1922
|
+
interface OwBulkItemResult {
|
|
1923
|
+
status: number;
|
|
1924
|
+
id?: string;
|
|
1925
|
+
created_at?: string;
|
|
1926
|
+
updated_at?: string;
|
|
1927
|
+
error?: OwErrorBody;
|
|
1928
|
+
}
|
|
1929
|
+
/** The wire error envelope carried in error slots and thrown errors. */
|
|
1930
|
+
interface OwErrorBody {
|
|
1931
|
+
type?: string;
|
|
1932
|
+
code?: string;
|
|
1933
|
+
message?: string;
|
|
1934
|
+
param?: string | null;
|
|
1935
|
+
doc_url?: string;
|
|
1936
|
+
}
|
|
1937
|
+
/**
|
|
1938
|
+
* /bulk response. WIRE-CORRECTED (fixtures P2a/P2c): the array key is `items`,
|
|
1939
|
+
* not `results`. `wasReplay` is populated by the client from the (lowercase on
|
|
1940
|
+
* the wire) Idempotent-Replay response header (fixture P2b) -- not a wire field.
|
|
1941
|
+
*/
|
|
1942
|
+
interface OwBulkResponse {
|
|
1943
|
+
errors: boolean;
|
|
1944
|
+
items: OwBulkItemResult[];
|
|
1945
|
+
/** Client-derived: true when the server replayed a prior Idempotency-Key. */
|
|
1946
|
+
wasReplay?: boolean;
|
|
1947
|
+
[k: string]: unknown;
|
|
1948
|
+
}
|
|
1949
|
+
interface OwLinkEdit {
|
|
1950
|
+
add?: string[];
|
|
1951
|
+
remove?: string[];
|
|
1952
|
+
}
|
|
1953
|
+
interface ListParams {
|
|
1954
|
+
limit?: number;
|
|
1955
|
+
cursor?: string;
|
|
1956
|
+
/** One-level stub expansion, e.g. ['friends', 'location']. */
|
|
1957
|
+
expand?: string[];
|
|
1958
|
+
/** Sparse include-set of field names. */
|
|
1959
|
+
fields?: string[];
|
|
1960
|
+
/**
|
|
1961
|
+
* Blessed Django-style filters: __icontains, __in, __gte, __lte, __isnull,
|
|
1962
|
+
* supertype/subtype equality. Unknown params 422 loudly server-side -- the
|
|
1963
|
+
* client passes them through and lets the platform name the typo.
|
|
1964
|
+
*/
|
|
1965
|
+
filter?: Record<string, string | number | boolean>;
|
|
1966
|
+
}
|
|
1967
|
+
interface OwClientConfig {
|
|
1968
|
+
/** ow_w_ / ow_r_ / ow_a_ prefixed key, or grandfathered 10-digit legacy key. */
|
|
1969
|
+
apiKey: string;
|
|
1970
|
+
/**
|
|
1971
|
+
* Optional. Required for writes when the world has a PIN, and for legacy-key
|
|
1972
|
+
* reads of private worlds. Prefixed keys read PIN-less. String, not number --
|
|
1973
|
+
* '0123' !== 123.
|
|
1974
|
+
*/
|
|
1975
|
+
apiPin?: string;
|
|
1976
|
+
/** Default: https://www.onlyworlds.com/api/v2 */
|
|
1977
|
+
baseUrl?: string;
|
|
1978
|
+
/**
|
|
1979
|
+
* Page size for element lists. Default 100 (server default; max 1000).
|
|
1980
|
+
* Deliberately visible in config: page size is a citizenship property.
|
|
1981
|
+
*/
|
|
1982
|
+
pageSize?: number;
|
|
1983
|
+
/**
|
|
1984
|
+
* Page size for /changes pulls. Default 100. Live precedents: Obsidian 100,
|
|
1985
|
+
* Atlas 250, MCP 25. /changes is the platform's heaviest route -- be polite.
|
|
1986
|
+
*/
|
|
1987
|
+
changesPageSize?: number;
|
|
1988
|
+
/** Injectable for tests / fake-keel harnesses. Defaults to globalThis.fetch. */
|
|
1989
|
+
fetch?: typeof globalThis.fetch;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
/**
|
|
1993
|
+
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
1994
|
+
* wire-corrected against live staging fixtures 2026-07-18.
|
|
1995
|
+
*
|
|
1996
|
+
* keel error envelope handling. The error contract is part of the contract:
|
|
1997
|
+
* envelopes carry a machine `code` and a `doc_url` fragment anchored at
|
|
1998
|
+
* onlyworlds.github.io/api/errors -- surface both, always. The live wire
|
|
1999
|
+
* envelope also carries `type` and `param` (fixtures P4a/P2c); both are
|
|
2000
|
+
* surfaced on the thrown error.
|
|
2001
|
+
*/
|
|
2002
|
+
/** Auth codes are distinguishable by design; client recovery UX differs per code. */
|
|
2003
|
+
type OwAuthErrorCode = 'invalid_credentials' | 'key_revoked' | 'world_gone';
|
|
2004
|
+
declare class OwApiError extends Error {
|
|
2005
|
+
readonly status: number;
|
|
2006
|
+
/** Machine error code from the keel envelope, e.g. 'invalid_credentials'. */
|
|
2007
|
+
readonly code: string | null;
|
|
2008
|
+
/** Error family from the envelope, e.g. 'invalid_request', 'not_found'. */
|
|
2009
|
+
readonly type: string | null;
|
|
2010
|
+
/** Offending field/param named by the envelope (422/400), else null. */
|
|
2011
|
+
readonly param: string | null;
|
|
2012
|
+
/** Documentation link from the envelope -- show it to users/logs verbatim. */
|
|
2013
|
+
readonly docUrl: string | null;
|
|
2014
|
+
/** Raw parsed envelope (or body text when the body wasn't JSON). */
|
|
2015
|
+
readonly detail: unknown;
|
|
2016
|
+
constructor(status: number, code: string | null, message: string, docUrl: string | null, detail: unknown, type?: string | null, param?: string | null);
|
|
2017
|
+
get isAuthError(): boolean;
|
|
2018
|
+
/** 422s/400s name the offending param/field -- typos error loudly platform-wide. */
|
|
2019
|
+
get isValidationError(): boolean;
|
|
2020
|
+
/** Same Idempotency-Key replayed with a different payload. */
|
|
2021
|
+
get isIdempotencyConflict(): boolean;
|
|
2022
|
+
}
|
|
2023
|
+
/** Network-level failure (fetch rejected) -- no envelope to parse. */
|
|
2024
|
+
declare class OwNetworkError extends Error {
|
|
2025
|
+
readonly cause2: unknown;
|
|
2026
|
+
constructor(message: string, cause: unknown);
|
|
2027
|
+
}
|
|
2028
|
+
/** Parse a wire envelope into OwApiError parts (exported for the error type-tests). */
|
|
2029
|
+
/** Parse the platform ERROR envelope into an OwApiError. (Renamed from parseEnvelope in 4.0 —
|
|
2030
|
+
* distinct from the world-export envelope, which is a different artifact entirely.) */
|
|
2031
|
+
declare function parseErrorEnvelope(status: number, body: unknown): OwApiError;
|
|
2032
|
+
/** Build an OwApiError from a non-2xx response, tolerating non-JSON bodies. */
|
|
2033
|
+
declare function errorFromResponse(res: Response): Promise<OwApiError>;
|
|
2034
|
+
|
|
2035
|
+
/**
|
|
2036
|
+
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
2037
|
+
* wire-corrected against live staging fixtures 2026-07-18.
|
|
2038
|
+
*
|
|
2039
|
+
* OnlyWorlds key-kind detection. Prefixes make leaked keys grep-scannable
|
|
2040
|
+
* (Stripe/GitHub precedent) -- and tell a client what auth shape to expect.
|
|
2041
|
+
*/
|
|
2042
|
+
type OwKeyKind =
|
|
2043
|
+
/** ow_w_ -- world key, read + write. Writes need the world's PIN if it has one. */
|
|
2044
|
+
'write'
|
|
2045
|
+
/** ow_r_ -- world key, read-only, works bare (no PIN). The share-with-players primitive. */
|
|
2046
|
+
| 'read'
|
|
2047
|
+
/** ow_a_ -- account Bearer token for /account/* routes; can mint world keys. */
|
|
2048
|
+
| 'account'
|
|
2049
|
+
/** Grandfathered 10-digit key. Needs PIN to read private worlds. */
|
|
2050
|
+
| 'legacy' | 'unknown';
|
|
2051
|
+
/** Demo range 0000000000-0000000009: read-only aliases, safe as live read gates. */
|
|
2052
|
+
declare function isDemoKey(key: string): boolean;
|
|
2053
|
+
declare function detectKeyKind(key: string): OwKeyKind;
|
|
2054
|
+
/** Can this key kind ever perform world writes? (PIN is a separate, per-world question.) */
|
|
2055
|
+
declare function kindCanWrite(kind: OwKeyKind): boolean;
|
|
2056
|
+
/**
|
|
2057
|
+
* Should a credential UI ask for a PIN with this key?
|
|
2058
|
+
* Prefixed keys read PIN-less; legacy keys may need it; writes on pinned
|
|
2059
|
+
* worlds always need it. 'optional' means: show the field, don't require it.
|
|
2060
|
+
*/
|
|
2061
|
+
declare function pinExpectation(kind: OwKeyKind): 'never' | 'optional' | 'required-for-private-reads';
|
|
2062
|
+
|
|
2063
|
+
/**
|
|
2064
|
+
* keel v2 engine absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
|
|
2065
|
+
* wire-corrected against live staging fixtures 2026-07-18.
|
|
2066
|
+
*
|
|
2067
|
+
* OwV2Client -- thin typed fetch client for the keel v2 API.
|
|
2068
|
+
*
|
|
2069
|
+
* Deliberately thin: no caching, no sync state, no retry policy -- those belong
|
|
2070
|
+
* to callers (sync engines, tools, games). What IS encoded here is the wire
|
|
2071
|
+
* contract and its safety rails: payload read-only-field stripping, opaque
|
|
2072
|
+
* cursors, idempotency headers, doc_url-bearing errors, polite page sizes, and
|
|
2073
|
+
* client-side UUID minting so idempotent retries are structurally safe.
|
|
2074
|
+
*/
|
|
2075
|
+
|
|
2076
|
+
declare class OwV2Client {
|
|
2077
|
+
readonly baseUrl: string;
|
|
2078
|
+
readonly keyKind: OwKeyKind;
|
|
2079
|
+
readonly pageSize: number;
|
|
2080
|
+
readonly changesPageSize: number;
|
|
2081
|
+
private readonly apiKey;
|
|
2082
|
+
private readonly apiPin;
|
|
2083
|
+
private readonly fetchImpl;
|
|
2084
|
+
constructor(config: OwClientConfig);
|
|
2085
|
+
/** GET /health -- unauthenticated liveness pulse. */
|
|
2086
|
+
health(): Promise<unknown>;
|
|
2087
|
+
/**
|
|
2088
|
+
* GET /world -- world meta (name, calendar/time fields, public_read).
|
|
2089
|
+
* GOTCHA (by server design): world-meta edits do NOT appear in /changes and
|
|
2090
|
+
* do not bump change_seq. Poll getWorld().updated_at for meta freshness.
|
|
2091
|
+
*/
|
|
2092
|
+
getWorld(): Promise<OwWorldMeta>;
|
|
2093
|
+
/** PATCH /world -- partial world-meta update. */
|
|
2094
|
+
patchWorld(partial: Record<string, unknown>): Promise<OwWorldMeta>;
|
|
2095
|
+
/** GET /{type}/ -- one cursor page. */
|
|
2096
|
+
list(type: ElementType | string, params?: ListParams): Promise<OwPage>;
|
|
2097
|
+
/** Cursor-walk every page of a type. Politeness: uses config pageSize. */
|
|
2098
|
+
listAll(type: ElementType | string, params?: Omit<ListParams, 'cursor'>): AsyncGenerator<OwElement>;
|
|
2099
|
+
/** GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields. */
|
|
2100
|
+
get(type: ElementType | string, id: string, opts?: Pick<ListParams, 'expand' | 'fields'>): Promise<OwElement>;
|
|
2101
|
+
/**
|
|
2102
|
+
* POST /{type}/ -- create. Mints an RFC-4122 UUID for element.id when the
|
|
2103
|
+
* caller omits one (design ruling D29d) so a retry carrying the same
|
|
2104
|
+
* Idempotency-Key is structurally safe. Callers MAY still supply their own id.
|
|
2105
|
+
*/
|
|
2106
|
+
create(type: ElementType | string, element: OwElement | Record<string, unknown>, opts?: {
|
|
2107
|
+
idempotencyKey?: string;
|
|
2108
|
+
}): Promise<OwElement>;
|
|
2109
|
+
/** PUT /{type}/{id}/ -- upsert-by-client-id. The local-first write primitive. */
|
|
2110
|
+
upsert(type: ElementType | string, id: string, element: OwElement | Record<string, unknown>): Promise<OwElement>;
|
|
2111
|
+
/**
|
|
2112
|
+
* PATCH /{type}/{id}/ -- partial update. DESTRUCTIVE on sent fields: arrays
|
|
2113
|
+
* replace wholesale, omitted fields stay untouched. For link arrays prefer
|
|
2114
|
+
* editLinks() -- atomic server-side merge, no read-before-write.
|
|
2115
|
+
*/
|
|
2116
|
+
patch(type: ElementType | string, id: string, partial: Record<string, unknown>): Promise<OwElement>;
|
|
2117
|
+
/**
|
|
2118
|
+
* DELETE /{type}/{id}/ -- idempotent (204 on absent). Server writes a
|
|
2119
|
+
* tombstone AND scrubs the id from every other element's links in the same
|
|
2120
|
+
* transaction -- no client-side unlink pass needed, ever.
|
|
2121
|
+
*/
|
|
2122
|
+
delete(type: ElementType | string, id: string): Promise<void>;
|
|
2123
|
+
/**
|
|
2124
|
+
* POST /{type}/{id}/links/{field} with {add, remove} -- atomic link merge.
|
|
2125
|
+
* Dedupes, tolerates already-present/already-absent ids. Returns the FULL
|
|
2126
|
+
* updated element (fixture P5). Use this for all relationship editing; it
|
|
2127
|
+
* retires the read-merge-PATCH dance.
|
|
2128
|
+
*/
|
|
2129
|
+
editLinks(type: ElementType | string, id: string, field: string, edit: OwLinkEdit): Promise<OwElement>;
|
|
2130
|
+
/**
|
|
2131
|
+
* POST /bulk -- up to ~1000 items. Partial success by default (HTTP 200
|
|
2132
|
+
* always; inspect per-slot numeric `status` + top-level `errors` flag);
|
|
2133
|
+
* atomic:true for all-or-nothing. Link validation runs against batch U
|
|
2134
|
+
* database -- send in any order, cycles included; no client topo-sort.
|
|
2135
|
+
* Success slots echo server-authoritative timestamps: set your sync baseline
|
|
2136
|
+
* from this response alone. When an idempotencyKey is replayed, the returned
|
|
2137
|
+
* response carries wasReplay:true (read from the Idempotent-Replay header).
|
|
2138
|
+
*/
|
|
2139
|
+
bulk(items: OwBulkItem[], opts?: {
|
|
2140
|
+
atomic?: boolean;
|
|
2141
|
+
idempotencyKey?: string;
|
|
2142
|
+
}): Promise<OwBulkResponse>;
|
|
2143
|
+
/**
|
|
2144
|
+
* GET /changes -- one page of the world's ordered change feed.
|
|
2145
|
+
* Cursor is OPAQUE and never expires: persist verbatim, never parse.
|
|
2146
|
+
* Zero/absent cursor = full export (byte-aligned with the Folder Format).
|
|
2147
|
+
* Rewind rule: if your persisted position is ahead of page.head, the server
|
|
2148
|
+
* was restored -- re-baseline from cursor zero; do not assume caught-up.
|
|
2149
|
+
* Citizenship: heaviest route on the platform; default page size is polite.
|
|
2150
|
+
*/
|
|
2151
|
+
changes(opts?: {
|
|
2152
|
+
since?: string;
|
|
2153
|
+
limit?: number;
|
|
2154
|
+
}): Promise<OwChangesPage>;
|
|
2155
|
+
/**
|
|
2156
|
+
* Walk the feed from `since` (or from zero = full export) to the current
|
|
2157
|
+
* tail, yielding ops in order. Returns the final cursor via the generator's
|
|
2158
|
+
* return value; persist it for the next incremental pull.
|
|
2159
|
+
*/
|
|
2160
|
+
changesAll(since?: string): AsyncGenerator<OwChange, {
|
|
2161
|
+
cursor: string;
|
|
2162
|
+
head: number;
|
|
2163
|
+
}>;
|
|
2164
|
+
/**
|
|
2165
|
+
* Raw authenticated request against this client's baseUrl. Public since 4.0
|
|
2166
|
+
* so auxiliary resources can ride the same transport — it structurally
|
|
2167
|
+
* satisfies `TokenTransport` (`new TokenResource(client)`). Prefer the typed
|
|
2168
|
+
* methods for element CRUD; this is the escape hatch, and it does NOT apply
|
|
2169
|
+
* sanitizePayload — callers own their body shape.
|
|
2170
|
+
*/
|
|
2171
|
+
request<T = unknown>(method: string, path: string, opts?: {
|
|
2172
|
+
query?: string;
|
|
2173
|
+
body?: unknown;
|
|
2174
|
+
idempotencyKey?: string;
|
|
2175
|
+
auth?: boolean;
|
|
2176
|
+
allowEmpty?: boolean;
|
|
2177
|
+
replayAware?: boolean;
|
|
2178
|
+
}): Promise<T>;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
/**
|
|
2182
|
+
* Canonical element colour palette — four semantic families.
|
|
2183
|
+
*
|
|
2184
|
+
* Ruled by Captain 2026-07-22 after Skeld's measurement pass (Orrery
|
|
2185
|
+
* `product/schema/element-palette-measurements.md`): 22 mutually-separable
|
|
2186
|
+
* hues is structurally impossible; four families is the ceiling that passes
|
|
2187
|
+
* all-pairs CVD separation in both modes. **Colour carries the FAMILY; the
|
|
2188
|
+
* icon (`ELEMENT_ICONS`) carries the TYPE.** Dark-mode pairs land in the 6–8
|
|
2189
|
+
* CVD floor band, so secondary encoding (icon + label) is REQUIRED alongside
|
|
2190
|
+
* colour, not optional.
|
|
2191
|
+
*
|
|
2192
|
+
* The type→family map is GENERATED: `ELEMENT_FAMILIES` is emitted by
|
|
2193
|
+
* `codegen/generate_types.py` from the `family:` key in keel's schema YAML
|
|
2194
|
+
* (added 2026-07-23, keel c69366b) — a keel PRESENTATION-WRAPPER key
|
|
2195
|
+
* (first-party rendering metadata, not part of the council-governed
|
|
2196
|
+
* OnlyWorlds standard). It cannot drift from the schema; membership and hex
|
|
2197
|
+
* invariants stay test-gated in `test/palette.test.mjs`.
|
|
2198
|
+
*
|
|
2199
|
+
* The hexes below are design constants, hand-authored beside the generated
|
|
2200
|
+
* map. Do not change any value without re-running the CVD validation (every
|
|
2201
|
+
* brighter World green collides with Temporal amber for protan viewers — the
|
|
2202
|
+
* green is pinned BY the accessibility budget).
|
|
2203
|
+
*
|
|
2204
|
+
* Provenance: first proven live in atlas (`src/core/element-colors.ts`) and
|
|
2205
|
+
* council (`src/cosmos/element-families.ts`) — both become re-exports of this
|
|
2206
|
+
* module.
|
|
2207
|
+
*/
|
|
2208
|
+
|
|
2209
|
+
/**
|
|
2210
|
+
* Family → validated hex per surface mode. `light` assumes near-white
|
|
2211
|
+
* surfaces, `dark` assumes near-black (measured against #0a0a0a).
|
|
2212
|
+
* World green is identical in both modes and sits at its low-contrast end
|
|
2213
|
+
* deliberately — see module header before "fixing" it.
|
|
2214
|
+
*/
|
|
2215
|
+
declare const FAMILY_COLORS: Record<ElementFamily, {
|
|
2216
|
+
light: string;
|
|
2217
|
+
dark: string;
|
|
2218
|
+
}>;
|
|
2219
|
+
/** Semantic family for an element type slug. */
|
|
2220
|
+
declare function familyOf(type: ElementType): ElementFamily;
|
|
2221
|
+
/**
|
|
2222
|
+
* The convenience most callers want: canonical colour for an element type.
|
|
2223
|
+
* Name matches the live atlas/council implementations so their SDK swap is a
|
|
2224
|
+
* re-export, not a rename. Defaults to `dark` (both current consumers are
|
|
2225
|
+
* dark-surface).
|
|
2226
|
+
*/
|
|
2227
|
+
declare function elementColor(type: ElementType, mode?: 'light' | 'dark'): string;
|
|
2228
|
+
/** All four families, in ruling order (the order IS the CVD-safety mechanism of the source palette). */
|
|
2229
|
+
declare const FAMILY_ORDER: readonly ElementFamily[];
|
|
2230
|
+
|
|
2231
|
+
/**
|
|
2232
|
+
* Current OnlyWorlds version
|
|
2233
|
+
* Synced with https://github.com/OnlyWorlds/OnlyWorlds/blob/main/VERSION
|
|
2234
|
+
*/
|
|
2235
|
+
declare const ELEMENT_LABELS: Record<ElementType, string>;
|
|
2226
2236
|
/**
|
|
2227
2237
|
* Get Material Design icon name for an element type
|
|
2228
2238
|
* Accepts multiple formats: 'character', 'characters', 'Character', etc.
|
package/dist/index.js
CHANGED
|
@@ -314,7 +314,7 @@ function buildQuery(params) {
|
|
|
314
314
|
|
|
315
315
|
// src/v2/types.generated.ts
|
|
316
316
|
var ELEMENT_TYPES = ["ability", "character", "collective", "construct", "creature", "event", "family", "institution", "language", "law", "location", "map", "marker", "narrative", "object", "phenomenon", "pin", "relation", "species", "title", "trait", "zone"];
|
|
317
|
-
var ONLYWORLDS_VERSION = "00.30.
|
|
317
|
+
var ONLYWORLDS_VERSION = "00.30.01";
|
|
318
318
|
var ELEMENT_FAMILIES = {
|
|
319
319
|
ability: "abstract",
|
|
320
320
|
character: "agents",
|
|
@@ -466,50 +466,6 @@ var ELEMENT_SECTIONS = {
|
|
|
466
466
|
{ name: "World", order: 2, fields: ["context", "populations", "titles", "principles"] }
|
|
467
467
|
]
|
|
468
468
|
};
|
|
469
|
-
|
|
470
|
-
// src/v2/types.ts
|
|
471
|
-
var SPATIAL_TYPES = ["map", "pin", "marker", "zone"];
|
|
472
|
-
|
|
473
|
-
// src/v2/palette.ts
|
|
474
|
-
var FAMILY_COLORS = {
|
|
475
|
-
agents: { light: "#2a78d6", dark: "#3987e5" },
|
|
476
|
-
world: { light: "#008300", dark: "#008300" },
|
|
477
|
-
abstract: { light: "#e87ba4", dark: "#d55181" },
|
|
478
|
-
temporal: { light: "#eda100", dark: "#c98500" }
|
|
479
|
-
};
|
|
480
|
-
function familyOf(type) {
|
|
481
|
-
return ELEMENT_FAMILIES[type];
|
|
482
|
-
}
|
|
483
|
-
function elementColor(type, mode = "dark") {
|
|
484
|
-
return FAMILY_COLORS[ELEMENT_FAMILIES[type]][mode];
|
|
485
|
-
}
|
|
486
|
-
var FAMILY_ORDER = ["agents", "world", "abstract", "temporal"];
|
|
487
|
-
|
|
488
|
-
// src/v2/constants.ts
|
|
489
|
-
var ELEMENT_LABELS = {
|
|
490
|
-
ability: "Abilities",
|
|
491
|
-
character: "Characters",
|
|
492
|
-
collective: "Collectives",
|
|
493
|
-
construct: "Constructs",
|
|
494
|
-
creature: "Creatures",
|
|
495
|
-
event: "Events",
|
|
496
|
-
family: "Families",
|
|
497
|
-
institution: "Institutions",
|
|
498
|
-
language: "Languages",
|
|
499
|
-
law: "Laws",
|
|
500
|
-
location: "Locations",
|
|
501
|
-
map: "Maps",
|
|
502
|
-
marker: "Markers",
|
|
503
|
-
narrative: "Narratives",
|
|
504
|
-
object: "Objects",
|
|
505
|
-
phenomenon: "Phenomena",
|
|
506
|
-
pin: "Pins",
|
|
507
|
-
relation: "Relations",
|
|
508
|
-
species: "Species",
|
|
509
|
-
title: "Titles",
|
|
510
|
-
trait: "Traits",
|
|
511
|
-
zone: "Zones"
|
|
512
|
-
};
|
|
513
469
|
var FIELD_SCHEMA = {
|
|
514
470
|
ability: {
|
|
515
471
|
// Base fields (shared by all elements)
|
|
@@ -594,7 +550,7 @@ var FIELD_SCHEMA = {
|
|
|
594
550
|
count: { type: "integer" },
|
|
595
551
|
formation_date: { type: "integer" },
|
|
596
552
|
operator: { type: "single_link", target: "institution" },
|
|
597
|
-
equipment: { type: "multi_link", target: "
|
|
553
|
+
equipment: { type: "multi_link", target: "object" },
|
|
598
554
|
// Dynamics
|
|
599
555
|
activity: { type: "text" },
|
|
600
556
|
disposition: { type: "text" },
|
|
@@ -655,7 +611,7 @@ var FIELD_SCHEMA = {
|
|
|
655
611
|
weight: { type: "integer" },
|
|
656
612
|
height: { type: "integer" },
|
|
657
613
|
species: { type: "multi_link", target: "species" },
|
|
658
|
-
//
|
|
614
|
+
// Behavior
|
|
659
615
|
habits: { type: "text" },
|
|
660
616
|
demeanor: { type: "text" },
|
|
661
617
|
traits: { type: "multi_link", target: "trait" },
|
|
@@ -957,9 +913,7 @@ var FIELD_SCHEMA = {
|
|
|
957
913
|
// Details
|
|
958
914
|
map: { type: "single_link", target: "map", required: true },
|
|
959
915
|
element_type: { type: "text", required: true },
|
|
960
|
-
// ElementType enum value; YAML 'element' generic-link is split into _type + _id
|
|
961
916
|
element_id: { type: "single_link", target: "any", required: true },
|
|
962
|
-
// Can reference any element
|
|
963
917
|
x: { type: "integer", required: true },
|
|
964
918
|
y: { type: "integer", required: true },
|
|
965
919
|
z: { type: "integer" }
|
|
@@ -992,7 +946,6 @@ var FIELD_SCHEMA = {
|
|
|
992
946
|
phenomena: { type: "multi_link", target: "phenomenon" },
|
|
993
947
|
languages: { type: "multi_link", target: "language" },
|
|
994
948
|
families: { type: "multi_link", target: "family" },
|
|
995
|
-
relations: { type: "multi_link", target: "relation" },
|
|
996
949
|
titles: { type: "multi_link", target: "title" },
|
|
997
950
|
constructs: { type: "multi_link", target: "construct" },
|
|
998
951
|
narratives: { type: "multi_link", target: "narrative" }
|
|
@@ -1104,6 +1057,50 @@ var FIELD_SCHEMA = {
|
|
|
1104
1057
|
principles: { type: "multi_link", target: "construct" }
|
|
1105
1058
|
}
|
|
1106
1059
|
};
|
|
1060
|
+
|
|
1061
|
+
// src/v2/types.ts
|
|
1062
|
+
var SPATIAL_TYPES = ["map", "pin", "marker", "zone"];
|
|
1063
|
+
|
|
1064
|
+
// src/v2/palette.ts
|
|
1065
|
+
var FAMILY_COLORS = {
|
|
1066
|
+
agents: { light: "#2a78d6", dark: "#3987e5" },
|
|
1067
|
+
world: { light: "#008300", dark: "#008300" },
|
|
1068
|
+
abstract: { light: "#e87ba4", dark: "#d55181" },
|
|
1069
|
+
temporal: { light: "#eda100", dark: "#c98500" }
|
|
1070
|
+
};
|
|
1071
|
+
function familyOf(type) {
|
|
1072
|
+
return ELEMENT_FAMILIES[type];
|
|
1073
|
+
}
|
|
1074
|
+
function elementColor(type, mode = "dark") {
|
|
1075
|
+
return FAMILY_COLORS[ELEMENT_FAMILIES[type]][mode];
|
|
1076
|
+
}
|
|
1077
|
+
var FAMILY_ORDER = ["agents", "world", "abstract", "temporal"];
|
|
1078
|
+
|
|
1079
|
+
// src/v2/constants.ts
|
|
1080
|
+
var ELEMENT_LABELS = {
|
|
1081
|
+
ability: "Abilities",
|
|
1082
|
+
character: "Characters",
|
|
1083
|
+
collective: "Collectives",
|
|
1084
|
+
construct: "Constructs",
|
|
1085
|
+
creature: "Creatures",
|
|
1086
|
+
event: "Events",
|
|
1087
|
+
family: "Families",
|
|
1088
|
+
institution: "Institutions",
|
|
1089
|
+
language: "Languages",
|
|
1090
|
+
law: "Laws",
|
|
1091
|
+
location: "Locations",
|
|
1092
|
+
map: "Maps",
|
|
1093
|
+
marker: "Markers",
|
|
1094
|
+
narrative: "Narratives",
|
|
1095
|
+
object: "Objects",
|
|
1096
|
+
phenomenon: "Phenomena",
|
|
1097
|
+
pin: "Pins",
|
|
1098
|
+
relation: "Relations",
|
|
1099
|
+
species: "Species",
|
|
1100
|
+
title: "Titles",
|
|
1101
|
+
trait: "Traits",
|
|
1102
|
+
zone: "Zones"
|
|
1103
|
+
};
|
|
1107
1104
|
var PLURAL_TO_SINGULAR = {
|
|
1108
1105
|
abilities: "ability",
|
|
1109
1106
|
characters: "character",
|
package/package.json
CHANGED
|
@@ -1,61 +1,63 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@onlyworlds/sdk",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"exports": {
|
|
7
|
-
".": {
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"import": "./dist/index.js"
|
|
10
|
-
},
|
|
11
|
-
"./package.json": "./package.json"
|
|
12
|
-
},
|
|
13
|
-
"types": "dist/index.d.ts",
|
|
14
|
-
"sideEffects": false,
|
|
15
|
-
"files": [
|
|
16
|
-
"dist",
|
|
17
|
-
"README.md",
|
|
18
|
-
"AGENTS.md",
|
|
19
|
-
"CHANGELOG.md",
|
|
20
|
-
"SCHEMA.md"
|
|
21
|
-
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
24
|
-
"dev": "tsup src/index.ts --format esm --dts --watch",
|
|
25
|
-
"pretest": "npm run build",
|
|
26
|
-
"test": "node --test
|
|
27
|
-
"codegen": "python codegen/generate_types.py",
|
|
28
|
-
"codegen:check": "python codegen/generate_types.py --check",
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@onlyworlds/sdk",
|
|
3
|
+
"version": "4.1.0",
|
|
4
|
+
"description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"types": "dist/index.d.ts",
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"AGENTS.md",
|
|
19
|
+
"CHANGELOG.md",
|
|
20
|
+
"SCHEMA.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
24
|
+
"dev": "tsup src/index.ts --format esm --dts --watch",
|
|
25
|
+
"pretest": "npm run build",
|
|
26
|
+
"test": "node --test",
|
|
27
|
+
"codegen": "python codegen/generate_types.py",
|
|
28
|
+
"codegen:check": "python codegen/generate_types.py --check",
|
|
29
|
+
"schema:verify": "python codegen/verify_dist.py",
|
|
30
|
+
"schema:check": "npm run schema:verify && npm run codegen:check",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"onlyworlds",
|
|
35
|
+
"worldbuilding",
|
|
36
|
+
"api",
|
|
37
|
+
"sdk",
|
|
38
|
+
"typescript",
|
|
39
|
+
"rpg",
|
|
40
|
+
"ttrpg",
|
|
41
|
+
"game-development"
|
|
42
|
+
],
|
|
43
|
+
"author": "OnlyWorlds",
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/OnlyWorlds/sdk.git"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://onlyworlds.github.io/",
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/OnlyWorlds/sdk/issues"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"tsup": "^8.0.1",
|
|
55
|
+
"typescript": "^5.3.3"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"typescript": ">=4.5.0"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=18.0.0"
|
|
62
|
+
}
|
|
63
|
+
}
|