@vantail/api 0.1.3 → 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.
@@ -0,0 +1,123 @@
1
+ import { type BinaryInput } from "./binary.js";
2
+ /** Everything SQLite can hold, as JavaScript sees it. */
3
+ export type DatabaseValue = null | number | bigint | string | Uint8Array;
4
+ /** What a statement can be given. Booleans are stored as 0 and 1. */
5
+ export type DatabaseParam = DatabaseValue | boolean | BinaryInput;
6
+ export type DatabaseRow = Record<string, DatabaseValue>;
7
+ export interface StatementOptions {
8
+ /**
9
+ * Read every INTEGER as a `bigint`.
10
+ *
11
+ * Without it an integer that a JavaScript number cannot hold exactly is an
12
+ * error rather than a rounded answer - which is the point. SQLite's INTEGER
13
+ * is 64-bit and a JavaScript number is a double, so anything past
14
+ * 2^53 silently loses its low bits; for a balance in minor units, that is
15
+ * money. Turn this on for tables whose ids or amounts can get large, and
16
+ * the numbers come back exact.
17
+ */
18
+ bigint?: boolean;
19
+ }
20
+ export interface DatabaseExecuteResult {
21
+ /** Rows inserted, updated or deleted. */
22
+ changes: number;
23
+ /** Only meaningful straight after an INSERT. */
24
+ lastInsertRowId: number | bigint;
25
+ }
26
+ /** The statements inside a `transaction` callback. */
27
+ export interface Transaction {
28
+ query<Row extends DatabaseRow = DatabaseRow>(sql: string, params?: DatabaseParam[], options?: StatementOptions): Promise<Row[]>;
29
+ execute(sql: string, params?: DatabaseParam[], options?: StatementOptions): Promise<DatabaseExecuteResult>;
30
+ }
31
+ export interface Database {
32
+ /** The handle the runtime knows this connection by. */
33
+ readonly id: number;
34
+ /** The file, resolved - `$APPDATA` and friends already expanded. */
35
+ readonly path: string;
36
+ /** Rows back. */
37
+ query<Row extends DatabaseRow = DatabaseRow>(sql: string, params?: DatabaseParam[], options?: StatementOptions): Promise<Row[]>;
38
+ /** No rows; a count of what changed. */
39
+ execute(sql: string, params?: DatabaseParam[], options?: StatementOptions): Promise<DatabaseExecuteResult>;
40
+ /**
41
+ * Run several statements atomically.
42
+ *
43
+ * Committed when `run` resolves, rolled back when it throws. SQLite has one
44
+ * write transaction per connection and so does this: callers that overlap
45
+ * wait their turn rather than joining an open `BEGIN`, because sharing one
46
+ * means a rollback in either discards the other's writes.
47
+ *
48
+ * Do only database work inside `run`. The transaction holds the connection
49
+ * for as long as the callback takes, and a transaction left idle for 30
50
+ * seconds is rolled back so a callback that never settles cannot wedge the
51
+ * connection for the life of the process.
52
+ *
53
+ * ```ts
54
+ * await db.transaction(async (tx) => {
55
+ * await tx.execute("update account set minor = minor - ? where id = ?", [amount, from]);
56
+ * await tx.execute("update account set minor = minor + ? where id = ?", [amount, to]);
57
+ * });
58
+ * ```
59
+ */
60
+ transaction<T>(run: (tx: Transaction) => Promise<T>): Promise<T>;
61
+ /**
62
+ * Fold the write-ahead log back into the database file.
63
+ *
64
+ * Worth doing before copying the file out by hand. `snapshot` does not need
65
+ * it - SQLite's backup API takes care of itself.
66
+ */
67
+ checkpoint(): Promise<null>;
68
+ /**
69
+ * Write a consistent copy to another path, which must also be writable.
70
+ *
71
+ * SQLite's own backup API, not a file copy: it is safe to call while the
72
+ * database is being written to, which `filesystem.copy` is not.
73
+ */
74
+ snapshot(path: string): Promise<{
75
+ path: string;
76
+ }>;
77
+ close(): Promise<null>;
78
+ }
79
+ export interface OpenOptions {
80
+ /** Where the file lives. Needs `filesystem.write` scope, or read for `readOnly`. */
81
+ path: string;
82
+ /** Open an existing database without being able to change it. */
83
+ readOnly?: boolean;
84
+ }
85
+ /**
86
+ * SQLite, from the runtime.
87
+ *
88
+ * A webview can run SQLite compiled to WebAssembly, and applications do. What
89
+ * it cannot do is give the database anywhere real to live: persisting it means
90
+ * writing the whole file out on every commit, and keeping it in the origin's
91
+ * private storage instead means the user cannot find, copy or back up their
92
+ * own data. This is the same file, written by SQLite itself - journalled,
93
+ * incremental, and sitting in a directory the config granted.
94
+ *
95
+ * ```ts
96
+ * import { database, os, path } from "@vantail/api";
97
+ *
98
+ * const db = await database.open({
99
+ * path: path.join(await os.appDataDir(), "ledger.sqlite"),
100
+ * });
101
+ *
102
+ * await db.execute(
103
+ * "create table if not exists entry(id integer primary key, minor integer not null)",
104
+ * );
105
+ * const rows = await db.query<{ id: number; minor: bigint }>(
106
+ * "select id, minor from entry where minor > ?",
107
+ * [0],
108
+ * { bigint: true },
109
+ * );
110
+ * ```
111
+ *
112
+ * Connections are opened with WAL journalling, `synchronous = NORMAL` and
113
+ * `foreign_keys = ON`, so a declared foreign key is actually enforced - SQLite
114
+ * leaves that off by default for compatibility with 2005.
115
+ *
116
+ * There is no encryption. `secrets` will hold a key, but there is nothing here
117
+ * to give it to; say so plainly in your UI rather than showing a padlock that
118
+ * means nothing.
119
+ */
120
+ export declare const database: {
121
+ open: (options: OpenOptions) => Promise<Database>;
122
+ };
123
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/D,yDAAyD;AACzD,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAEzE,qEAAqE;AACrE,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,OAAO,GAAG,WAAW,CAAC;AAElE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;CAClC;AAED,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,GAAG,SAAS,WAAW,GAAG,WAAW,EACzC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,aAAa,EAAE,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClB,OAAO,CACL,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,aAAa,EAAE,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,QAAQ;IACvB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,iBAAiB;IACjB,KAAK,CAAC,GAAG,SAAS,WAAW,GAAG,WAAW,EACzC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,aAAa,EAAE,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAElB,wCAAwC;IACxC,OAAO,CACL,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,aAAa,EAAE,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAElC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAEjE;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAElD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,QAAQ;IACnB,IAAI,YAAkB,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC;CAOtD,CAAC"}
@@ -0,0 +1,127 @@
1
+ import { decode, encode } from "./binary.js";
2
+ import { invoke } from "./transport.js";
3
+ /**
4
+ * SQLite, from the runtime.
5
+ *
6
+ * A webview can run SQLite compiled to WebAssembly, and applications do. What
7
+ * it cannot do is give the database anywhere real to live: persisting it means
8
+ * writing the whole file out on every commit, and keeping it in the origin's
9
+ * private storage instead means the user cannot find, copy or back up their
10
+ * own data. This is the same file, written by SQLite itself - journalled,
11
+ * incremental, and sitting in a directory the config granted.
12
+ *
13
+ * ```ts
14
+ * import { database, os, path } from "@vantail/api";
15
+ *
16
+ * const db = await database.open({
17
+ * path: path.join(await os.appDataDir(), "ledger.sqlite"),
18
+ * });
19
+ *
20
+ * await db.execute(
21
+ * "create table if not exists entry(id integer primary key, minor integer not null)",
22
+ * );
23
+ * const rows = await db.query<{ id: number; minor: bigint }>(
24
+ * "select id, minor from entry where minor > ?",
25
+ * [0],
26
+ * { bigint: true },
27
+ * );
28
+ * ```
29
+ *
30
+ * Connections are opened with WAL journalling, `synchronous = NORMAL` and
31
+ * `foreign_keys = ON`, so a declared foreign key is actually enforced - SQLite
32
+ * leaves that off by default for compatibility with 2005.
33
+ *
34
+ * There is no encryption. `secrets` will hold a key, but there is nothing here
35
+ * to give it to; say so plainly in your UI rather than showing a padlock that
36
+ * means nothing.
37
+ */
38
+ export const database = {
39
+ open: async (options) => {
40
+ const opened = await invoke("database.open", options);
41
+ return connect(opened.id, opened.path);
42
+ },
43
+ };
44
+ function connect(id, path) {
45
+ const query = async (sql, params = [], options = {}, transaction) => {
46
+ const result = await invoke("database.query", {
47
+ id,
48
+ sql,
49
+ params: params.map(toWire),
50
+ bigint: options.bigint === true,
51
+ ...(transaction === undefined ? {} : { transaction }),
52
+ });
53
+ return result.rows.map(fromWireRow);
54
+ };
55
+ const execute = async (sql, params = [], options = {}, transaction) => {
56
+ const result = await invoke("database.execute", {
57
+ id,
58
+ sql,
59
+ params: params.map(toWire),
60
+ bigint: options.bigint === true,
61
+ ...(transaction === undefined ? {} : { transaction }),
62
+ });
63
+ return {
64
+ changes: result.changes,
65
+ lastInsertRowId: fromWire(result.lastInsertRowId),
66
+ };
67
+ };
68
+ return {
69
+ id,
70
+ path,
71
+ query: (sql, params, options) => query(sql, params, options),
72
+ execute: (sql, params, options) => execute(sql, params, options),
73
+ async transaction(run) {
74
+ const { transaction } = await invoke("database.begin", { id });
75
+ let result;
76
+ try {
77
+ result = await run({
78
+ query: (sql, params, options) => query(sql, params, options, transaction),
79
+ execute: (sql, params, options) => execute(sql, params, options, transaction),
80
+ });
81
+ }
82
+ catch (cause) {
83
+ // Rolling back must not replace the error that caused it - the
84
+ // application needs to see why its work was abandoned.
85
+ await invoke("database.rollback", { id, transaction }).catch(() => { });
86
+ throw cause;
87
+ }
88
+ await invoke("database.commit", { id, transaction });
89
+ return result;
90
+ },
91
+ checkpoint: () => invoke("database.checkpoint", { id }),
92
+ snapshot: (to) => invoke("database.snapshot", { id, path: to }),
93
+ close: () => invoke("database.close", { id }),
94
+ };
95
+ }
96
+ /**
97
+ * JSON has no 64-bit integer and no byte string, so both are tagged.
98
+ *
99
+ * The alternative - numbers for everything - is what silently truncates a
100
+ * balance, so the tag is the point rather than an inconvenience.
101
+ */
102
+ function toWire(value) {
103
+ if (typeof value === "bigint")
104
+ return { $bigint: value.toString() };
105
+ if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
106
+ return { $blob: encode(value) };
107
+ }
108
+ return value;
109
+ }
110
+ function fromWire(value) {
111
+ if (value !== null && typeof value === "object") {
112
+ const tagged = value;
113
+ if (typeof tagged.$bigint === "string")
114
+ return BigInt(tagged.$bigint);
115
+ if (typeof tagged.$blob === "string")
116
+ return decode(tagged.$blob);
117
+ }
118
+ return value;
119
+ }
120
+ function fromWireRow(row) {
121
+ const out = {};
122
+ for (const [column, value] of Object.entries(row)) {
123
+ out[column] = fromWire(value);
124
+ }
125
+ return out;
126
+ }
127
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -14,16 +14,18 @@
14
14
  export { app, type AppInfo, type ProgressOptions, type ProgressState, } from "./app.js";
15
15
  export { autostart } from "./autostart.js";
16
16
  export { clipboard, type ClipboardImage } from "./clipboard.js";
17
+ export { database, type Database, type DatabaseParam, type DatabaseRow, type DatabaseValue, type DatabaseExecuteResult, type OpenOptions as DatabaseOpenOptions, type StatementOptions, type Transaction, } from "./database.js";
17
18
  export { deepLink } from "./deeplink.js";
18
19
  export { fileDrop, type DropEvent } from "./drop.js";
19
20
  export { dialog, type ConfirmOptions, type FileFilter, type MessageOptions, type OpenOptions, type SaveOptions, } from "./dialog.js";
20
21
  export { filesystem, type DirEntry, type FileChange, type FileInfo, type Watch, } from "./filesystem.js";
21
22
  export { hid, type HidConnection, type HidDeviceInfo } from "./hid.js";
22
23
  export { mdns, type DiscoveredService, type DiscoverOptions } from "./mdns.js";
23
- export { menu, type MenuItem, type PredefinedMenuItem } from "./menu.js";
24
- export { network, type NetworkRequestOptions, type NetworkResponse, } from "./network.js";
24
+ export { menu, type MenuInstalled, type MenuItem, type PredefinedMenuItem, } from "./menu.js";
25
+ export { network, type NetworkRedirect, type NetworkRequestOptions, type NetworkResponse, type NetworkSocket, type NetworkSocketClosed, type NetworkSocketOptions, type NetworkStream, type NetworkStreamEnd, type NetworkStreamHead, type NetworkTiming, } from "./network.js";
25
26
  export { notification, type NotificationOptions } from "./notification.js";
26
27
  export { os, type OsInfo, type Platform } from "./os.js";
28
+ export { path, type PathApi } from "./path.js";
27
29
  export { process, type Child, type ExecuteOptions, type ExecuteResult, type ExitEvent, type RunOptions, } from "./process.js";
28
30
  export { screen, type Screen } from "./screen.js";
29
31
  export { power } from "./power.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -14,16 +14,18 @@
14
14
  export { app, } from "./app.js";
15
15
  export { autostart } from "./autostart.js";
16
16
  export { clipboard } from "./clipboard.js";
17
+ export { database, } from "./database.js";
17
18
  export { deepLink } from "./deeplink.js";
18
19
  export { fileDrop } from "./drop.js";
19
20
  export { dialog, } from "./dialog.js";
20
21
  export { filesystem, } from "./filesystem.js";
21
22
  export { hid } from "./hid.js";
22
23
  export { mdns } from "./mdns.js";
23
- export { menu } from "./menu.js";
24
+ export { menu, } from "./menu.js";
24
25
  export { network, } from "./network.js";
25
26
  export { notification } from "./notification.js";
26
27
  export { os } from "./os.js";
28
+ export { path } from "./path.js";
27
29
  export { process, } from "./process.js";
28
30
  export { screen } from "./screen.js";
29
31
  export { power } from "./power.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,GAAG,GAIJ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAuB,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAkB,MAAM,WAAW,CAAC;AACrD,OAAO,EACL,MAAM,GAMP,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,GAKX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,GAAG,EAA0C,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,IAAI,EAAgD,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,IAAI,EAA0C,MAAM,WAAW,CAAC;AACzE,OAAO,EACL,OAAO,GAGR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAA4B,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,EAAE,EAA8B,MAAM,SAAS,CAAC;AACzD,OAAO,EACL,OAAO,GAMR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,MAAM,EAAe,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAuC,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAoC,MAAM,WAAW,CAAC;AACnE,OAAO,EACL,OAAO,GAMR,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,SAAS,IAAI,MAAM,EACnB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,cAAc,EACd,eAAe,EACf,aAAa,GAMd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAoB,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,MAAM,EACN,SAAS,EACT,MAAM,EACN,cAAc,EACd,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,GAAG,GAIJ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAuB,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,QAAQ,GAST,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAkB,MAAM,WAAW,CAAC;AACrD,OAAO,EACL,MAAM,GAMP,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,GAKX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,GAAG,EAA0C,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,IAAI,EAAgD,MAAM,WAAW,CAAC;AAC/E,OAAO,EACL,IAAI,GAIL,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,OAAO,GAWR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAA4B,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,EAAE,EAA8B,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,IAAI,EAAgB,MAAM,WAAW,CAAC;AAC/C,OAAO,EACL,OAAO,GAMR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,MAAM,EAAe,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAuC,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAoC,MAAM,WAAW,CAAC;AACnE,OAAO,EACL,OAAO,GAMR,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,SAAS,IAAI,MAAM,EACnB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,cAAc,EACd,eAAe,EACf,aAAa,GAMd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAoB,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,MAAM,EACN,SAAS,EACT,MAAM,EACN,cAAc,EACd,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
package/dist/menu.d.ts CHANGED
@@ -26,6 +26,18 @@ export type MenuItem = {
26
26
  label?: string;
27
27
  };
28
28
  export type PredefinedMenuItem = "separator" | "copy" | "cut" | "paste" | "selectAll" | "undo" | "redo" | "minimize" | "maximize" | "fullscreen" | "hide" | "hideOthers" | "showAll" | "closeWindow" | "quit" | "about" | "services" | "bringAllToFront";
29
+ /**
30
+ * What the platform would not accept, and therefore what is missing from the
31
+ * menu that was installed.
32
+ *
33
+ * One mistyped accelerator used to cost the whole menu, which on macOS means
34
+ * losing Cmd-C, Cmd-V, Cmd-Q and Cmd-W along with it - those shortcuts exist
35
+ * only as menu items. The offending item is now left out instead, and named
36
+ * here. `skipped` is empty in the ordinary case.
37
+ */
38
+ export interface MenuInstalled {
39
+ skipped: string[];
40
+ }
29
41
  /**
30
42
  * The application menu.
31
43
  *
@@ -52,7 +64,7 @@ export type PredefinedMenuItem = "separator" | "copy" | "cut" | "paste" | "selec
52
64
  * ```
53
65
  */
54
66
  export declare const menu: {
55
- set: (items: MenuItem[]) => Promise<null>;
67
+ set: (items: MenuItem[]) => Promise<MenuInstalled>;
56
68
  remove: () => Promise<null>;
57
69
  setEnabled: (id: string, enabled: boolean) => Promise<null>;
58
70
  setLabel: (id: string, label: string) => Promise<null>;
@@ -1 +1 @@
1
- {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAEA,iDAAiD;AACjD,MAAM,MAAM,QAAQ,GAChB;IACE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,MAAM,GACN,KAAK,GACL,OAAO,GACP,WAAW,GACX,MAAM,GACN,MAAM,GACN,UAAU,GACV,UAAU,GACV,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,SAAS,GACT,aAAa,GACb,MAAM,GACN,OAAO,GACP,UAAU,GACV,iBAAiB,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,IAAI;IACf,GAAG,UAAU,QAAQ,EAAE;IAEvB,MAAM;IAEN,UAAU,OAAO,MAAM,WAAW,OAAO;IAEzC,QAAQ,OAAO,MAAM,SAAS,MAAM;IAEpC,UAAU,OAAO,MAAM,WAAW,OAAO;IAEzC,SAAS,OAAO,MAAM;IAEtB;;;OAGG;IACH,KAAK,UACI,QAAQ,EAAE,YACR;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAGrD,gFAAgF;IAChF,OAAO,YAAY,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI;CAEnD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAOvD"}
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAEA,iDAAiD;AACjD,MAAM,MAAM,QAAQ,GAChB;IACE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,MAAM,GACN,KAAK,GACL,OAAO,GACP,WAAW,GACX,MAAM,GACN,MAAM,GACN,UAAU,GACV,UAAU,GACV,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,SAAS,GACT,aAAa,GACb,MAAM,GACN,OAAO,GACP,UAAU,GACV,iBAAiB,CAAC;AAEtB;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,IAAI;IACf,GAAG,UAAU,QAAQ,EAAE;IAEvB,MAAM;IAEN,UAAU,OAAO,MAAM,WAAW,OAAO;IAEzC,QAAQ,OAAO,MAAM,SAAS,MAAM;IAEpC,UAAU,OAAO,MAAM,WAAW,OAAO;IAEzC,SAAS,OAAO,MAAM;IAEtB;;;OAGG;IACH,KAAK,UACI,QAAQ,EAAE,YACR;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAGrD,gFAAgF;IAChF,OAAO,YAAY,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI;CAEnD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAOvD"}
package/dist/menu.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA4ChD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,GAAG,EAAE,CAAC,KAAiB,EAAE,EAAE,CACzB,MAAM,CAAO,UAAU,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACvD,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAO,aAAa,CAAC;IAEzC,UAAU,EAAE,CAAC,EAAU,EAAE,OAAgB,EAAE,EAAE,CAC3C,MAAM,CAAO,iBAAiB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IAClD,QAAQ,EAAE,CAAC,EAAU,EAAE,KAAa,EAAE,EAAE,CACtC,MAAM,CAAO,eAAe,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IAC9C,UAAU,EAAE,CAAC,EAAU,EAAE,OAAgB,EAAE,EAAE,CAC3C,MAAM,CAAO,iBAAiB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IAClD,SAAS,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAU,gBAAgB,EAAE,EAAE,EAAE,EAAE,CAAC;IAEpE;;;OAGG;IACH,KAAK,EAAE,CACL,KAAiB,EACjB,OAAO,GAA+C,EAAE,EACxD,EAAE,CAAC,MAAM,CAAO,YAAY,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAExE,gFAAgF;IAChF,OAAO,EAAE,CAAC,OAAwC,EAAE,EAAE,CACpD,MAAM,CAAiB,YAAY,EAAE,OAAO,CAAC;CAChD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,EAEtC,CAAC;QACF,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAyDhD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,GAAG,EAAE,CAAC,KAAiB,EAAE,EAAE,CACzB,MAAM,CAAgB,UAAU,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAChE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAO,aAAa,CAAC;IAEzC,UAAU,EAAE,CAAC,EAAU,EAAE,OAAgB,EAAE,EAAE,CAC3C,MAAM,CAAO,iBAAiB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IAClD,QAAQ,EAAE,CAAC,EAAU,EAAE,KAAa,EAAE,EAAE,CACtC,MAAM,CAAO,eAAe,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IAC9C,UAAU,EAAE,CAAC,EAAU,EAAE,OAAgB,EAAE,EAAE,CAC3C,MAAM,CAAO,iBAAiB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IAClD,SAAS,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,MAAM,CAAU,gBAAgB,EAAE,EAAE,EAAE,EAAE,CAAC;IAEpE;;;OAGG;IACH,KAAK,EAAE,CACL,KAAiB,EACjB,OAAO,GAA+C,EAAE,EACxD,EAAE,CAAC,MAAM,CAAO,YAAY,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAExE,gFAAgF;IAChF,OAAO,EAAE,CAAC,OAAwC,EAAE,EAAE,CACpD,MAAM,CAAiB,YAAY,EAAE,OAAO,CAAC;CAChD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,EAEtC,CAAC;QACF,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/network.d.ts CHANGED
@@ -13,6 +13,46 @@ export interface NetworkRequestOptions {
13
13
  timeoutMs?: number;
14
14
  /** Default 5. Every hop is permission-checked. */
15
15
  maxRedirects?: number;
16
+ /**
17
+ * Abandon the request, the way `fetch` does.
18
+ *
19
+ * Aborting rejects this call at once with a `CANCELLED` `VantailError`. It
20
+ * does not stop the request that is already on the wire: the runtime cannot
21
+ * interrupt a socket read in progress, so the connection is dropped when it
22
+ * next comes up for air or when `timeoutMs` expires. For a stop button that
23
+ * is exactly right - the application is free immediately - but a burst of
24
+ * cancelled requests to a host that never answers will keep the runtime's
25
+ * network queue busy until they time out.
26
+ */
27
+ signal?: AbortSignal;
28
+ }
29
+ /** Where the time went. Milliseconds, with a fraction. */
30
+ export interface NetworkTiming {
31
+ /**
32
+ * The first byte of the final response, measured from the start of the
33
+ * call - so redirects, DNS, connecting and TLS are all inside this number.
34
+ */
35
+ ttfbMs: number;
36
+ /** The final request on its own, up to its response head. */
37
+ headMs: number;
38
+ /** Reading the body, after the head arrived. */
39
+ downloadMs: number;
40
+ /** Everything, including every redirect hop. */
41
+ totalMs: number;
42
+ }
43
+ /** One hop that was followed on the way to the answer. */
44
+ export interface NetworkRedirect {
45
+ /** The 3xx that sent us on. */
46
+ status: number;
47
+ /** The URL that answered with it. */
48
+ url: string;
49
+ /** Its `Location` header, exactly as sent - which may be relative. */
50
+ location: string;
51
+ /**
52
+ * Credentials dropped because this hop crossed to another host, the way a
53
+ * browser drops them. The answer to "which redirect ate my auth header".
54
+ */
55
+ droppedHeaders: string[];
16
56
  }
17
57
  export interface NetworkResponse<Body = string> {
18
58
  /** The URL that actually answered, after any redirects. */
@@ -23,7 +63,132 @@ export interface NetworkResponse<Body = string> {
23
63
  ok: boolean;
24
64
  /** Lower-cased names. Repeated headers are joined with `, `. */
25
65
  headers: Record<string, string>;
66
+ /**
67
+ * Every header line in the order it arrived, repeats intact.
68
+ *
69
+ * `headers` is the convenient form and right nearly always, but it cannot
70
+ * represent `set-cookie`: that header is legitimately repeated, and joining
71
+ * it is ambiguous because an `Expires` date contains a comma and a space of
72
+ * its own. Read cookies from here instead:
73
+ *
74
+ * ```ts
75
+ * const cookies = response.headerPairs
76
+ * .filter(([name]) => name === "set-cookie")
77
+ * .map(([, value]) => value);
78
+ * ```
79
+ */
80
+ headerPairs: [string, string][];
26
81
  body: Body;
82
+ /**
83
+ * The size of the body in bytes, after any content decoding - a gzipped
84
+ * response counts as what it inflated to.
85
+ *
86
+ * Worth having even when you have the body: `body.length` on a string
87
+ * counts UTF-16 code units, which is not the byte count for anything
88
+ * outside ASCII.
89
+ */
90
+ bodyBytes: number;
91
+ /** Every redirect followed, in order. Empty when there were none. */
92
+ redirects: NetworkRedirect[];
93
+ timing: NetworkTiming;
94
+ }
95
+ /** Everything a stream knows before its first byte of body. */
96
+ export interface NetworkStreamHead {
97
+ /** The URL that actually answered, after any redirects. */
98
+ url: string;
99
+ status: number;
100
+ statusText: string;
101
+ ok: boolean;
102
+ headers: Record<string, string>;
103
+ /** Every header line in order, repeats intact. */
104
+ headerPairs: [string, string][];
105
+ redirects: NetworkRedirect[];
106
+ /** Only the two that are known before the body has been read. */
107
+ timing: {
108
+ ttfbMs: number;
109
+ headMs: number;
110
+ };
111
+ }
112
+ export interface NetworkStreamEnd {
113
+ /** `true` when it stopped because the application asked it to. */
114
+ cancelled: boolean;
115
+ /** Set when the connection failed part-way through. */
116
+ error?: string;
117
+ }
118
+ /** A response being delivered as it arrives. */
119
+ export interface NetworkStream<Chunk> extends NetworkStreamHead {
120
+ /** The handle the runtime knows this stream by. */
121
+ readonly id: number;
122
+ /**
123
+ * Chunks as they arrive, in order.
124
+ *
125
+ * Chunks that arrive before the first handler is attached are held and
126
+ * delivered to it, so `await`ing something between opening the stream and
127
+ * listening to it does not silently lose the beginning. Attach promptly all
128
+ * the same: nothing is dropped, which means nothing is bounded either.
129
+ */
130
+ onChunk(handler: (chunk: Chunk) => void): () => void;
131
+ /** The stream finished, failed, or was cancelled. Fires exactly once. */
132
+ onEnd(handler: (end: NetworkStreamEnd) => void): () => void;
133
+ /**
134
+ * Stop it. Resolves `false` if it had already finished.
135
+ *
136
+ * As with `signal` on a buffered request, this frees the application at
137
+ * once; the connection itself is dropped when the runtime's reader next
138
+ * comes up for air.
139
+ */
140
+ cancel(): Promise<boolean>;
141
+ }
142
+ export interface NetworkSocketOptions {
143
+ /** A `ws://` or `wss://` URL. Checked against `permissions.network`. */
144
+ url: string;
145
+ /**
146
+ * Sent on the opening handshake.
147
+ *
148
+ * The reason this exists: the webview's own `WebSocket` takes a URL and a
149
+ * subprotocol list and nothing else, so a bearer token has to go in the
150
+ * query string, where it ends up in server logs.
151
+ */
152
+ headers?: Record<string, string>;
153
+ /** Subprotocols to offer. The server picks at most one. */
154
+ protocols?: string[];
155
+ /** Connecting and the handshake, not the life of the socket. Default 30000. */
156
+ timeoutMs?: number;
157
+ /** Abandons the handshake, or closes the socket once it is up. */
158
+ signal?: AbortSignal;
159
+ }
160
+ export interface NetworkSocketClosed {
161
+ /** The WebSocket close code, when the other side sent one. */
162
+ code?: number;
163
+ reason: string;
164
+ /** Set when the connection failed rather than closed. */
165
+ error?: string;
166
+ /** `true` when it closed because the application asked. */
167
+ cancelled: boolean;
168
+ }
169
+ /** An open WebSocket. */
170
+ export interface NetworkSocket {
171
+ /** The handle the runtime knows this socket by. */
172
+ readonly id: number;
173
+ readonly url: string;
174
+ /** The subprotocol the server chose, if any. */
175
+ readonly protocol?: string;
176
+ /** Send a text message. */
177
+ send(data: string): Promise<null>;
178
+ /** Send a binary message. */
179
+ sendBytes(data: BinaryInput): Promise<null>;
180
+ /**
181
+ * Messages as they arrive. Text messages give a `string`, binary ones a
182
+ * `Uint8Array`.
183
+ *
184
+ * As with a stream, messages that arrive before the first handler is
185
+ * attached are held and delivered to it.
186
+ */
187
+ onMessage(handler: (data: string | Uint8Array) => void): () => void;
188
+ /** The socket closed, failed, or was closed by this application. */
189
+ onClose(handler: (closed: NetworkSocketClosed) => void): () => void;
190
+ /** Close it, optionally with a code and reason. */
191
+ close(code?: number, reason?: string): Promise<null>;
27
192
  }
28
193
  /**
29
194
  * HTTP from the runtime rather than the webview.
@@ -49,13 +214,96 @@ export interface NetworkResponse<Body = string> {
49
214
  * body: JSON.stringify({ lights: [{ on: 1, brightness: 80 }] }),
50
215
  * });
51
216
  * ```
217
+ *
218
+ * Every URL is checked against `permissions.network.allow` first, redirects
219
+ * included. An application that has to reach a host its user names at run
220
+ * time - an API client, a link checker - says so with `allow: ["*"]`.
52
221
  */
53
222
  export declare const network: {
54
- /** Send a request and read the response as text. */
223
+ /**
224
+ * Send a request and read the response as text.
225
+ *
226
+ * The body is decoded as UTF-8, and anything that is not valid UTF-8 is
227
+ * replaced with U+FFFD rather than failing. Use {@link network.binary} when
228
+ * the response might not be text, or when you need the bytes exactly;
229
+ * `bodyBytes` is there to tell you when the two disagree.
230
+ */
55
231
  request: (options: NetworkRequestOptions) => Promise<NetworkResponse<string>>;
56
232
  /** The same, parsed as JSON. Throws if the body is not JSON. */
57
233
  json: <T = unknown>(options: NetworkRequestOptions) => Promise<NetworkResponse<T>>;
58
- /** The same, with the body as bytes. */
234
+ /**
235
+ * The same, with the body as bytes.
236
+ *
237
+ * The better default for anything that is not certainly UTF-8 text: the
238
+ * byte count is exact and nothing is replaced on the way through.
239
+ */
59
240
  binary: (options: NetworkRequestOptions) => Promise<NetworkResponse<Uint8Array>>;
241
+ /**
242
+ * A response delivered as it arrives, as text.
243
+ *
244
+ * This is how server-sent events and long-polling are consumed from the
245
+ * runtime at all: `network.request` waits for the whole body, which for a
246
+ * stream that stays open is forever. The webview's own `EventSource` works
247
+ * and is the right tool when CORS allows it - this is for when it does not,
248
+ * and for when the request needs headers `EventSource` cannot set.
249
+ *
250
+ * ```ts
251
+ * const stream = await network.stream({
252
+ * url: `${base}/events`,
253
+ * headers: { authorization: `Bearer ${token}`, accept: "text/event-stream" },
254
+ * });
255
+ *
256
+ * let buffer = "";
257
+ * stream.onChunk((chunk) => {
258
+ * buffer += chunk;
259
+ * // SSE separates events with a blank line.
260
+ * const events = buffer.split("\n\n");
261
+ * buffer = events.pop() ?? "";
262
+ * for (const event of events) handle(event);
263
+ * });
264
+ * stream.onEnd(({ error }) => { if (error) retry(); });
265
+ * ```
266
+ *
267
+ * Chunks are decoded as UTF-8 with any character split across a chunk
268
+ * boundary held back and joined to the next one, so a stream of JSON stays
269
+ * parseable.
270
+ */
271
+ stream: (options: NetworkRequestOptions) => Promise<NetworkStream<string>>;
272
+ /**
273
+ * The same, as bytes - for a download, or anything that is not text.
274
+ *
275
+ * The whole body never has to be held in memory at once, which is what
276
+ * `network.binary` cannot avoid.
277
+ */
278
+ streamBinary: (options: NetworkRequestOptions) => Promise<NetworkStream<Uint8Array>>;
279
+ /**
280
+ * A WebSocket opened by the runtime rather than the page.
281
+ *
282
+ * The webview has its own `WebSocket` and it is the right tool when it can
283
+ * do the job. It cannot set a header on the opening handshake, which is how
284
+ * most APIs authenticate one - so the token goes in the query string, where
285
+ * it ends up in the server's logs. This can set headers, and is not subject
286
+ * to the page's origin rules.
287
+ *
288
+ * ```ts
289
+ * const socket = await network.socket({
290
+ * url: "wss://api.example.com/live",
291
+ * headers: { authorization: `Bearer ${token}` },
292
+ * protocols: ["graphql-transport-ws"],
293
+ * });
294
+ *
295
+ * socket.onMessage((data) => {
296
+ * if (typeof data === "string") handle(JSON.parse(data));
297
+ * });
298
+ * socket.onClose(({ code, error }) => { if (error) reconnect(); });
299
+ *
300
+ * await socket.send(JSON.stringify({ type: "subscribe", topic }));
301
+ * ```
302
+ *
303
+ * Pings are answered by the runtime, so a socket stays up without the
304
+ * application doing anything. Send latency is bounded at about 10ms: one
305
+ * thread owns the socket, and a send waits for its read to come up for air.
306
+ */
307
+ socket: (options: NetworkSocketOptions) => Promise<NetworkSocket>;
60
308
  };
61
309
  //# sourceMappingURL=network.d.ts.map