@oddington/sdk 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Oddington SDK
2
2
 
3
- The importable client for Oddington routines and response handlers. Requires
4
- Node.js 22.12.0 or later. Installing the package grants no authority.
3
+ The importable client for Oddington apps, routines and response handlers.
4
+ Node operations require Node.js 22.12.0 or later. The root import and hosted
5
+ Data and Files APIs work in browsers. Installing the package grants no authority.
5
6
 
6
7
  ```sh
7
8
  npm install @oddington/sdk
@@ -13,6 +14,138 @@ import { defineHandler, resolveAsk, routinePublicationClient } from '@oddington/
13
14
  const inbox = routinePublicationClient();
14
15
  ```
15
16
 
17
+ The OS-owned browser entry point initializes the existing shared refreshing
18
+ session source before app code runs:
19
+
20
+ ```ts
21
+ import { os } from '@oddington/sdk';
22
+
23
+ os.init({ auth });
24
+ ```
25
+
26
+ This returns `void` and derives context from the current HTTPS workspace origin
27
+ under `oddington.ai`, excluding `auth`. Reinitialization replaces the previous
28
+ session subscription. Workspace existence and member access are checked by the
29
+ OS service. App modules use capability namespaces; routines and handlers receive
30
+ runtime context without calling `os.init`.
31
+
32
+ Create and recover a private immutable original through the same host context:
33
+
34
+ ```ts
35
+ import { files } from '@oddington/sdk';
36
+
37
+ const report = await files.create({
38
+ file: selectedFile, // Web File, path-backed Blob, Uint8Array or byte stream
39
+ name: 'September statement.csv',
40
+ path: 'HSC/2026/09',
41
+ }, { requestKey: 'statement/2026/09' });
42
+ const descriptor = await files.get(report.id);
43
+ const response = await files.read(descriptor.id);
44
+ await response.text(); // Also supports blob(), arrayBuffer() and body streaming.
45
+ ```
46
+
47
+ Hosted Files retains remote originals only, with empty `enrichments`. It rejects
48
+ `local`, `both` and explicit routine local preparation with `unsupported_context`.
49
+ Unnamed inputs require a safe `name`; streams also require declared `size`.
50
+ Blob and byte-array declarations must match their intrinsic size. Originals are
51
+ bounded to 16 MiB, metadata to 4 KiB, and descriptor/error bodies to 16 KiB.
52
+ Creates allow four concurrent buffered operations and a 30-second deadline;
53
+ transport retries at most once with the same prepared bytes and request key.
54
+ Omitting a key generates one for that invocation. Supply a stable key to recover
55
+ across processes or fresh routine runs. Caller inputs remain owned by the caller.
56
+ Each request resolves current authority; routine Files calls go directly to the
57
+ selected workspace's HTTPS OS host. `FileOperationError` exposes a bounded code,
58
+ status and retryability without server details. Reads return the successful Web
59
+ Response without consuming its body. Creation grants private creator access;
60
+ workspace membership alone never grants another creator's File.
61
+
62
+ Read a named repository through the authenticated host context:
63
+
64
+ ```ts
65
+ import { data, DataOperationError } from '@oddington/sdk';
66
+
67
+ const general = data.repository('general');
68
+ const collections = await general.collections.list();
69
+ const schema = await general.collections.schema('invoices');
70
+ const first = await general.records.select({
71
+ invoices: { $: { limit: 50 }, supplier: { $: { fields: ['name'] } } },
72
+ suppliers: {},
73
+ });
74
+ const next = first.$meta.collections.invoices.next;
75
+ if (next) await general.records.select({
76
+ invoices: { $: { limit: 50, after: next }, supplier: { $: { fields: ['name'] } } },
77
+ });
78
+ ```
79
+
80
+ Binding is inert. Each operation resolves current workspace, endpoint and
81
+ short-lived authority from the trusted app host or managed routine context.
82
+ Customer calls cannot configure those values. Missing or expired context
83
+ rejects; a named handle does not expand repository access. During explicit
84
+ `os routine run --local`, the same calls use the matched checkout's committed
85
+ version through a private parent transport. Dirty files are ignored. An OS
86
+ cache outside the checkout reuses derived data; reads require no remote access
87
+ or preparation storage. Later accepted record effects advance the run's view
88
+ to their exact proposed version. Login, installed grants and provider authority
89
+ retain their normal checks. A dead local parent fails without hosted fallback.
90
+
91
+ Each graph selection sends one request and returns only selected canonical
92
+ values, expanded forward links and exact opaque public versions. Cursors
93
+ continue the exact retained artifact and collection selection, even after
94
+ replacement; repeat its options and links while omitting unrelated collections.
95
+ No automatic retry, separate version fetch, search or history operation is
96
+ included. Collection schemas omit Markdown storage hints.
97
+
98
+ `where` combines field conditions with AND. Alongside exact scalar/null equality
99
+ and `$in`, declared one-valued `integer`, `number` and `date` fields accept
100
+ `$gt`, `$gte`, `$lt` and `$lte`:
101
+
102
+ ```ts
103
+ await general.records.select({ invoices: { $: { where: {
104
+ amount: { $gte: 10, $lte: 20 },
105
+ date: { $gte: '2026-10-01', $lt: '2026-11-01' },
106
+ month: { $gte: '2026-10', $lte: '2026-10' },
107
+ }, count: true } } });
108
+ ```
109
+
110
+ Supply one lower bound, one upper bound, or one of each. Bounds cannot combine
111
+ `$gt` with `$gte`, `$lt` with `$lte`, or any bound with `$in`. Operands must be
112
+ valid for the declared field, including numeric precision and real day/month
113
+ dates; values are never coerced. Missing and null values never match bounds.
114
+ A valid interval without matches returns an empty array and requested zero
115
+ count. V0 types check expression structure; runtime schema validation owns field
116
+ eligibility. Repeat the same bounds when continuing a cursor.
117
+
118
+ `DataOperationError.code` distinguishes `context_unavailable`, `unauthenticated`,
119
+ `access_denied`, `invalid_query`, `request_too_large`, `capacity` and `unavailable`.
120
+ For reads, only `capacity` and `unavailable` are retryable; an error never includes private
121
+ server details. Server boundaries own query bounds and authorization.
122
+
123
+ Guarded updates use the same handle in hosted and explicitly local routines:
124
+
125
+ ```ts
126
+ const changes = general.changes();
127
+ changes.update(first.invoices[0], { amount: 30 });
128
+ await changes.validate();
129
+ const publication = await changes.publish();
130
+ ```
131
+
132
+ Preparation captures only the Record's `$ref`, `$version` and explicit set,
133
+ without I/O. Validation checks the complete committed result without effects;
134
+ publication repeats guarded validation and applies the whole update batch.
135
+ Success returns `{ version, created: [], updated: [{ $ref, $version }], deleted: [] }`
136
+ only after its exact index is ready. Later current reads discover that version.
137
+ During `os routine run --local`, publication retains the exact proposal and
138
+ advances only run-local reads. `os routine publish` later applies and indexes
139
+ that immutable proposal; unrelated staged and unstaged work is preserved.
140
+
141
+ `invalid_change` and known-unapplied `conflict` reject the batch.
142
+ `publication_pending` is retryable and may report `uncertain` or `applied`;
143
+ retry the same change set to reconcile its retained identity. A transport failure
144
+ also keeps that identity. Concurrent publication calls coalesce, confirmed calls
145
+ replay the result, and changed intent requires a new change set. Updates are
146
+ bounded to 10,000 Records and the 256 KiB Data request limit. Create, delete,
147
+ `$filing`, search and history are outside this supported Changes slice.
148
+
16
149
  Bind a declared Airtable connection with `connections.airtable('project-management')`
17
150
  from the package root. Import and binding perform no network or credential work.
18
151
  The client exposes `tables.list()` and `records.list`, `get`, `create`, `update`