lauther-client 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -6
- package/package.json +1 -1
- package/src/index.d.ts +23 -8
- package/src/index.js +23 -10
package/README.md
CHANGED
|
@@ -84,7 +84,8 @@ const { response } = await lauther.approve({
|
|
|
84
84
|
|
|
85
85
|
A request is an approval whose "yes" carries something back: the person taps
|
|
86
86
|
**Share**, the phone does one thing while they watch, and the result rides
|
|
87
|
-
home on the answer.
|
|
87
|
+
home on the answer. Three kinds: where they are, one picture, and a short
|
|
88
|
+
typed answer.
|
|
88
89
|
|
|
89
90
|
```js
|
|
90
91
|
const where = await lauther.requestLocation({
|
|
@@ -105,7 +106,18 @@ if (shot.response === "approve") {
|
|
|
105
106
|
}
|
|
106
107
|
```
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
```js
|
|
110
|
+
const code = await lauther.requestText({
|
|
111
|
+
title: "What is the 6-digit code from your authenticator?",
|
|
112
|
+
placeholder: "6-digit code",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (code.response === "approve") {
|
|
116
|
+
const { text } = code.result; // what they typed
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
All three return `{ id, response, confirmedBy, result, waitedSeconds, expired }`.
|
|
109
121
|
`response` is `"approve"`, `"deny"` or `null`, and `result` is `null` unless
|
|
110
122
|
the person approved. They wait the way `requestApproval()` does: past the
|
|
111
123
|
server's 25 seconds on the **same** request, so the phone still shows one.
|
|
@@ -117,9 +129,14 @@ means the request lapsed on the phone (10 minutes by default; set
|
|
|
117
129
|
`{ lat, lng, accuracy, at }`, with `accuracy` in metres.
|
|
118
130
|
- **Photo** is a JPEG they take or pick, at most 2 MB. You receive a link,
|
|
119
131
|
and **the link works for 7 days**; download it if you want to keep it.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
- **Text** is a short answer they type on the phone: `{ text }`, 1 to 500
|
|
133
|
+
characters. Use it for a code, a choice, a short fact only they know. The
|
|
134
|
+
optional `placeholder` (up to 80 characters) hints at the shape of the
|
|
135
|
+
answer, such as "6-digit code".
|
|
136
|
+
|
|
137
|
+
Options for all three: `title`, `message`, `requireBiometric`, `priority`,
|
|
138
|
+
`expiresIn`, plus `timeoutSeconds` and `pollIntervalMs` for the wait;
|
|
139
|
+
`requestText()` also takes `placeholder`. For
|
|
123
140
|
full control, `request(kind, options)` is the single call behind them (it
|
|
124
141
|
answers within `wait` seconds, 0 to 25), and `poll(id)` also returns `result`
|
|
125
142
|
and `expired`.
|
|
@@ -163,9 +180,10 @@ reported separately rather than collapsed into one flag.
|
|
|
163
180
|
| `push(options)` | `title`, `message`, `priority`, `url`, `path`, `tag`, `icon`, `color`, `sound`, `image` |
|
|
164
181
|
| `approve(options)` | `title`, `message`, `wait` (0–25s), `approveTitle`, `denyTitle`, `requireBiometric`, `priority` |
|
|
165
182
|
| `requestApproval(question, options?)` | Ask and wait, past the 25s cap, on one notification |
|
|
166
|
-
| `request(kind, options?)` | Ask for `"location"` or `"
|
|
183
|
+
| `request(kind, options?)` | Ask for `"location"`, `"photo"` or `"text"`; `title`, `message`, `requireBiometric`, `priority`, `wait`, `expiresIn`, `placeholder` |
|
|
167
184
|
| `requestLocation(options?)` | Ask for a position and wait, past the 25s cap, on one request |
|
|
168
185
|
| `requestPhoto(options?)` | Ask for one picture and wait, past the 25s cap |
|
|
186
|
+
| `requestText(options?)` | Ask a short question and wait for the typed answer, past the 25s cap |
|
|
169
187
|
| `poll(id)` | Ask about an approval or request already started (carries `result` and `expired`) |
|
|
170
188
|
| `ask(question, options?)` | `requestApproval()` reduced to a boolean |
|
|
171
189
|
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -70,10 +70,10 @@ export interface PollResult {
|
|
|
70
70
|
/** How the answer was confirmed, e.g. a biometric check. `null` if not. */
|
|
71
71
|
confirmedBy: string | null;
|
|
72
72
|
/**
|
|
73
|
-
* What a request carried back: a `LocationResult
|
|
74
|
-
* approved, `null` until then, when denied, and for plain approvals.
|
|
73
|
+
* What a request carried back: a `LocationResult`, `PhotoResult` or
|
|
74
|
+
* `TextResult` once approved, `null` until then, when denied, and for plain approvals.
|
|
75
75
|
*/
|
|
76
|
-
result?: LocationResult | PhotoResult | null;
|
|
76
|
+
result?: LocationResult | PhotoResult | TextResult | null;
|
|
77
77
|
/** `true` once a request has lapsed unanswered; there is no point polling on. */
|
|
78
78
|
expired?: boolean;
|
|
79
79
|
}
|
|
@@ -98,10 +98,13 @@ export interface ApprovalOutcome {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/** The kinds of thing a person can be asked to share. */
|
|
101
|
-
export type RequestKind = "location" | "photo";
|
|
101
|
+
export type RequestKind = "location" | "photo" | "text";
|
|
102
102
|
|
|
103
103
|
export interface RequestOptions {
|
|
104
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* The question. Defaults to "Share your location?" / "Take a photo?" /
|
|
106
|
+
* "Answer a question?".
|
|
107
|
+
*/
|
|
105
108
|
title?: string;
|
|
106
109
|
message?: string;
|
|
107
110
|
/** Demand a fingerprint or face before the share goes out. */
|
|
@@ -111,6 +114,11 @@ export interface RequestOptions {
|
|
|
111
114
|
wait?: number;
|
|
112
115
|
/** Seconds the request stays answerable, 60-3600. Defaults to 600. */
|
|
113
116
|
expiresIn?: number;
|
|
117
|
+
/**
|
|
118
|
+
* Text requests only: a hint at the shape of the answer, shown in the
|
|
119
|
+
* field on the phone ("6-digit code"). Up to 80 characters.
|
|
120
|
+
*/
|
|
121
|
+
placeholder?: string;
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
/** One position, as the phone read it a moment before sending. */
|
|
@@ -132,13 +140,18 @@ export interface PhotoResult {
|
|
|
132
140
|
height?: number;
|
|
133
141
|
}
|
|
134
142
|
|
|
143
|
+
/** A typed answer: 1 to 500 characters, trimmed. */
|
|
144
|
+
export interface TextResult {
|
|
145
|
+
text: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
135
148
|
export interface RequestResult {
|
|
136
149
|
ok: true;
|
|
137
150
|
id: string;
|
|
138
151
|
/** `null` means nobody answered in time. Silence is not consent. */
|
|
139
152
|
response: "approve" | "deny" | null;
|
|
140
153
|
/** What was shared. `null` unless the person approved. */
|
|
141
|
-
result: LocationResult | PhotoResult | null;
|
|
154
|
+
result: LocationResult | PhotoResult | TextResult | null;
|
|
142
155
|
}
|
|
143
156
|
|
|
144
157
|
export interface RequestWaitOptions extends Omit<RequestOptions, "wait"> {
|
|
@@ -152,7 +165,7 @@ export interface RequestWaitOptions extends Omit<RequestOptions, "wait"> {
|
|
|
152
165
|
pollIntervalMs?: number;
|
|
153
166
|
}
|
|
154
167
|
|
|
155
|
-
export interface RequestOutcome<R = LocationResult | PhotoResult> {
|
|
168
|
+
export interface RequestOutcome<R = LocationResult | PhotoResult | TextResult> {
|
|
156
169
|
id: string;
|
|
157
170
|
/** `null` means nobody answered, or the request expired. */
|
|
158
171
|
response: "approve" | "deny" | null;
|
|
@@ -191,12 +204,14 @@ export declare class Lauther {
|
|
|
191
204
|
poll(id: string): Promise<PollResult>;
|
|
192
205
|
/** Ask and wait, past the server's 25s cap, on one notification. */
|
|
193
206
|
requestApproval(question: string, options?: WaitOptions): Promise<ApprovalOutcome>;
|
|
194
|
-
/** Ask the person to share `"location"` or a `"
|
|
207
|
+
/** Ask the person to share `"location"`, a `"photo"` or a typed `"text"`; answers within `wait` seconds. */
|
|
195
208
|
request(kind: RequestKind, options?: RequestOptions): Promise<RequestResult>;
|
|
196
209
|
/** Ask for the person's position and wait, past the server's 25s cap. */
|
|
197
210
|
requestLocation(options?: RequestWaitOptions): Promise<RequestOutcome<LocationResult>>;
|
|
198
211
|
/** Ask for one picture and wait, past the server's 25s cap. */
|
|
199
212
|
requestPhoto(options?: RequestWaitOptions): Promise<RequestOutcome<PhotoResult>>;
|
|
213
|
+
/** Ask a short question and wait for the typed answer, past the server's 25s cap. */
|
|
214
|
+
requestText(options?: RequestWaitOptions): Promise<RequestOutcome<TextResult>>;
|
|
200
215
|
/** True only on an explicit Approve; a denial and a timeout are both false. */
|
|
201
216
|
ask(question: string, options?: WaitOptions): Promise<boolean>;
|
|
202
217
|
}
|
package/src/index.js
CHANGED
|
@@ -180,21 +180,21 @@ export class Lauther {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
|
-
* Ask the person to share something from their phone: where they are,
|
|
184
|
-
* picture. The "yes" carries the payload.
|
|
183
|
+
* Ask the person to share something from their phone: where they are, a
|
|
184
|
+
* picture, or a short typed answer. The "yes" carries the payload.
|
|
185
185
|
*
|
|
186
186
|
* Like `approve()` this blocks server-side for up to 25 seconds, and
|
|
187
187
|
* `response` is `"approve"`, `"deny"` or `null`. On an approve, `result`
|
|
188
|
-
* holds what was shared (see `LocationResult
|
|
189
|
-
* anything else it is `null`.
|
|
188
|
+
* holds what was shared (see `LocationResult`, `PhotoResult` and
|
|
189
|
+
* `TextResult`); on anything else it is `null`.
|
|
190
190
|
*
|
|
191
|
-
* @param {"location" | "photo"} kind
|
|
191
|
+
* @param {"location" | "photo" | "text"} kind
|
|
192
192
|
* @param {import("./index.d.ts").RequestOptions} [options]
|
|
193
193
|
* @returns {Promise<import("./index.d.ts").RequestResult>}
|
|
194
194
|
*/
|
|
195
195
|
async request(kind, options) {
|
|
196
196
|
if (!kind) {
|
|
197
|
-
throw new LautherError('request() needs a kind: "location" or "
|
|
197
|
+
throw new LautherError('request() needs a kind: "location", "photo" or "text".');
|
|
198
198
|
}
|
|
199
199
|
const {wait = MAX_WAIT_SECONDS, ...rest} = options ?? {};
|
|
200
200
|
return this.#request("/v1/request", {
|
|
@@ -229,11 +229,24 @@ export class Lauther {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
232
|
+
* Ask a short question and wait for the typed answer: a code, a name, a
|
|
233
|
+
* choice. Same waiting rules as `requestApproval()`. `options.placeholder`
|
|
234
|
+
* (up to 80 characters) hints at the shape of the answer on the phone, for
|
|
235
|
+
* example "6-digit code". `result.text` is 1 to 500 characters.
|
|
235
236
|
*
|
|
236
|
-
* @param {"
|
|
237
|
+
* @param {import("./index.d.ts").RequestWaitOptions} [options]
|
|
238
|
+
* @returns {Promise<import("./index.d.ts").RequestOutcome<import("./index.d.ts").TextResult>>}
|
|
239
|
+
*/
|
|
240
|
+
requestText(options = {}) {
|
|
241
|
+
return this.#requestAndWait("text", options);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Shared by `requestLocation()`, `requestPhoto()` and `requestText()`:
|
|
246
|
+
* start the request, then keep asking about the SAME notification until it
|
|
247
|
+
* is answered, expires, or `timeoutSeconds` runs out.
|
|
248
|
+
*
|
|
249
|
+
* @param {"location" | "photo" | "text"} kind
|
|
237
250
|
* @param {import("./index.d.ts").RequestWaitOptions} options
|
|
238
251
|
*/
|
|
239
252
|
async #requestAndWait(kind, options) {
|