selfstore 1.8.6 → 1.8.7

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.
@@ -21,19 +21,54 @@ declare function changePassword(input: Blob | Uint8Array, opts: {
21
21
 
22
22
  /**
23
23
  * A client-only DriveAuth: the Google Identity Services token flow, no backend.
24
- * The access token is cached in sessionStorage so a reload reuses it, and a
25
- * silent re-acquisition is attempted when it lapses; if that fails (the Google
26
- * session expired, or third-party cookies are blocked) the Drive target reports
27
- * needs-attention and the user reconnects in one click. For a connection that
28
- * never re-prompts, back the Drive target with a server that holds a refresh
29
- * token instead (a broker implementing the same DriveAuth interface).
24
+ *
25
+ * What this flow can and cannot do, because it decides how often a user is
26
+ * interrupted. Google's browser token flow issues an access token that lives
27
+ * about an hour and NO refresh token - a refresh token requires a client secret,
28
+ * which requires a server. And `requestAccessToken` always opens a popup, even
29
+ * with `prompt: ''`: the popup closes by itself when the grant is still on file,
30
+ * but opening it at all needs a user gesture. So a purely client-side app cannot
31
+ * silently re-acquire a token on page load. What it CAN do:
32
+ *
33
+ * - reuse a token it already has (`persist: 'session'`), so a reload inside the
34
+ * hour asks for nothing at all;
35
+ * - name the account (`hint`), so the popup does not ask which one;
36
+ * - re-grant without the consent screen (`prompt: ''` before `'consent'`) -
37
+ * which is also what stops Google mailing "you granted access" every time.
38
+ *
39
+ * For a connection that never re-prompts, back the Drive target with a server
40
+ * that holds a refresh token instead (a broker implementing this same DriveAuth).
30
41
  */
31
42
 
32
- /** Build a client-only DriveAuth for the given OAuth client id (no backend). */
33
- declare function gisDriveAuth(opts: {
43
+ /** Where the access token survives between requests. */
44
+ type GisTokenPersistence = 'memory' | 'session';
45
+ interface GisDriveAuthOptions {
34
46
  clientId: string;
35
47
  scope?: string;
36
- }): DriveAuth;
48
+ /**
49
+ * The account to re-grant for, so the popup does not ask which one. Pass the
50
+ * address the app remembers (`driveTarget.account()` answers it once
51
+ * connected); a function is read at every request, for a host that only
52
+ * learns it after the first connect.
53
+ */
54
+ hint?: string | (() => string | null | undefined);
55
+ /**
56
+ * Where the access token lives between requests.
57
+ *
58
+ * `'memory'` (the default) keeps it in a closure and nowhere else: a reload
59
+ * has to re-acquire it, which needs a click, but no Drive-scoped credential is
60
+ * ever written to web storage.
61
+ *
62
+ * `'session'` also keeps it in `sessionStorage`, so a reload reuses the token
63
+ * it already has and asks for nothing. That token is a bearer credential for
64
+ * the `drive.file` scope, readable by any script on the origin; it dies with
65
+ * the tab and within the hour. Opt in for an app whose users reload often;
66
+ * leave it alone where an XSS on the origin must find nothing to lift.
67
+ */
68
+ persist?: GisTokenPersistence;
69
+ }
70
+ /** Build a client-only DriveAuth for the given OAuth client id (no backend). */
71
+ declare function gisDriveAuth(opts: GisDriveAuthOptions): DriveAuth;
37
72
 
38
73
  /**
39
74
  * Save a backup blob to disk via the File System Access API, else a download.
@@ -62,4 +97,4 @@ declare function datedName(filename: string, when?: Date): string;
62
97
  /** Prompt the user to pick a backup file from disk. Resolves null if cancelled. */
63
98
  declare function pickFromDisk(): Promise<File | null>;
64
99
 
65
- export { inspect as a, isEncrypted as b, changePassword as c, datedName as d, exportSnapshot as e, gisDriveAuth as g, importSnapshot as i, pickFromDisk as p, saveToDisk as s };
100
+ export { type GisDriveAuthOptions as G, type GisTokenPersistence as a, inspect as b, isEncrypted as c, datedName as d, exportSnapshot as e, changePassword as f, gisDriveAuth as g, importSnapshot as i, pickFromDisk as p, saveToDisk as s };
package/llms.txt CHANGED
@@ -295,8 +295,16 @@ the store's restoreTarget option):
295
295
  - webdavTarget.connect({ kv, config: { url, username, password } }) - the url MUST
296
296
  be https (loopback excepted).
297
297
  - driveTarget.connect({ auth, kv, fileName }) - Google Drive; auth: DriveAuth
298
- (gisDriveAuth({ clientId }) is the client-only reference; a refresh-token
299
- broker makes it permanent). Shared-file primitives: driveTarget.preview /
298
+ (gisDriveAuth({ clientId, hint?, persist? }) is the client-only reference; a
299
+ refresh-token broker makes it permanent). How often it interrupts: the browser
300
+ token flow has NO refresh token and requestAccessToken opens a popup even with
301
+ prompt '' (so it needs a user gesture - no silent re-acquisition on page load).
302
+ persist: 'session' keeps the ~1h token in sessionStorage so a reload asks
303
+ nothing (opt-in: it is a drive.file bearer credential in web storage); hint
304
+ (value or callback, e.g. what driveTarget.account() returned) skips the account
305
+ chooser; reconnect() tries prompt '' before 'consent', because forcing consent
306
+ over a live grant re-asks an answered question and makes Google mail the user
307
+ each time. Shared-file primitives: driveTarget.preview /
300
308
  adopt / findOrCreateOwnFile. My-backups ops (metadata, one call each):
301
309
  listBackups({ auth, nameContains? }) / createBackup({ auth, fileName }) /
302
310
  renameBackup({ auth, fileId, fileName }) / deleteBackup({ auth, fileId }) -
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selfstore",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "Local-first storage for browser apps: an IndexedDB working copy, portable encrypted ZIP backups (AES-256-GCM over Argon2id), durable homes (disk, Google Drive, WebDAV) and a serverless multi-device merge.",
5
5
  "type": "module",
6
6
  "license": "MIT",