toilscript 0.1.28 → 0.1.29
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/dist/cli.js +186 -4
- package/dist/cli.js.map +2 -2
- package/dist/importmap.json +2 -2
- package/dist/toilscript.js +2 -2
- package/dist/toilscript.js.map +2 -2
- package/dist/web.js +3 -3
- package/package.json +1 -1
- package/std/assembly/bindings/toildb.ts +61 -0
- package/std/assembly/toildb.ts +121 -0
- package/std/assembly/toilscript.d.ts +96 -0
package/dist/web.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var ASSEMBLYSCRIPT_VERSION = "0.1.
|
|
1
|
+
var ASSEMBLYSCRIPT_VERSION = "0.1.29";
|
|
2
2
|
var ASSEMBLYSCRIPT_IMPORTMAP = {
|
|
3
3
|
"imports": {
|
|
4
|
-
"toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.
|
|
5
|
-
"toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.
|
|
4
|
+
"toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.29/dist/toilscript.js",
|
|
5
|
+
"toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.29/dist/cli.js",
|
|
6
6
|
"binaryen": "https://cdn.jsdelivr.net/npm/binaryen@129.0.0-nightly.20260428/index.js",
|
|
7
7
|
"long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -126,6 +126,67 @@ export namespace toildbHost {
|
|
|
126
126
|
idemPtr: usize
|
|
127
127
|
): i32;
|
|
128
128
|
|
|
129
|
+
// membership.contains -> 1 present | 0 absent | negative error.
|
|
130
|
+
// @ts-ignore: decorator
|
|
131
|
+
@external("env", "data.membership_contains")
|
|
132
|
+
export declare function membershipContains(
|
|
133
|
+
handle: u32, setPtr: usize, setLen: i32, memberPtr: usize, memberLen: i32
|
|
134
|
+
): i32;
|
|
135
|
+
|
|
136
|
+
// membership.add -> 0 ok | negative error.
|
|
137
|
+
// @ts-ignore: decorator
|
|
138
|
+
@external("env", "data.membership_add")
|
|
139
|
+
export declare function membershipAdd(
|
|
140
|
+
handle: u32, setPtr: usize, setLen: i32, memberPtr: usize, memberLen: i32, idemPtr: usize
|
|
141
|
+
): i32;
|
|
142
|
+
|
|
143
|
+
// membership.remove -> 0 ok | negative error.
|
|
144
|
+
// @ts-ignore: decorator
|
|
145
|
+
@external("env", "data.membership_remove")
|
|
146
|
+
export declare function membershipRemove(
|
|
147
|
+
handle: u32, setPtr: usize, setLen: i32, memberPtr: usize, memberLen: i32, idemPtr: usize
|
|
148
|
+
): i32;
|
|
149
|
+
|
|
150
|
+
// membership.list(limit) -> framed-list length (stashed) | negative error.
|
|
151
|
+
// The blob is `u32 count` then per member `u32 len + bytes`.
|
|
152
|
+
// @ts-ignore: decorator
|
|
153
|
+
@external("env", "data.membership_list")
|
|
154
|
+
export declare function membershipList(handle: u32, setPtr: usize, setLen: i32, limit: i32): i32;
|
|
155
|
+
|
|
156
|
+
// capacity.set_total(total: i64) -> 0 ok | negative error (job/derive only).
|
|
157
|
+
// @ts-ignore: decorator
|
|
158
|
+
@external("env", "data.capacity_set_total")
|
|
159
|
+
export declare function capacitySetTotal(
|
|
160
|
+
handle: u32, keyPtr: usize, keyLen: i32, total: i64, idemPtr: usize
|
|
161
|
+
): i32;
|
|
162
|
+
|
|
163
|
+
// capacity.available -> 8 (the i64 available stashed as 8 LE bytes) | neg.
|
|
164
|
+
// @ts-ignore: decorator
|
|
165
|
+
@external("env", "data.capacity_available")
|
|
166
|
+
export declare function capacityAvailable(handle: u32, keyPtr: usize, keyLen: i32): i32;
|
|
167
|
+
|
|
168
|
+
// capacity.reserve(amount: i64, ttl_ms: i64) -> 8 (the u64 reservation id
|
|
169
|
+
// stashed) | -2 insufficient | negative error.
|
|
170
|
+
// @ts-ignore: decorator
|
|
171
|
+
@external("env", "data.capacity_reserve")
|
|
172
|
+
export declare function capacityReserve(
|
|
173
|
+
handle: u32, keyPtr: usize, keyLen: i32, amount: i64, ttlMs: i64, idemPtr: usize
|
|
174
|
+
): i32;
|
|
175
|
+
|
|
176
|
+
// capacity.confirm(reservationId: i64) -> 1 confirmed | 0 unknown | neg.
|
|
177
|
+
// @ts-ignore: decorator
|
|
178
|
+
@external("env", "data.capacity_confirm")
|
|
179
|
+
export declare function capacityConfirm(
|
|
180
|
+
handle: u32, keyPtr: usize, keyLen: i32, reservationId: i64, idemPtr: usize
|
|
181
|
+
): i32;
|
|
182
|
+
|
|
183
|
+
// capacity.cancel(reservationId: i64) -> 1 cancelled | 0 unknown/confirmed | neg.
|
|
184
|
+
// @ts-ignore: decorator
|
|
185
|
+
@external("env", "data.capacity_cancel")
|
|
186
|
+
export declare function capacityCancel(
|
|
187
|
+
handle: u32, keyPtr: usize, keyLen: i32, reservationId: i64, idemPtr: usize
|
|
188
|
+
): i32;
|
|
189
|
+
|
|
129
190
|
// counter.get -> 8 (the i64 sum stashed as 8 LE bytes) | negative error.
|
|
130
191
|
// @ts-ignore: decorator
|
|
131
192
|
@external("env", "data.counter_get")
|
package/std/assembly/toildb.ts
CHANGED
|
@@ -48,6 +48,7 @@ function __toildbTakeGrow(): Uint8Array {
|
|
|
48
48
|
|
|
49
49
|
/// A mutable keyed-entity collection (spec 7.1). `V` is the `@data` value type,
|
|
50
50
|
/// `K` the `@data` key type.
|
|
51
|
+
@global
|
|
51
52
|
export class Record<V, K> {
|
|
52
53
|
private __handle: u32;
|
|
53
54
|
|
|
@@ -154,6 +155,7 @@ export class Record<V, K> {
|
|
|
154
155
|
/// leaderboards, rendered fragments. Read by any function kind; PUBLISHED only
|
|
155
156
|
/// by a `@derive`/`@job` (the host kind gate enforces it). `V` is the `@data`
|
|
156
157
|
/// value type, `K` the `@data` key type.
|
|
158
|
+
@global
|
|
157
159
|
export class View<V, K> {
|
|
158
160
|
private __handle: u32;
|
|
159
161
|
|
|
@@ -192,12 +194,14 @@ export class View<V, K> {
|
|
|
192
194
|
/// The result of a `unique.claim` (spec 8.6). `claimed` is true when the caller
|
|
193
195
|
/// owns the key (a fresh claim or an idempotent re-claim of its own); when
|
|
194
196
|
/// false, `owner` is the value that currently holds the key.
|
|
197
|
+
@global
|
|
195
198
|
export class ClaimResult<V> {
|
|
196
199
|
constructor(public claimed: bool, public owner: V | null) {}
|
|
197
200
|
}
|
|
198
201
|
|
|
199
202
|
/// A globally-unique claim collection (spec 7.6): username, email, slug, ...
|
|
200
203
|
/// `V` is the `@data` OWNER value type, `K` the `@data` claim-key type.
|
|
204
|
+
@global
|
|
201
205
|
export class Unique<V, K> {
|
|
202
206
|
private __handle: u32;
|
|
203
207
|
|
|
@@ -244,9 +248,125 @@ export class Unique<V, K> {
|
|
|
244
248
|
}
|
|
245
249
|
}
|
|
246
250
|
|
|
251
|
+
/// An unordered set (spec 7.3): followers, tags, ACLs, room members. `M` is the
|
|
252
|
+
/// `@data` member type, `K` the `@data` set-key type.
|
|
253
|
+
@global
|
|
254
|
+
export class Membership<M, K> {
|
|
255
|
+
private __handle: u32;
|
|
256
|
+
|
|
257
|
+
constructor(handle: u32) {
|
|
258
|
+
this.__handle = handle;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/// Whether `member` is in the set keyed by `key`.
|
|
262
|
+
contains(key: K, member: M): bool {
|
|
263
|
+
const kb = key.encode();
|
|
264
|
+
const mb = member.encode();
|
|
265
|
+
return toildbHost.membershipContains(
|
|
266
|
+
this.__handle, kb.dataStart, kb.byteLength, mb.dataStart, mb.byteLength
|
|
267
|
+
) == 1;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/// Add `member` to the set (idempotent).
|
|
271
|
+
add(key: K, member: M): void {
|
|
272
|
+
const kb = key.encode();
|
|
273
|
+
const mb = member.encode();
|
|
274
|
+
toildbHost.membershipAdd(
|
|
275
|
+
this.__handle, kb.dataStart, kb.byteLength, mb.dataStart, mb.byteLength, 0
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/// Remove `member` from the set (idempotent).
|
|
280
|
+
remove(key: K, member: M): void {
|
|
281
|
+
const kb = key.encode();
|
|
282
|
+
const mb = member.encode();
|
|
283
|
+
toildbHost.membershipRemove(
|
|
284
|
+
this.__handle, kb.dataStart, kb.byteLength, mb.dataStart, mb.byteLength, 0
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/// Up to `limit` members of the set. Decodes each framed member into an `M`.
|
|
289
|
+
list(key: K, limit: i32): M[] {
|
|
290
|
+
const kb = key.encode();
|
|
291
|
+
const status = toildbHost.membershipList(this.__handle, kb.dataStart, kb.byteLength, limit);
|
|
292
|
+
if (status < 0) unreachable();
|
|
293
|
+
const blob = __toildbTake(status);
|
|
294
|
+
const out = new Array<M>();
|
|
295
|
+
let off: i32 = 0;
|
|
296
|
+
const count = load<u32>(blob.dataStart + off);
|
|
297
|
+
off += 4;
|
|
298
|
+
for (let i: u32 = 0; i < count; i++) {
|
|
299
|
+
const len = <i32>load<u32>(blob.dataStart + off);
|
|
300
|
+
off += 4;
|
|
301
|
+
const m = instantiate<M>();
|
|
302
|
+
m.decodeInto(blob.subarray(off, off + len));
|
|
303
|
+
out.push(m);
|
|
304
|
+
off += len;
|
|
305
|
+
}
|
|
306
|
+
return out;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/// A finite, strongly-consistent resource (spec 7.7): limited stock, seats,
|
|
311
|
+
/// rate grants. Reserve/confirm/cancel two-phase holds prevent oversell. `K` is
|
|
312
|
+
/// the `@data` key type (the value is the host-owned escrow ledger).
|
|
313
|
+
@global
|
|
314
|
+
export class Capacity<K> {
|
|
315
|
+
private __handle: u32;
|
|
316
|
+
|
|
317
|
+
constructor(handle: u32) {
|
|
318
|
+
this.__handle = handle;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/// Units available to reserve right now.
|
|
322
|
+
available(key: K): i64 {
|
|
323
|
+
const kb = key.encode();
|
|
324
|
+
const status = toildbHost.capacityAvailable(this.__handle, kb.dataStart, kb.byteLength);
|
|
325
|
+
if (status < 0) unreachable();
|
|
326
|
+
return load<i64>(__toildbTake(status).dataStart);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/// Hold `amount` for `ttlMs` (it auto-releases if not confirmed in time).
|
|
330
|
+
/// Returns the reservation id (> 0), or 0 if there was not enough available
|
|
331
|
+
/// (no oversell).
|
|
332
|
+
reserve(key: K, amount: i64, ttlMs: i64): u64 {
|
|
333
|
+
const kb = key.encode();
|
|
334
|
+
const status = toildbHost.capacityReserve(
|
|
335
|
+
this.__handle, kb.dataStart, kb.byteLength, amount, ttlMs, 0
|
|
336
|
+
);
|
|
337
|
+
if (status == -2) return 0; // insufficient
|
|
338
|
+
if (status < 0) unreachable();
|
|
339
|
+
return load<u64>(__toildbTake(status).dataStart);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/// Finalize a hold into a permanent consume. Returns whether the id was valid.
|
|
343
|
+
confirm(key: K, reservationId: u64): bool {
|
|
344
|
+
const kb = key.encode();
|
|
345
|
+
return toildbHost.capacityConfirm(
|
|
346
|
+
this.__handle, kb.dataStart, kb.byteLength, reservationId as i64, 0
|
|
347
|
+
) == 1;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/// Release a hold back to available (a confirmed sale cannot be cancelled).
|
|
351
|
+
cancel(key: K, reservationId: u64): bool {
|
|
352
|
+
const kb = key.encode();
|
|
353
|
+
return toildbHost.capacityCancel(
|
|
354
|
+
this.__handle, kb.dataStart, kb.byteLength, reservationId as i64, 0
|
|
355
|
+
) == 1;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/// Set the ceiling (restock / reduce). `@job`/`@derive` only; the kind gate
|
|
359
|
+
/// (compile + runtime) enforces it.
|
|
360
|
+
setTotal(key: K, total: i64): void {
|
|
361
|
+
const kb = key.encode();
|
|
362
|
+
toildbHost.capacitySetTotal(this.__handle, kb.dataStart, kb.byteLength, total, 0);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
247
366
|
/// A commutative integer counter (spec 7.4): likes, view counts, inventory.
|
|
248
367
|
/// `K` is the `@data` key type; the value is a host-aggregated i64 rollup (there
|
|
249
368
|
/// is no `set`, only `add` and `get`, so concurrent deltas never lose writes).
|
|
369
|
+
@global
|
|
250
370
|
export class Counter<K> {
|
|
251
371
|
private __handle: u32;
|
|
252
372
|
|
|
@@ -273,6 +393,7 @@ export class Counter<K> {
|
|
|
273
393
|
/// An append-only event log (spec 7.5): activity feeds, audit trails, the
|
|
274
394
|
/// fact stream a `@derive` consumes. `V` is the `@data` event type, `K` the
|
|
275
395
|
/// `@data` stream-key type.
|
|
396
|
+
@global
|
|
276
397
|
export class Events<V, K> {
|
|
277
398
|
private __handle: u32;
|
|
278
399
|
|
|
@@ -85,6 +85,102 @@ declare function auth(target: Object, propertyKey: string | symbol, descriptor:
|
|
|
85
85
|
/** Declare the authenticated-user type (`@user class User { ... }`); enables `AuthService.getUser()`. */
|
|
86
86
|
declare function user(target: Function): void;
|
|
87
87
|
|
|
88
|
+
// --- ToilDB (@database / @collection + the @query/@action/... function kinds),
|
|
89
|
+
// handled natively by the compiler; typed here so editors accept the bare forms ---
|
|
90
|
+
|
|
91
|
+
/** Marks a class as a ToilDB database: each `@collection` field becomes a typed,
|
|
92
|
+
* lazily-resolved collection handle (`App.users.get(...)`). */
|
|
93
|
+
declare function database(target: Function): void;
|
|
94
|
+
|
|
95
|
+
/** Declares a `@database` field as a collection - a `Record`/`View`/`Unique`/
|
|
96
|
+
* `Counter`/`Events`/`Membership`/`Capacity` handle. */
|
|
97
|
+
declare function collection(target: Object, propertyKey: string | symbol): void;
|
|
98
|
+
|
|
99
|
+
/** ToilDB function kinds (spec 6) - the data ops a function may issue. `@query`
|
|
100
|
+
* is read-only; `@action` adds bounded writes/claims; `@derive` publishes
|
|
101
|
+
* views/rollups; `@job` is background work; `@admin` is control-plane only. The
|
|
102
|
+
* compiler enforces the family x kind matrix (a `@query` calling `.patch` is a
|
|
103
|
+
* compile error). */
|
|
104
|
+
declare function query(target: Function): void;
|
|
105
|
+
declare function action(target: Function): void;
|
|
106
|
+
declare function job(target: Function): void;
|
|
107
|
+
declare function derive(target: Function): void;
|
|
108
|
+
declare function admin(target: Function): void;
|
|
109
|
+
|
|
110
|
+
// The ToilDB collection HANDLES are ambient globals (no import) - the compiler
|
|
111
|
+
// provides them (`std/assembly/toildb`, `@global`); these typings let editors
|
|
112
|
+
// recognize `@collection users!: Record<User, UserId>` and `App.users.get(...)`.
|
|
113
|
+
// `K`/`V`/`M` are `@data` types (the binary codec the host marshals).
|
|
114
|
+
|
|
115
|
+
/** A mutable keyed-entity collection (spec 7.1): user profiles, items, sessions. */
|
|
116
|
+
declare class Record<V, K> {
|
|
117
|
+
get(key: K): V | null;
|
|
118
|
+
require(key: K): V;
|
|
119
|
+
exists(key: K): bool;
|
|
120
|
+
getMany(keys: K[]): (V | null)[];
|
|
121
|
+
create(key: K, value: V): bool;
|
|
122
|
+
patch(key: K, value: V): V;
|
|
123
|
+
delete(key: K): void;
|
|
124
|
+
getDelete(key: K): V | null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** A precomputed, read-optimized projection (spec 7.2): pages, leaderboards. */
|
|
128
|
+
declare class View<V, K> {
|
|
129
|
+
get(key: K): V | null;
|
|
130
|
+
require(key: K): V;
|
|
131
|
+
publish(key: K, value: V): void;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** The result of a `unique.claim` (spec 8.6). */
|
|
135
|
+
declare class ClaimResult<V> {
|
|
136
|
+
claimed: bool;
|
|
137
|
+
owner: V | null;
|
|
138
|
+
constructor(claimed: bool, owner: V | null);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** A globally-unique claim collection (spec 7.6): usernames, emails, slugs. */
|
|
142
|
+
declare class Unique<V, K> {
|
|
143
|
+
lookup(key: K): V | null;
|
|
144
|
+
claim(key: K, value: V): ClaimResult<V>;
|
|
145
|
+
release(key: K, value: V): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** An unordered set (spec 7.3): followers, tags, ACLs, room members. */
|
|
149
|
+
declare class Membership<M, K> {
|
|
150
|
+
contains(key: K, member: M): bool;
|
|
151
|
+
add(key: K, member: M): void;
|
|
152
|
+
remove(key: K, member: M): void;
|
|
153
|
+
list(key: K, limit: i32): M[];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** A finite, strongly-consistent resource via escrow (spec 7.7): stock, seats. */
|
|
157
|
+
declare class Capacity<K> {
|
|
158
|
+
available(key: K): i64;
|
|
159
|
+
reserve(key: K, amount: i64, ttlMs: i64): u64;
|
|
160
|
+
confirm(key: K, reservationId: u64): bool;
|
|
161
|
+
cancel(key: K, reservationId: u64): bool;
|
|
162
|
+
setTotal(key: K, total: i64): void;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** A commutative integer counter (spec 7.4): likes, view counts, inventory. */
|
|
166
|
+
declare class Counter<K> {
|
|
167
|
+
get(key: K): i64;
|
|
168
|
+
add(key: K, delta: i64): void;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** An append-only event log (spec 7.5): activity feeds, audit trails. */
|
|
172
|
+
declare class Events<V, K> {
|
|
173
|
+
append(key: K, event: V): void;
|
|
174
|
+
latest(key: K, limit: i32): V[];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// The handles are ambient (no import needed), but `import { Counter } from
|
|
178
|
+
// 'toildb'` is also accepted for editors that prefer explicit imports - it just
|
|
179
|
+
// re-exports the same globals.
|
|
180
|
+
declare module 'toildb' {
|
|
181
|
+
export { Record, View, Unique, ClaimResult, Membership, Capacity, Counter, Events };
|
|
182
|
+
}
|
|
183
|
+
|
|
88
184
|
// Big integers, native globals implemented in std/assembly/bignum. The
|
|
89
185
|
// arithmetic/bitwise/comparison operators
|
|
90
186
|
// (+ - * / % & | ^ << >> == != < > <= >=) are operator overloads resolved by
|