toilscript 0.1.48 → 0.1.50
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/NOTICE +0 -1
- package/dist/cli.js +95 -5
- package/dist/cli.js.map +2 -2
- package/dist/importmap.json +2 -2
- package/dist/web.js +3 -3
- package/package.json +1 -1
- package/std/assembly/bindings/toildb.ts +16 -0
- package/std/assembly/toildb.ts +76 -2
- package/std/assembly/toilscript.d.ts +26 -0
package/dist/importmap.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"imports": {
|
|
3
|
-
"toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.
|
|
4
|
-
"toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.
|
|
3
|
+
"toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.50/dist/toilscript.js",
|
|
4
|
+
"toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.50/dist/cli.js",
|
|
5
5
|
"binaryen": "https://cdn.jsdelivr.net/npm/binaryen@130.0.0-nightly.20260609/index.js",
|
|
6
6
|
"long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
|
|
7
7
|
}
|
package/dist/web.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var ASSEMBLYSCRIPT_VERSION = "0.1.
|
|
1
|
+
var ASSEMBLYSCRIPT_VERSION = "0.1.50";
|
|
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.50/dist/toilscript.js",
|
|
5
|
+
"toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.50/dist/cli.js",
|
|
6
6
|
"binaryen": "https://cdn.jsdelivr.net/npm/binaryen@130.0.0-nightly.20260609/index.js",
|
|
7
7
|
"long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -273,3 +273,19 @@ export namespace toildbHost {
|
|
|
273
273
|
@external("env", "data.write_allowed")
|
|
274
274
|
export declare function writeAllowed(): i32;
|
|
275
275
|
}
|
|
276
|
+
|
|
277
|
+
// Per-domain analytics read. The host stashes a versioned little-endian TenantStats
|
|
278
|
+
// frame in the SAME result buffer the `data.*` ops use, so the guest drains it with
|
|
279
|
+
// `toildbHost.takeResult`. Returns the frame length (>= 0), -2 absent (no caller
|
|
280
|
+
// context / unknown domain), -3 forbidden (a non-dacely caller asked for another domain).
|
|
281
|
+
export namespace analyticsHost {
|
|
282
|
+
// @ts-ignore: decorator
|
|
283
|
+
@external("env", "analytics_read")
|
|
284
|
+
export declare function read(domainPtr: usize, domainLen: i32): i32;
|
|
285
|
+
|
|
286
|
+
// analytics_list_sites(cursor, limit): frame length (count u32 | (u32 nameLen, name)* |
|
|
287
|
+
// has_more u8) stashed for takeResult; -3 forbidden when the caller is not dacely.com.
|
|
288
|
+
// @ts-ignore: decorator
|
|
289
|
+
@external("env", "analytics_list_sites")
|
|
290
|
+
export declare function listSites(cursorPtr: usize, cursorLen: i32, limit: i32): i32;
|
|
291
|
+
}
|
package/std/assembly/toildb.ts
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
// static through a type parameter, but `instantiate<V>()` + `v.decodeInto(buf)`
|
|
14
14
|
// works). Value types must be default-constructible.
|
|
15
15
|
|
|
16
|
-
import { toildbHost } from "bindings/toildb";
|
|
17
|
-
import { DataWriter } from "data";
|
|
16
|
+
import { analyticsHost, toildbHost } from "bindings/toildb";
|
|
17
|
+
import { DataReader, DataWriter } from "data";
|
|
18
18
|
|
|
19
19
|
/// Resolve a `"<db>/<collection>"` name to its numeric host handle. Called once
|
|
20
20
|
/// per collection at module init by the generated `App` binding.
|
|
@@ -438,6 +438,80 @@ export class Counter<K> {
|
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
/// One tenant's analytics snapshot (the metering counters + plan limits), read via the
|
|
442
|
+
/// `Analytics` API. `lifetime` holds the per-domain lifetime totals by metric name
|
|
443
|
+
/// (`requests`, `bytes_served`, `status_2xx`.., `db_ops`, `stream_*`, ...); the request
|
|
444
|
+
/// windows pair the current minute/day usage with the plan cap (cap 0 = unlimited).
|
|
445
|
+
export class TenantStats {
|
|
446
|
+
lifetime: Map<string, i64> = new Map<string, i64>();
|
|
447
|
+
reqMinuteUsed: i64 = 0;
|
|
448
|
+
reqMinuteCap: u64 = 0;
|
|
449
|
+
reqDayUsed: i64 = 0;
|
|
450
|
+
reqDayCap: u64 = 0;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/// A page of site names from `Analytics.listSites` (dacely.com only). When `hasMore` is
|
|
454
|
+
/// true, pass the last `sites` entry back as the next call's cursor.
|
|
455
|
+
export class SiteList {
|
|
456
|
+
sites: string[] = [];
|
|
457
|
+
hasMore: bool = false;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/// Per-domain analytics. A site reads its OWN stats with `Analytics.self()`. The
|
|
461
|
+
/// privileged `dacely.com` domain may read ANY site with `Analytics.site(domain)`; any
|
|
462
|
+
/// other caller gets `null` for a cross-domain read (`null` is also an unknown domain).
|
|
463
|
+
/// The trusted calling domain is decided host-side — the guest cannot forge it.
|
|
464
|
+
export class Analytics {
|
|
465
|
+
private static decode(buf: Uint8Array): TenantStats {
|
|
466
|
+
const r = new DataReader(buf);
|
|
467
|
+
const stats = new TenantStats();
|
|
468
|
+
r.readU16(); // frame version (currently 1)
|
|
469
|
+
const count = r.readU32();
|
|
470
|
+
for (let i: u32 = 0; i < count && r.ok; i++) {
|
|
471
|
+
const name = r.readString();
|
|
472
|
+
stats.lifetime.set(name, r.readI64());
|
|
473
|
+
}
|
|
474
|
+
stats.reqMinuteUsed = r.readI64();
|
|
475
|
+
stats.reqMinuteCap = r.readU64();
|
|
476
|
+
stats.reqDayUsed = r.readI64();
|
|
477
|
+
stats.reqDayCap = r.readU64();
|
|
478
|
+
return stats;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/// This site's own analytics. Returns empty stats if unavailable.
|
|
482
|
+
static self(): TenantStats {
|
|
483
|
+
const status = analyticsHost.read(0, 0);
|
|
484
|
+
if (status < 0) return new TenantStats();
|
|
485
|
+
return Analytics.decode(__toildbTake(status));
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/// Another site's analytics. Only `dacely.com` may call this for a domain other than
|
|
489
|
+
/// its own; every other caller (and an unknown domain) gets `null`.
|
|
490
|
+
static site(domain: string): TenantStats | null {
|
|
491
|
+
const db = Uint8Array.wrap(String.UTF8.encode(domain));
|
|
492
|
+
const status = analyticsHost.read(db.dataStart, db.byteLength);
|
|
493
|
+
if (status < 0) return null;
|
|
494
|
+
return Analytics.decode(__toildbTake(status));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/// Enumerate sites, paginated. ONLY `dacely.com` gets results; any other caller gets an
|
|
498
|
+
/// empty list. `cursor` is the previous page's last name (`""` = from the start); reads up
|
|
499
|
+
/// to `limit` names. When `hasMore` is true, pass the last `sites` entry as the next cursor.
|
|
500
|
+
static listSites(cursor: string = "", limit: i32 = 256): SiteList {
|
|
501
|
+
const cb = Uint8Array.wrap(String.UTF8.encode(cursor));
|
|
502
|
+
const out = new SiteList();
|
|
503
|
+
const status = analyticsHost.listSites(cb.dataStart, cb.byteLength, limit);
|
|
504
|
+
if (status < 0) return out;
|
|
505
|
+
const r = new DataReader(__toildbTake(status));
|
|
506
|
+
const count = r.readU32();
|
|
507
|
+
for (let i: u32 = 0; i < count && r.ok; i++) {
|
|
508
|
+
out.sites.push(r.readString());
|
|
509
|
+
}
|
|
510
|
+
out.hasMore = r.readU8() != 0;
|
|
511
|
+
return out;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
441
515
|
/// An append-only event log (spec 7.5): activity feeds, audit trails, the
|
|
442
516
|
/// fact stream a `@derive` consumes. `V` is the `@data` event type, `K` the
|
|
443
517
|
/// `@data` stream-key type.
|
|
@@ -282,6 +282,32 @@ declare class Events<K, V> {
|
|
|
282
282
|
latest(key: K, limit: i32): V[];
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
/** One tenant's analytics snapshot: per-metric lifetime totals + the request rate
|
|
286
|
+
* windows (current usage paired with the plan cap; cap 0 = unlimited). */
|
|
287
|
+
declare class TenantStats {
|
|
288
|
+
lifetime: Map<string, i64>;
|
|
289
|
+
reqMinuteUsed: i64;
|
|
290
|
+
reqMinuteCap: u64;
|
|
291
|
+
reqDayUsed: i64;
|
|
292
|
+
reqDayCap: u64;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Per-domain analytics. `Analytics.self()` reads this site's own stats; the privileged
|
|
296
|
+
* `dacely.com` domain may read any site via `Analytics.site(domain)` (any other caller,
|
|
297
|
+
* or an unknown domain, gets `null`). The calling domain is decided host-side. */
|
|
298
|
+
/** A page of site names from `Analytics.listSites` (dacely.com only). When `hasMore` is
|
|
299
|
+
* true, pass the last `sites` entry back as the next call's cursor. */
|
|
300
|
+
declare class SiteList {
|
|
301
|
+
sites: string[];
|
|
302
|
+
hasMore: bool;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
declare class Analytics {
|
|
306
|
+
static self(): TenantStats;
|
|
307
|
+
static site(domain: string): TenantStats | null;
|
|
308
|
+
static listSites(cursor?: string, limit?: i32): SiteList;
|
|
309
|
+
}
|
|
310
|
+
|
|
285
311
|
// Big integers, native globals implemented in std/assembly/bignum. The
|
|
286
312
|
// arithmetic/bitwise/comparison operators
|
|
287
313
|
// (+ - * / % & | ^ << >> == != < > <= >=) are operator overloads resolved by
|