@monimesl/dot-dash 0.1.0-alpha.3 → 0.1.0-alpha.30
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/index.d.ts +736 -113
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +720 -89
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,113 +1,293 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { HostError, HostError as
|
|
2
|
+
import { DEFAULT_DASH_API_VERSION, HostError, HostError as DashError, callHost, createHostRequest, offersDashApiVersion } from "@monimesl/dot-core";
|
|
3
|
+
//#region src/api-versions.ts
|
|
4
|
+
const DASH_API_VERSION = "1.0";
|
|
5
|
+
const DASH_API_SINCE = {
|
|
6
|
+
"account.signIn": "1.0",
|
|
7
|
+
"contacts.pickPhone": "1.0",
|
|
8
|
+
"crypto.hmac": "1.0",
|
|
9
|
+
"crypto.randomBytes": "1.0",
|
|
10
|
+
"crypto.randomUUID": "1.0",
|
|
11
|
+
"crypto.sha256": "1.0",
|
|
12
|
+
"crypto.sha512": "1.0",
|
|
13
|
+
"dot.close": "1.0",
|
|
14
|
+
"media.pickFile": "1.0",
|
|
15
|
+
"media.pickPhoto": "1.0",
|
|
16
|
+
"media.scanCode": "1.0",
|
|
17
|
+
"network.http.download": "1.0",
|
|
18
|
+
"network.http.request": "1.0",
|
|
19
|
+
"network.http.upload": "1.0",
|
|
20
|
+
"network.status": "1.0",
|
|
21
|
+
"storage.cache.clear": "1.0",
|
|
22
|
+
"storage.cache.exists": "1.0",
|
|
23
|
+
"storage.cache.get": "1.0",
|
|
24
|
+
"storage.cache.keys": "1.0",
|
|
25
|
+
"storage.cache.remove": "1.0",
|
|
26
|
+
"storage.cache.set": "1.0",
|
|
27
|
+
"storage.file.copy": "1.0",
|
|
28
|
+
"storage.file.createFolder": "1.0",
|
|
29
|
+
"storage.file.list": "1.0",
|
|
30
|
+
"storage.file.move": "1.0",
|
|
31
|
+
"storage.file.open": "1.0",
|
|
32
|
+
"storage.file.read": "1.0",
|
|
33
|
+
"storage.file.remove": "1.0",
|
|
34
|
+
"storage.file.save": "1.0",
|
|
35
|
+
"storage.file.stat": "1.0",
|
|
36
|
+
"storage.file.usage": "1.0",
|
|
37
|
+
"storage.file.write": "1.0",
|
|
38
|
+
"storage.secret.clear": "1.0",
|
|
39
|
+
"storage.secret.get": "1.0",
|
|
40
|
+
"storage.secret.remove": "1.0",
|
|
41
|
+
"storage.secret.set": "1.0",
|
|
42
|
+
"system.brightness": "1.0",
|
|
43
|
+
"system.copyText": "1.0",
|
|
44
|
+
"system.delay": "1.0",
|
|
45
|
+
"system.dial": "1.0",
|
|
46
|
+
"system.info": "1.0",
|
|
47
|
+
"system.keepAwake": "1.0",
|
|
48
|
+
"system.openUrl": "1.0",
|
|
49
|
+
"system.share": "1.0",
|
|
50
|
+
"system.torch": "1.0",
|
|
51
|
+
"system.vibrate": "1.0",
|
|
52
|
+
"ui.alert": "1.0",
|
|
53
|
+
"ui.pickDate": "1.0",
|
|
54
|
+
"ui.pickTime": "1.0"
|
|
55
|
+
};
|
|
56
|
+
let hostApiVersions = [DEFAULT_DASH_API_VERSION];
|
|
57
|
+
let dotMinApiVersion;
|
|
58
|
+
const checkedFeatures = /* @__PURE__ */ new Set();
|
|
59
|
+
const warnedFeatures = /* @__PURE__ */ new Set();
|
|
60
|
+
function useHostDashApiVersions(versions) {
|
|
61
|
+
hostApiVersions = versions;
|
|
62
|
+
}
|
|
63
|
+
function warnAboveDashApiVersion(minApiVersion) {
|
|
64
|
+
dotMinApiVersion = minApiVersion;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Whether the Dash the dot runs in has `feature`: a call, such as "contacts.pickPhone", or a field
|
|
68
|
+
* added to a call later. Check it before using one that's newer than the dot's minApiVersion.
|
|
69
|
+
* @since 1.0
|
|
70
|
+
*/
|
|
71
|
+
function supports(feature) {
|
|
72
|
+
checkedFeatures.add(feature);
|
|
73
|
+
const since = sinceOf(feature);
|
|
74
|
+
return since !== void 0 && offersDashApiVersion(hostApiVersions, since);
|
|
75
|
+
}
|
|
76
|
+
function warnIfNewerThanDot(method, params) {
|
|
77
|
+
if (dotMinApiVersion === void 0) return;
|
|
78
|
+
const callName = method.replace(/^dash\./, "");
|
|
79
|
+
for (const feature of [callName, ...fieldsSent(callName, params)]) {
|
|
80
|
+
const since = sinceOf(feature);
|
|
81
|
+
if (since === void 0) continue;
|
|
82
|
+
if (checkedFeatures.has(feature) || warnedFeatures.has(feature)) continue;
|
|
83
|
+
if (offersDashApiVersion([dotMinApiVersion], since)) continue;
|
|
84
|
+
warnedFeatures.add(feature);
|
|
85
|
+
console.warn(`dash.${feature} came in Dash API ${since}, but this dot's minApiVersion is ${dotMinApiVersion}, so older Dash doesn't have it. Raise "minApiVersion" in dot.json, or check dash.supports('${feature}') first.`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function sinceOf(feature) {
|
|
89
|
+
const table = DASH_API_SINCE;
|
|
90
|
+
return Object.hasOwn(table, feature) ? table[feature] : void 0;
|
|
91
|
+
}
|
|
92
|
+
function fieldsSent(callName, params) {
|
|
93
|
+
if (typeof params !== "object" || params === null) return [];
|
|
94
|
+
return Object.keys(params).map((field) => `${callName}.${field}`).filter((feature) => sinceOf(feature) !== void 0);
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
3
97
|
//#region src/call.ts
|
|
4
98
|
function call(method, params, options = {}) {
|
|
99
|
+
warnIfNewerThanDot(method, params);
|
|
5
100
|
return callHost(method, params, options);
|
|
6
101
|
}
|
|
7
102
|
//#endregion
|
|
8
|
-
//#region src/
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
103
|
+
//#region src/account/index.ts
|
|
104
|
+
var account_exports = /* @__PURE__ */ __exportAll({ signIn: () => signIn });
|
|
105
|
+
function signIn(options, callOptions) {
|
|
106
|
+
const params = {
|
|
107
|
+
mode: options.mode,
|
|
108
|
+
nonce: options.nonce ?? ""
|
|
109
|
+
};
|
|
110
|
+
if (options.mode === "oidc" && options.scopes) params.scopes = options.scopes;
|
|
111
|
+
return call("dash.account.signIn", params, callOptions);
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/contacts/pick-phone.ts
|
|
115
|
+
/**
|
|
116
|
+
* Shows the phone's contacts so the person chooses one phone number, such as who to send money to.
|
|
117
|
+
* Needs the `contacts` permission. The dot sees only the chosen contact. Rejects with `cancelled` if
|
|
118
|
+
* the person closes it.
|
|
119
|
+
* @since 1.0
|
|
120
|
+
*/
|
|
121
|
+
function pickPhone(callOptions) {
|
|
122
|
+
return call("dash.contacts.pickPhone", {}, callOptions);
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/contacts/index.ts
|
|
126
|
+
var contacts_exports = /* @__PURE__ */ __exportAll({ pickPhone: () => pickPhone });
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/crypto/index.ts
|
|
129
|
+
var crypto_exports = /* @__PURE__ */ __exportAll({
|
|
130
|
+
hmac: () => hmac,
|
|
131
|
+
randomBytes: () => randomBytes,
|
|
132
|
+
randomUUID: () => randomUUID,
|
|
133
|
+
sha256: () => sha256,
|
|
134
|
+
sha512: () => sha512
|
|
21
135
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
...options
|
|
26
|
-
}, callOptions);
|
|
136
|
+
/** @since 1.0 */
|
|
137
|
+
function sha256(data, options = {}, callOptions) {
|
|
138
|
+
return call("dash.crypto.sha256", wireInput(data, options), callOptions);
|
|
27
139
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
data,
|
|
32
|
-
...options
|
|
33
|
-
}, callOptions);
|
|
140
|
+
/** @since 1.0 */
|
|
141
|
+
function sha512(data, options = {}, callOptions) {
|
|
142
|
+
return call("dash.crypto.sha512", wireInput(data, options), callOptions);
|
|
34
143
|
}
|
|
35
|
-
|
|
36
|
-
|
|
144
|
+
/**
|
|
145
|
+
* Signs `data` with `key`, as HMAC-SHA256 or HMAC-SHA512, such as
|
|
146
|
+
* `hmac({ algorithm: 'sha256', key, data })`.
|
|
147
|
+
* @since 1.0
|
|
148
|
+
*/
|
|
149
|
+
function hmac(options, callOptions) {
|
|
150
|
+
const wireKey = valueAndEncoding(options.key);
|
|
151
|
+
return call("dash.crypto.hmac", {
|
|
152
|
+
...wireInput(options.data, options),
|
|
153
|
+
algorithm: options.algorithm,
|
|
154
|
+
key: wireKey.value,
|
|
155
|
+
keyEncoding: wireKey.encoding
|
|
156
|
+
}, callOptions);
|
|
37
157
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
158
|
+
/**
|
|
159
|
+
* `count` secure random bytes, from 1 to 1024, such as for a nonce.
|
|
160
|
+
* @since 1.0
|
|
161
|
+
*/
|
|
162
|
+
function randomBytes(count, options = {}, callOptions) {
|
|
163
|
+
return call("dash.crypto.randomBytes", {
|
|
164
|
+
count,
|
|
165
|
+
as: outputEncoding(options)
|
|
42
166
|
}, callOptions);
|
|
43
167
|
}
|
|
44
|
-
|
|
45
|
-
|
|
168
|
+
/**
|
|
169
|
+
* A random version 4 UUID, such as "3f0e5c3a-6d1b-4c8e-9a2f-1b7d4e6a9c05".
|
|
170
|
+
* @since 1.0
|
|
171
|
+
*/
|
|
172
|
+
function randomUUID(callOptions) {
|
|
173
|
+
return call("dash.crypto.randomUUID", {}, callOptions);
|
|
46
174
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
175
|
+
function wireInput(data, options) {
|
|
176
|
+
const { value, encoding } = valueAndEncoding(data);
|
|
177
|
+
return {
|
|
178
|
+
data: value,
|
|
179
|
+
dataEncoding: encoding,
|
|
180
|
+
as: outputEncoding(options)
|
|
181
|
+
};
|
|
53
182
|
}
|
|
54
|
-
function
|
|
55
|
-
return
|
|
56
|
-
from,
|
|
57
|
-
to,
|
|
58
|
-
...options
|
|
59
|
-
}, callOptions);
|
|
183
|
+
function outputEncoding(options) {
|
|
184
|
+
return options.as ?? "hex";
|
|
60
185
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
186
|
+
function valueAndEncoding(input) {
|
|
187
|
+
if (typeof input === "string") return {
|
|
188
|
+
value: input,
|
|
189
|
+
encoding: "text"
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
value: input.base64,
|
|
193
|
+
encoding: "base64"
|
|
194
|
+
};
|
|
66
195
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/dot/index.ts
|
|
198
|
+
var dot_exports = /* @__PURE__ */ __exportAll({ close: () => close });
|
|
199
|
+
/**
|
|
200
|
+
* Closes the dot, as going back from its first page does. Calls still running are cancelled.
|
|
201
|
+
* @since 1.0
|
|
202
|
+
*/
|
|
203
|
+
function close(callOptions) {
|
|
204
|
+
return call("dash.dot.close", {}, callOptions);
|
|
73
205
|
}
|
|
74
|
-
|
|
75
|
-
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/media/pick-file.ts
|
|
208
|
+
/**
|
|
209
|
+
* Lets the person choose a file from their phone, of at most 25 MB. Needs the `files` permission.
|
|
210
|
+
* Rejects with `cancelled` if they close the picker, and with `invalid` for a larger file. Like a
|
|
211
|
+
* download, it lasts until the dot closes, so `dash.storage.file.save` it to keep it.
|
|
212
|
+
* @since 1.0
|
|
213
|
+
*/
|
|
214
|
+
function pickFile(options = {}, callOptions) {
|
|
215
|
+
const params = {};
|
|
216
|
+
if (options.types) params.types = options.types;
|
|
217
|
+
return call("dash.media.pickFile", params, callOptions);
|
|
76
218
|
}
|
|
77
|
-
|
|
78
|
-
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/media/pick-photo.ts
|
|
221
|
+
/**
|
|
222
|
+
* Lets the person choose a photo or take one. Resolves with it as a JPEG of at most 2048 pixels on its
|
|
223
|
+
* longest side, without its location or other details. Rejects with `cancelled` if they close the
|
|
224
|
+
* picker, and with `unsupported` on a device without a camera. Save it with `dash.storage.file.save`
|
|
225
|
+
* to keep it after the dot closes.
|
|
226
|
+
* @since 1.0
|
|
227
|
+
*/
|
|
228
|
+
function pickPhoto(options, callOptions) {
|
|
229
|
+
return call("dash.media.pickPhoto", { source: options.source }, callOptions);
|
|
230
|
+
}
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/media/scan-code.ts
|
|
233
|
+
/**
|
|
234
|
+
* Opens Dash's scanner until it reads a QR code. Needs the `camera` permission. Rejects with
|
|
235
|
+
* `cancelled` if the person closes it, and with `unsupported` where Dash has no scanner.
|
|
236
|
+
* @since 1.0
|
|
237
|
+
*/
|
|
238
|
+
function scanCode(callOptions) {
|
|
239
|
+
return call("dash.media.scanCode", {}, callOptions);
|
|
79
240
|
}
|
|
80
241
|
//#endregion
|
|
242
|
+
//#region src/media/index.ts
|
|
243
|
+
var media_exports = /* @__PURE__ */ __exportAll({
|
|
244
|
+
pickFile: () => pickFile,
|
|
245
|
+
pickPhoto: () => pickPhoto,
|
|
246
|
+
scanCode: () => scanCode
|
|
247
|
+
});
|
|
248
|
+
//#endregion
|
|
81
249
|
//#region src/network/http.ts
|
|
82
250
|
var http_exports = /* @__PURE__ */ __exportAll({
|
|
83
251
|
download: () => download,
|
|
84
252
|
request: () => request,
|
|
85
253
|
upload: () => upload
|
|
86
254
|
});
|
|
255
|
+
/**
|
|
256
|
+
* Like fetch, resolves with any response, even a 404. An object body is sent as JSON.
|
|
257
|
+
* @since 1.0
|
|
258
|
+
*/
|
|
87
259
|
function request(options, callOptions) {
|
|
88
|
-
const { as, ...request } = options;
|
|
89
|
-
return readBody(call("dash.network.http.request", wireRequest(request,
|
|
260
|
+
const { as: readAs, ...request } = options;
|
|
261
|
+
return readBody(call("dash.network.http.request", wireRequest(request, readAs), callOptions), readAs);
|
|
90
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Saves a 2xx response's body, up to 256 MB, to a temporary file.
|
|
265
|
+
* @since 1.0
|
|
266
|
+
*/
|
|
91
267
|
function download(options, callOptions) {
|
|
92
268
|
return call("dash.network.http.download", wireRequest(options), callOptions);
|
|
93
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Sends the dot's files as a multipart form.
|
|
272
|
+
* @since 1.0
|
|
273
|
+
*/
|
|
94
274
|
function upload(options, callOptions) {
|
|
95
|
-
const { as, ...request } = options;
|
|
96
|
-
const files = request.files.map((
|
|
97
|
-
...
|
|
98
|
-
file:
|
|
275
|
+
const { as: readAs, ...request } = options;
|
|
276
|
+
const files = request.files.map((upload) => ({
|
|
277
|
+
...upload,
|
|
278
|
+
file: upload.file.id
|
|
99
279
|
}));
|
|
100
280
|
const params = {
|
|
101
281
|
...request,
|
|
102
282
|
files
|
|
103
283
|
};
|
|
104
|
-
if (
|
|
105
|
-
return readBody(call("dash.network.http.upload", params, callOptions),
|
|
284
|
+
if (readAs === "json") params.headers = withDefaultHeader(request.headers, "Accept", "application/json");
|
|
285
|
+
return readBody(call("dash.network.http.upload", params, callOptions), readAs);
|
|
106
286
|
}
|
|
107
|
-
function wireRequest(request,
|
|
287
|
+
function wireRequest(request, readAs) {
|
|
108
288
|
let headers = request.headers;
|
|
109
289
|
let body;
|
|
110
|
-
if (
|
|
290
|
+
if (readAs === "json") headers = withDefaultHeader(headers, "Accept", "application/json");
|
|
111
291
|
if (typeof request.body === "string") body = request.body;
|
|
112
292
|
else if (request.body !== void 0) {
|
|
113
293
|
headers = withDefaultHeader(headers, "Content-Type", "application/json");
|
|
@@ -120,15 +300,16 @@ function wireRequest(request, as) {
|
|
|
120
300
|
};
|
|
121
301
|
}
|
|
122
302
|
function withDefaultHeader(headers, name, value) {
|
|
303
|
+
if (headers === void 0) return { [name]: value };
|
|
123
304
|
const lowerName = name.toLowerCase();
|
|
124
|
-
if (
|
|
305
|
+
if (Object.keys(headers).some((existing) => existing.toLowerCase() === lowerName)) return headers;
|
|
125
306
|
return {
|
|
126
307
|
...headers,
|
|
127
308
|
[name]: value
|
|
128
309
|
};
|
|
129
310
|
}
|
|
130
|
-
function readBody(response,
|
|
131
|
-
if (
|
|
311
|
+
function readBody(response, readAs) {
|
|
312
|
+
if (readAs !== "json") return response;
|
|
132
313
|
const parsed = response.then((result) => ({
|
|
133
314
|
...result,
|
|
134
315
|
body: parseJson(result)
|
|
@@ -140,54 +321,318 @@ function parseJson({ status, statusText, body }) {
|
|
|
140
321
|
return JSON.parse(body);
|
|
141
322
|
} catch (error) {
|
|
142
323
|
const message = error instanceof Error ? error.message : String(error);
|
|
143
|
-
throw new HostError
|
|
324
|
+
throw new HostError("failed", `The response (${status} ${statusText}) isn't JSON: ${message}`);
|
|
144
325
|
}
|
|
145
326
|
}
|
|
146
327
|
//#endregion
|
|
328
|
+
//#region src/network/status.ts
|
|
329
|
+
/**
|
|
330
|
+
* Whether the phone is online now, and how. It can still be online without reaching a server.
|
|
331
|
+
* @since 1.0
|
|
332
|
+
*/
|
|
333
|
+
function status(callOptions) {
|
|
334
|
+
return call("dash.network.status", {}, callOptions);
|
|
335
|
+
}
|
|
336
|
+
//#endregion
|
|
147
337
|
//#region src/network/index.ts
|
|
148
|
-
var network_exports = /* @__PURE__ */ __exportAll({
|
|
338
|
+
var network_exports = /* @__PURE__ */ __exportAll({
|
|
339
|
+
http: () => http_exports,
|
|
340
|
+
status: () => status
|
|
341
|
+
});
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/storage/cache.ts
|
|
344
|
+
var cache_exports = /* @__PURE__ */ __exportAll({
|
|
345
|
+
clear: () => clear$1,
|
|
346
|
+
exists: () => exists,
|
|
347
|
+
get: () => get$1,
|
|
348
|
+
keys: () => keys,
|
|
349
|
+
remove: () => remove$2,
|
|
350
|
+
set: () => set$1
|
|
351
|
+
});
|
|
352
|
+
/**
|
|
353
|
+
* Resolves with null for a missing or expired key.
|
|
354
|
+
* @since 1.0
|
|
355
|
+
*/
|
|
356
|
+
function get$1(key, callOptions) {
|
|
357
|
+
return call("dash.storage.cache.get", { key }, callOptions);
|
|
358
|
+
}
|
|
359
|
+
/** @since 1.0 */
|
|
360
|
+
function set$1(key, value, options = {}, callOptions) {
|
|
361
|
+
return call("dash.storage.cache.set", {
|
|
362
|
+
key,
|
|
363
|
+
value,
|
|
364
|
+
...options
|
|
365
|
+
}, callOptions);
|
|
366
|
+
}
|
|
367
|
+
/** @since 1.0 */
|
|
368
|
+
function remove$2(key, callOptions) {
|
|
369
|
+
return call("dash.storage.cache.remove", { key }, callOptions);
|
|
370
|
+
}
|
|
371
|
+
/** @since 1.0 */
|
|
372
|
+
function exists(key, callOptions) {
|
|
373
|
+
return call("dash.storage.cache.exists", { key }, callOptions);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* The keys, sorted.
|
|
377
|
+
* @since 1.0
|
|
378
|
+
*/
|
|
379
|
+
function keys(callOptions) {
|
|
380
|
+
return call("dash.storage.cache.keys", {}, callOptions);
|
|
381
|
+
}
|
|
382
|
+
/** @since 1.0 */
|
|
383
|
+
function clear$1(callOptions) {
|
|
384
|
+
return call("dash.storage.cache.clear", {}, callOptions);
|
|
385
|
+
}
|
|
386
|
+
//#endregion
|
|
387
|
+
//#region src/storage/file.ts
|
|
388
|
+
var file_exports = /* @__PURE__ */ __exportAll({
|
|
389
|
+
copy: () => copy,
|
|
390
|
+
createFolder: () => createFolder,
|
|
391
|
+
list: () => list,
|
|
392
|
+
move: () => move,
|
|
393
|
+
open: () => open,
|
|
394
|
+
read: () => read,
|
|
395
|
+
remove: () => remove$1,
|
|
396
|
+
save: () => save,
|
|
397
|
+
stat: () => stat,
|
|
398
|
+
usage: () => usage,
|
|
399
|
+
write: () => write
|
|
400
|
+
});
|
|
401
|
+
/**
|
|
402
|
+
* Reads a file of up to 5 MB.
|
|
403
|
+
* @since 1.0
|
|
404
|
+
*/
|
|
405
|
+
function read(path, options = {}, callOptions) {
|
|
406
|
+
return call("dash.storage.file.read", {
|
|
407
|
+
path,
|
|
408
|
+
...options
|
|
409
|
+
}, callOptions);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Creates any missing folders above the file.
|
|
413
|
+
* @since 1.0
|
|
414
|
+
*/
|
|
415
|
+
function write(path, data, options = {}, callOptions) {
|
|
416
|
+
return call("dash.storage.file.write", {
|
|
417
|
+
path,
|
|
418
|
+
data,
|
|
419
|
+
...options
|
|
420
|
+
}, callOptions);
|
|
421
|
+
}
|
|
422
|
+
/** @since 1.0 */
|
|
423
|
+
function stat(path, callOptions) {
|
|
424
|
+
return call("dash.storage.file.stat", { path }, callOptions);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Sorted by path.
|
|
428
|
+
* @since 1.0
|
|
429
|
+
*/
|
|
430
|
+
function list(path = "", options = {}, callOptions) {
|
|
431
|
+
return call("dash.storage.file.list", {
|
|
432
|
+
path,
|
|
433
|
+
...options
|
|
434
|
+
}, callOptions);
|
|
435
|
+
}
|
|
436
|
+
/** @since 1.0 */
|
|
437
|
+
function createFolder(path, callOptions) {
|
|
438
|
+
return call("dash.storage.file.createFolder", { path }, callOptions);
|
|
439
|
+
}
|
|
440
|
+
/** @since 1.0 */
|
|
441
|
+
function move(from, to, options = {}, callOptions) {
|
|
442
|
+
return call("dash.storage.file.move", {
|
|
443
|
+
from,
|
|
444
|
+
to,
|
|
445
|
+
...options
|
|
446
|
+
}, callOptions);
|
|
447
|
+
}
|
|
448
|
+
/** @since 1.0 */
|
|
449
|
+
function copy(from, to, options = {}, callOptions) {
|
|
450
|
+
return call("dash.storage.file.copy", {
|
|
451
|
+
from,
|
|
452
|
+
to,
|
|
453
|
+
...options
|
|
454
|
+
}, callOptions);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Removing a folder that isn't empty needs `recursive`.
|
|
458
|
+
* @since 1.0
|
|
459
|
+
*/
|
|
460
|
+
function remove$1(path, options = {}, callOptions) {
|
|
461
|
+
return call("dash.storage.file.remove", {
|
|
462
|
+
path,
|
|
463
|
+
...options
|
|
464
|
+
}, callOptions);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Keeps a temporary file, such as a download, at `path`.
|
|
468
|
+
* @since 1.0
|
|
469
|
+
*/
|
|
470
|
+
function save(file, path, options = {}, callOptions) {
|
|
471
|
+
return call("dash.storage.file.save", {
|
|
472
|
+
file: file.id,
|
|
473
|
+
path,
|
|
474
|
+
...options
|
|
475
|
+
}, callOptions);
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* A stored file as a DotFile, to show with its `url` or send with `http.upload`.
|
|
479
|
+
* @since 1.0
|
|
480
|
+
*/
|
|
481
|
+
function open(path, callOptions) {
|
|
482
|
+
return call("dash.storage.file.open", { path }, callOptions);
|
|
483
|
+
}
|
|
484
|
+
/** @since 1.0 */
|
|
485
|
+
function usage(callOptions) {
|
|
486
|
+
return call("dash.storage.file.usage", {}, callOptions);
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/storage/secret.ts
|
|
490
|
+
var secret_exports = /* @__PURE__ */ __exportAll({
|
|
491
|
+
clear: () => clear,
|
|
492
|
+
get: () => get,
|
|
493
|
+
remove: () => remove,
|
|
494
|
+
set: () => set
|
|
495
|
+
});
|
|
496
|
+
/** @since 1.0 */
|
|
497
|
+
function get(key, callOptions) {
|
|
498
|
+
return call("dash.storage.secret.get", { key }, callOptions);
|
|
499
|
+
}
|
|
500
|
+
/** @since 1.0 */
|
|
501
|
+
function set(key, value, callOptions) {
|
|
502
|
+
return call("dash.storage.secret.set", {
|
|
503
|
+
key,
|
|
504
|
+
value
|
|
505
|
+
}, callOptions);
|
|
506
|
+
}
|
|
507
|
+
/** @since 1.0 */
|
|
508
|
+
function remove(key, callOptions) {
|
|
509
|
+
return call("dash.storage.secret.remove", { key }, callOptions);
|
|
510
|
+
}
|
|
511
|
+
/** @since 1.0 */
|
|
512
|
+
function clear(callOptions) {
|
|
513
|
+
return call("dash.storage.secret.clear", {}, callOptions);
|
|
514
|
+
}
|
|
515
|
+
//#endregion
|
|
516
|
+
//#region src/storage/index.ts
|
|
517
|
+
var storage_exports = /* @__PURE__ */ __exportAll({
|
|
518
|
+
cache: () => cache_exports,
|
|
519
|
+
file: () => file_exports,
|
|
520
|
+
secret: () => secret_exports
|
|
521
|
+
});
|
|
149
522
|
//#endregion
|
|
150
523
|
//#region src/system/clipboard.ts
|
|
524
|
+
/** @since 1.0 */
|
|
151
525
|
function copyText(text, callOptions) {
|
|
152
526
|
return call("dash.system.copyText", { text }, callOptions);
|
|
153
527
|
}
|
|
154
528
|
//#endregion
|
|
155
529
|
//#region src/system/delay.ts
|
|
530
|
+
/**
|
|
531
|
+
* Resolves after `milliseconds`. The host keeps the time, since a dot's logic has no timers.
|
|
532
|
+
* @since 1.0
|
|
533
|
+
*/
|
|
156
534
|
function delay(milliseconds, callOptions) {
|
|
157
535
|
return call("dash.system.delay", { milliseconds }, callOptions);
|
|
158
536
|
}
|
|
159
537
|
//#endregion
|
|
538
|
+
//#region src/system/dial.ts
|
|
539
|
+
/**
|
|
540
|
+
* Opens the phone's dialer with `number` ready, such as "+232 76 123456" or a USSD code such as
|
|
541
|
+
* "*715#". The person taps Call. Spaces and dashes are fine; anything else but digits, +, * and #
|
|
542
|
+
* rejects with `invalid`.
|
|
543
|
+
* @since 1.0
|
|
544
|
+
*/
|
|
545
|
+
function dial(number, callOptions) {
|
|
546
|
+
return call("dash.system.dial", { number }, callOptions);
|
|
547
|
+
}
|
|
548
|
+
//#endregion
|
|
160
549
|
//#region src/system/haptics.ts
|
|
550
|
+
/**
|
|
551
|
+
* Plays a short vibration. Resolves once it's done.
|
|
552
|
+
* @since 1.0
|
|
553
|
+
*/
|
|
161
554
|
function vibrate(options = {}, callOptions) {
|
|
162
555
|
return call("dash.system.vibrate", { style: options.style ?? "medium" }, callOptions);
|
|
163
556
|
}
|
|
164
557
|
//#endregion
|
|
558
|
+
//#region src/system/info.ts
|
|
559
|
+
/**
|
|
560
|
+
* The phone and the Dash the dot runs in. It has nothing that identifies the person or the phone.
|
|
561
|
+
* @since 1.0
|
|
562
|
+
*/
|
|
563
|
+
function info(callOptions) {
|
|
564
|
+
return call("dash.system.info", {}, callOptions);
|
|
565
|
+
}
|
|
566
|
+
//#endregion
|
|
567
|
+
//#region src/system/open-url.ts
|
|
568
|
+
/**
|
|
569
|
+
* Opens an https address in the device's browser. Any other address rejects with `invalid`.
|
|
570
|
+
* @since 1.0
|
|
571
|
+
*/
|
|
572
|
+
function openUrl(url, callOptions) {
|
|
573
|
+
return call("dash.system.openUrl", { url }, callOptions);
|
|
574
|
+
}
|
|
575
|
+
//#endregion
|
|
576
|
+
//#region src/system/screen.ts
|
|
577
|
+
/**
|
|
578
|
+
* Keeps the screen from dimming and locking while the dot shows, such as while a ticket's QR code is
|
|
579
|
+
* up. Dash undoes it when the dot closes.
|
|
580
|
+
* @since 1.0
|
|
581
|
+
*/
|
|
582
|
+
function keepAwake(on, callOptions) {
|
|
583
|
+
return call("dash.system.keepAwake", { on }, callOptions);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* `max` makes the screen as bright as it goes, so a scanner can read a QR code on it, and `normal`
|
|
587
|
+
* puts it back. Dash puts it back too when the dot closes or the person leaves the app.
|
|
588
|
+
* @since 1.0
|
|
589
|
+
*/
|
|
590
|
+
function brightness(level, callOptions) {
|
|
591
|
+
return call("dash.system.brightness", { level }, callOptions);
|
|
592
|
+
}
|
|
593
|
+
//#endregion
|
|
165
594
|
//#region src/system/share.ts
|
|
595
|
+
/**
|
|
596
|
+
* Opens the device's share sheet. Resolves once it shows.
|
|
597
|
+
* @since 1.0
|
|
598
|
+
*/
|
|
166
599
|
function share(options, callOptions) {
|
|
167
|
-
const { file, ...
|
|
168
|
-
if (file === void 0) return call("dash.system.share",
|
|
169
|
-
const id = typeof file === "string" ? file : file.id;
|
|
600
|
+
const { file, ...content } = options;
|
|
601
|
+
if (file === void 0) return call("dash.system.share", content, callOptions);
|
|
170
602
|
return call("dash.system.share", {
|
|
171
|
-
...
|
|
172
|
-
file: id
|
|
603
|
+
...content,
|
|
604
|
+
file: file.id
|
|
173
605
|
}, callOptions);
|
|
174
606
|
}
|
|
175
607
|
//#endregion
|
|
176
608
|
//#region src/system/torch.ts
|
|
177
|
-
|
|
178
|
-
|
|
609
|
+
/**
|
|
610
|
+
* Turns the torch on or off. Rejects with `unsupported` on a device without one.
|
|
611
|
+
* @since 1.0
|
|
612
|
+
*/
|
|
613
|
+
function torch(on, callOptions) {
|
|
614
|
+
return call("dash.system.torch", { on }, callOptions);
|
|
179
615
|
}
|
|
180
616
|
//#endregion
|
|
181
617
|
//#region src/system/index.ts
|
|
182
618
|
var system_exports = /* @__PURE__ */ __exportAll({
|
|
619
|
+
brightness: () => brightness,
|
|
183
620
|
copyText: () => copyText,
|
|
184
621
|
delay: () => delay,
|
|
622
|
+
dial: () => dial,
|
|
623
|
+
info: () => info,
|
|
624
|
+
keepAwake: () => keepAwake,
|
|
625
|
+
openUrl: () => openUrl,
|
|
185
626
|
share: () => share,
|
|
186
627
|
torch: () => torch,
|
|
187
628
|
vibrate: () => vibrate
|
|
188
629
|
});
|
|
189
630
|
//#endregion
|
|
190
631
|
//#region src/ui/dialogs.ts
|
|
632
|
+
/**
|
|
633
|
+
* Shows a native alert. Resolves with the action the person chose.
|
|
634
|
+
* @since 1.0
|
|
635
|
+
*/
|
|
191
636
|
function alert(options, callOptions) {
|
|
192
637
|
const actions = options.actions ?? [{
|
|
193
638
|
id: "ok",
|
|
@@ -199,31 +644,217 @@ function alert(options, callOptions) {
|
|
|
199
644
|
}, callOptions);
|
|
200
645
|
}
|
|
201
646
|
//#endregion
|
|
647
|
+
//#region src/ui/pickers.ts
|
|
648
|
+
/**
|
|
649
|
+
* Opens the phone's own calendar. Resolves with the chosen date, such as "2026-10-24", or rejects
|
|
650
|
+
* with `cancelled` if the person closes it.
|
|
651
|
+
* @since 1.0
|
|
652
|
+
*/
|
|
653
|
+
function pickDate(options = {}, callOptions) {
|
|
654
|
+
return call("dash.ui.pickDate", options, callOptions);
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Opens the phone's own clock. Resolves with the chosen time in 24 hours, such as "19:30", or
|
|
658
|
+
* rejects with `cancelled` if the person closes it.
|
|
659
|
+
* @since 1.0
|
|
660
|
+
*/
|
|
661
|
+
function pickTime(options = {}, callOptions) {
|
|
662
|
+
return call("dash.ui.pickTime", options, callOptions);
|
|
663
|
+
}
|
|
664
|
+
//#endregion
|
|
202
665
|
//#region src/ui/index.ts
|
|
203
|
-
var ui_exports = /* @__PURE__ */ __exportAll({
|
|
666
|
+
var ui_exports = /* @__PURE__ */ __exportAll({
|
|
667
|
+
alert: () => alert,
|
|
668
|
+
pickDate: () => pickDate,
|
|
669
|
+
pickTime: () => pickTime
|
|
670
|
+
});
|
|
671
|
+
//#endregion
|
|
672
|
+
//#region src/utils/encoding.ts
|
|
673
|
+
const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
674
|
+
const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
675
|
+
const HEX_PATTERN = /^(?:[0-9a-fA-F]{2})*$/;
|
|
676
|
+
const base64 = {
|
|
677
|
+
encode(text) {
|
|
678
|
+
return bytesToBase64(utf8Bytes(text));
|
|
679
|
+
},
|
|
680
|
+
decode(encoded) {
|
|
681
|
+
return utf8Text(base64ToBytes(encoded));
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
const hex = {
|
|
685
|
+
encode(text) {
|
|
686
|
+
return utf8Bytes(text).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
687
|
+
},
|
|
688
|
+
decode(encoded) {
|
|
689
|
+
if (!HEX_PATTERN.test(encoded)) throw new Error(`"${encoded.slice(0, 20)}" isn't hex. Use pairs of 0-9 and a-f.`);
|
|
690
|
+
const bytes = [];
|
|
691
|
+
for (let index = 0; index < encoded.length; index += 2) bytes.push(parseInt(encoded.slice(index, index + 2), 16));
|
|
692
|
+
return utf8Text(bytes);
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
function bytesToBase64(bytes) {
|
|
696
|
+
let encoded = "";
|
|
697
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
698
|
+
const group = bytes.slice(index, index + 3);
|
|
699
|
+
const bits = (group[0] ?? 0) << 16 | (group[1] ?? 0) << 8 | (group[2] ?? 0);
|
|
700
|
+
const sextets = [
|
|
701
|
+
bits >> 18 & 63,
|
|
702
|
+
bits >> 12 & 63,
|
|
703
|
+
bits >> 6 & 63,
|
|
704
|
+
bits & 63
|
|
705
|
+
];
|
|
706
|
+
const characterCount = group.length + 1;
|
|
707
|
+
for (const sextet of sextets.slice(0, characterCount)) encoded += BASE64_ALPHABET[sextet];
|
|
708
|
+
encoded += "=".repeat(4 - characterCount);
|
|
709
|
+
}
|
|
710
|
+
return encoded;
|
|
711
|
+
}
|
|
712
|
+
function base64ToBytes(encoded) {
|
|
713
|
+
if (!BASE64_PATTERN.test(encoded)) throw new Error(`"${encoded.slice(0, 20)}" isn't base64.`);
|
|
714
|
+
const bytes = [];
|
|
715
|
+
for (let index = 0; index < encoded.length; index += 4) {
|
|
716
|
+
const characters = encoded.slice(index, index + 4);
|
|
717
|
+
let bits = 0;
|
|
718
|
+
let padding = 0;
|
|
719
|
+
for (const character of characters) {
|
|
720
|
+
bits <<= 6;
|
|
721
|
+
if (character === "=") padding += 1;
|
|
722
|
+
else bits |= BASE64_ALPHABET.indexOf(character);
|
|
723
|
+
}
|
|
724
|
+
bytes.push(bits >> 16 & 255);
|
|
725
|
+
if (padding < 2) bytes.push(bits >> 8 & 255);
|
|
726
|
+
if (padding < 1) bytes.push(bits & 255);
|
|
727
|
+
}
|
|
728
|
+
return bytes;
|
|
729
|
+
}
|
|
730
|
+
function utf8Bytes(text) {
|
|
731
|
+
const bytes = [];
|
|
732
|
+
for (const character of text) {
|
|
733
|
+
const codePoint = character.codePointAt(0);
|
|
734
|
+
if (codePoint < 128) bytes.push(codePoint);
|
|
735
|
+
else if (codePoint < 2048) bytes.push(192 | codePoint >> 6, 128 | codePoint & 63);
|
|
736
|
+
else if (codePoint < 65536) bytes.push(224 | codePoint >> 12, 128 | codePoint >> 6 & 63, 128 | codePoint & 63);
|
|
737
|
+
else bytes.push(240 | codePoint >> 18, 128 | codePoint >> 12 & 63, 128 | codePoint >> 6 & 63, 128 | codePoint & 63);
|
|
738
|
+
}
|
|
739
|
+
return bytes;
|
|
740
|
+
}
|
|
741
|
+
const MAX_CODE_POINT = 1114111;
|
|
742
|
+
function utf8Text(bytes) {
|
|
743
|
+
let text = "";
|
|
744
|
+
let index = 0;
|
|
745
|
+
while (index < bytes.length) {
|
|
746
|
+
const first = bytes[index];
|
|
747
|
+
const length = sequenceLength(first);
|
|
748
|
+
const continuation = bytes.slice(index + 1, index + length);
|
|
749
|
+
if (length === 0 || !isCompleteContinuation(continuation, length)) {
|
|
750
|
+
text += "�";
|
|
751
|
+
index += 1;
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
let codePoint = firstByteBits(first, length);
|
|
755
|
+
for (const byte of continuation) codePoint = codePoint << 6 | byte & 63;
|
|
756
|
+
if (codePoint > MAX_CODE_POINT) {
|
|
757
|
+
text += "�";
|
|
758
|
+
index += 1;
|
|
759
|
+
continue;
|
|
760
|
+
}
|
|
761
|
+
text += String.fromCodePoint(codePoint);
|
|
762
|
+
index += length;
|
|
763
|
+
}
|
|
764
|
+
return text;
|
|
765
|
+
}
|
|
766
|
+
function sequenceLength(first) {
|
|
767
|
+
if (first < 128) return 1;
|
|
768
|
+
if (first >= 240) return 4;
|
|
769
|
+
if (first >= 224) return 3;
|
|
770
|
+
if (first >= 192) return 2;
|
|
771
|
+
return 0;
|
|
772
|
+
}
|
|
773
|
+
function isCompleteContinuation(continuation, length) {
|
|
774
|
+
if (continuation.length !== length - 1) return false;
|
|
775
|
+
return continuation.every((byte) => (byte & 192) === 128);
|
|
776
|
+
}
|
|
777
|
+
function firstByteBits(first, length) {
|
|
778
|
+
if (length === 1) return first;
|
|
779
|
+
return first & 255 >> length + 1;
|
|
780
|
+
}
|
|
781
|
+
//#endregion
|
|
782
|
+
//#region src/utils/index.ts
|
|
783
|
+
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
784
|
+
base64: () => base64,
|
|
785
|
+
hex: () => hex
|
|
786
|
+
});
|
|
204
787
|
//#endregion
|
|
205
788
|
//#region src/tracked.ts
|
|
206
789
|
function tracked(group, track) {
|
|
207
790
|
const copy = {};
|
|
208
791
|
for (const [name, member] of Object.entries(group)) if (typeof member === "function") {
|
|
209
|
-
const
|
|
792
|
+
const startCall = member;
|
|
210
793
|
copy[name] = (...args) => {
|
|
211
|
-
const
|
|
212
|
-
track(
|
|
213
|
-
return
|
|
794
|
+
const result = startCall(...args);
|
|
795
|
+
if (result instanceof Promise) track(result);
|
|
796
|
+
return result;
|
|
214
797
|
};
|
|
215
798
|
} else copy[name] = tracked(member, track);
|
|
216
799
|
return copy;
|
|
217
800
|
}
|
|
218
801
|
//#endregion
|
|
802
|
+
//#region src/errors.ts
|
|
803
|
+
function isDashError(error, ...codes) {
|
|
804
|
+
if (error instanceof HostError) return codes.length === 0 || codes.includes(error.code);
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
function errorMessage(error) {
|
|
808
|
+
if (error instanceof Error) return error.message;
|
|
809
|
+
if (typeof error === "string" && error) return error;
|
|
810
|
+
return "Something went wrong. Try again.";
|
|
811
|
+
}
|
|
812
|
+
async function unlessCancelled(call) {
|
|
813
|
+
try {
|
|
814
|
+
return await call;
|
|
815
|
+
} catch (error) {
|
|
816
|
+
if (isDashError(error, "cancelled")) return;
|
|
817
|
+
throw error;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
//#endregion
|
|
821
|
+
//#region src/latest.ts
|
|
822
|
+
function latest() {
|
|
823
|
+
let running;
|
|
824
|
+
return (call) => {
|
|
825
|
+
running?.cancel();
|
|
826
|
+
running = call;
|
|
827
|
+
return call;
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
function debounce(milliseconds) {
|
|
831
|
+
const wait = latest();
|
|
832
|
+
return async (dash) => {
|
|
833
|
+
try {
|
|
834
|
+
await wait(dash.system.delay(milliseconds));
|
|
835
|
+
return true;
|
|
836
|
+
} catch (error) {
|
|
837
|
+
if (isDashError(error, "cancelled")) return false;
|
|
838
|
+
throw error;
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
//#endregion
|
|
219
843
|
//#region src/index.ts
|
|
220
844
|
const dash = {
|
|
221
845
|
ui: ui_exports,
|
|
222
846
|
system: system_exports,
|
|
223
847
|
network: network_exports,
|
|
224
|
-
|
|
848
|
+
storage: storage_exports,
|
|
849
|
+
media: media_exports,
|
|
850
|
+
contacts: contacts_exports,
|
|
851
|
+
dot: dot_exports,
|
|
852
|
+
account: account_exports,
|
|
853
|
+
crypto: crypto_exports,
|
|
854
|
+
utils: utils_exports,
|
|
855
|
+
supports
|
|
225
856
|
};
|
|
226
857
|
//#endregion
|
|
227
|
-
export {
|
|
858
|
+
export { DASH_API_SINCE, DASH_API_VERSION, DashError, dash, debounce, errorMessage, isDashError, latest, tracked, unlessCancelled, useHostDashApiVersions, warnAboveDashApiVersion };
|
|
228
859
|
|
|
229
860
|
//# sourceMappingURL=index.js.map
|