latchkey 2.19.1 → 2.20.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/dist/src/curlInjection.d.ts.map +1 -1
- package/dist/src/curlInjection.js +30 -5
- package/dist/src/curlInjection.js.map +1 -1
- package/dist/src/serviceRegistry.d.ts +18 -0
- package/dist/src/serviceRegistry.d.ts.map +1 -1
- package/dist/src/serviceRegistry.js +32 -12
- package/dist/src/serviceRegistry.js.map +1 -1
- package/dist/src/services/dropbox.d.ts +20 -0
- package/dist/src/services/dropbox.d.ts.map +1 -1
- package/dist/src/services/dropbox.js +143 -24
- package/dist/src/services/dropbox.js.map +1 -1
- package/dist/src/services/google/docs.d.ts +1 -1
- package/dist/src/services/google/docs.d.ts.map +1 -1
- package/dist/src/services/google/docs.js +8 -1
- package/dist/src/services/google/docs.js.map +1 -1
- package/dist/src/services/google/sheets.d.ts +1 -1
- package/dist/src/services/google/sheets.d.ts.map +1 -1
- package/dist/src/services/google/sheets.js +8 -1
- package/dist/src/services/google/sheets.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tests/cli.test.js +86 -2
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/github.test.js +14 -11
- package/dist/tests/github.test.js.map +1 -1
- package/dist/tests/serviceRegistry.test.js +33 -9
- package/dist/tests/serviceRegistry.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"curlInjection.d.ts","sourceRoot":"","sources":["../../src/curlInjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"curlInjection.d.ts","sourceRoot":"","sources":["../../src/curlInjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,qBAAa,wBAAyB,SAAQ,KAAK;;CAKlD;AAED,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,MAAM,CAAC,EAAE,MAAM;CAQ5B;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAET,GAAG,EAAE,MAAM;CAKxB;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,WAAW,EAAE,MAAM;CAKhC;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,WAAW,EAAE,MAAM;CAKhC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,eAAe,EAAE,CACxB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,EAClB,sBAAsB,EAAE,OAAO,KAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,iCAAiC,EAAE,OAAO,CAAC;IACpD,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;CAC9C;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,yBAAyB;AACvC;;;;;;;GAOG;AACH,6BAA6B,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5C,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAyG5B"}
|
|
@@ -107,20 +107,45 @@ requestBodyForPermissionCheck) {
|
|
|
107
107
|
if (url === null) {
|
|
108
108
|
throw new UrlExtractionFailedError();
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
// A single URL can match several services when an API is shared (e.g. the
|
|
111
|
+
// Google Drive files API is used by Drive, Docs, and Sheets). Pick the
|
|
112
|
+
// matching service that actually has usable credentials, preferring one
|
|
113
|
+
// whose credentials are not expired so we avoid unnecessary refreshes and
|
|
114
|
+
// network round-trips. Registration order breaks ties, which lets the
|
|
115
|
+
// canonical owner win when it too has usable credentials.
|
|
116
|
+
const candidates = dependencies.registry.getCandidatesByUrl(url);
|
|
117
|
+
const firstCandidate = candidates[0];
|
|
118
|
+
if (firstCandidate === undefined) {
|
|
112
119
|
if (dependencies.passthroughUnknown) {
|
|
113
120
|
return [...curlArguments];
|
|
114
121
|
}
|
|
115
122
|
throw new NoServiceForUrlError(url);
|
|
116
123
|
}
|
|
117
|
-
let
|
|
118
|
-
|
|
124
|
+
let selection = null;
|
|
125
|
+
let fallbackWithCredentials = null;
|
|
126
|
+
for (const candidate of candidates) {
|
|
127
|
+
const candidateCredentials = apiCredentialStore.get(candidate.name);
|
|
128
|
+
if (candidateCredentials === null) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
fallbackWithCredentials ??= { service: candidate, apiCredentials: candidateCredentials };
|
|
132
|
+
if (candidateCredentials.isExpired() !== true) {
|
|
133
|
+
selection = { service: candidate, apiCredentials: candidateCredentials };
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Fall back to the first candidate that has credentials at all (they may be
|
|
138
|
+
// expired and refreshable below). If nothing has credentials, report against
|
|
139
|
+
// the first matching service for a sensible error message.
|
|
140
|
+
const chosen = selection ?? fallbackWithCredentials;
|
|
141
|
+
if (chosen === null) {
|
|
119
142
|
if (dependencies.passthroughUnknown) {
|
|
120
143
|
return [...curlArguments];
|
|
121
144
|
}
|
|
122
|
-
throw new NoCredentialsForServiceError(
|
|
145
|
+
throw new NoCredentialsForServiceError(firstCandidate.name);
|
|
123
146
|
}
|
|
147
|
+
const service = chosen.service;
|
|
148
|
+
let apiCredentials = chosen.apiCredentials;
|
|
124
149
|
if (apiCredentials.isExpired() === true) {
|
|
125
150
|
apiCredentials = await maybeRefreshCredentials(service, apiCredentials, apiCredentialStore, dependencies.credentialsRefreshDisabled);
|
|
126
151
|
if (apiCredentials.isExpired() === true) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"curlInjection.js","sourceRoot":"","sources":["../../src/curlInjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"curlInjection.js","sourceRoot":"","sources":["../../src/curlInjection.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,24 @@ export declare class ServiceRegistry {
|
|
|
15
15
|
get services(): readonly Service[];
|
|
16
16
|
addService(service: Service): void;
|
|
17
17
|
getByName(name: string): Service | null;
|
|
18
|
+
private matchesUrl;
|
|
19
|
+
/**
|
|
20
|
+
* Return every service whose base API URLs match the given URL, in
|
|
21
|
+
* registration order.
|
|
22
|
+
*
|
|
23
|
+
* Some APIs are shared across services (e.g. the Google Drive files API is
|
|
24
|
+
* used by Drive, Docs, and Sheets), so a single URL can legitimately match
|
|
25
|
+
* more than one service. Callers disambiguate by picking the candidate that
|
|
26
|
+
* actually has usable credentials.
|
|
27
|
+
*/
|
|
28
|
+
getCandidatesByUrl(url: string): readonly Service[];
|
|
29
|
+
/**
|
|
30
|
+
* The primary (first-registered) service matching a URL, or null if none do.
|
|
31
|
+
*
|
|
32
|
+
* The injection pipeline uses {@link getCandidatesByUrl} to consider every
|
|
33
|
+
* match and disambiguate by credential availability; this remains as a
|
|
34
|
+
* convenience for SDK consumers that just want the canonical owner.
|
|
35
|
+
*/
|
|
18
36
|
getByUrl(url: string): Service | null;
|
|
19
37
|
}
|
|
20
38
|
export declare function loadRegisteredServicesIntoServiceRegistry(configPath: string, registry: ServiceRegistry): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serviceRegistry.d.ts","sourceRoot":"","sources":["../../src/serviceRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,OAAO,EA8BR,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,IAAI,EAAE,MAAM;CAMzB;AAID,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;gBAE1B,QAAQ,EAAE,SAAS,OAAO,EAAE;IAIxC,IAAI,QAAQ,IAAI,SAAS,OAAO,EAAE,CAEjC;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IASvC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"serviceRegistry.d.ts","sourceRoot":"","sources":["../../src/serviceRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,OAAO,EA8BR,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,IAAI,EAAE,MAAM;CAMzB;AAID,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;gBAE1B,QAAQ,EAAE,SAAS,OAAO,EAAE;IAIxC,IAAI,QAAQ,IAAI,SAAS,OAAO,EAAE,CAEjC;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IASvC,OAAO,CAAC,UAAU;IAelB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE;IAInD;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;CAGtC;AAED,wBAAgB,yCAAyC,CACvD,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,eAAe,GACxB,IAAI,CAqBN;AAED,eAAO,MAAM,gBAAgB,iBA8B3B,CAAC"}
|
|
@@ -46,22 +46,42 @@ export class ServiceRegistry {
|
|
|
46
46
|
}
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
for (const
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
return service;
|
|
55
|
-
}
|
|
49
|
+
matchesUrl(service, url) {
|
|
50
|
+
for (const baseApiUrl of service.baseApiUrls) {
|
|
51
|
+
if (typeof baseApiUrl === 'string') {
|
|
52
|
+
if (url.startsWith(baseApiUrl)) {
|
|
53
|
+
return true;
|
|
56
54
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (baseApiUrl.test(url)) {
|
|
58
|
+
return true;
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
}
|
|
64
|
-
return
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Return every service whose base API URLs match the given URL, in
|
|
66
|
+
* registration order.
|
|
67
|
+
*
|
|
68
|
+
* Some APIs are shared across services (e.g. the Google Drive files API is
|
|
69
|
+
* used by Drive, Docs, and Sheets), so a single URL can legitimately match
|
|
70
|
+
* more than one service. Callers disambiguate by picking the candidate that
|
|
71
|
+
* actually has usable credentials.
|
|
72
|
+
*/
|
|
73
|
+
getCandidatesByUrl(url) {
|
|
74
|
+
return this._services.filter((service) => this.matchesUrl(service, url));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The primary (first-registered) service matching a URL, or null if none do.
|
|
78
|
+
*
|
|
79
|
+
* The injection pipeline uses {@link getCandidatesByUrl} to consider every
|
|
80
|
+
* match and disambiguate by credential availability; this remains as a
|
|
81
|
+
* convenience for SDK consumers that just want the canonical owner.
|
|
82
|
+
*/
|
|
83
|
+
getByUrl(url) {
|
|
84
|
+
return this.getCandidatesByUrl(url)[0] ?? null;
|
|
65
85
|
}
|
|
66
86
|
}
|
|
67
87
|
export function loadRegisteredServicesIntoServiceRegistry(configPath, registry) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serviceRegistry.js","sourceRoot":"","sources":["../../src/serviceRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAEL,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,EACN,MAAM,EACN,UAAU,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,WAAW,EACX,aAAa,EACb,SAAS,EACT,MAAM,EACN,IAAI,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,iBAAiB,EACjB,OAAO,EACP,KAAK,EACL,IAAI,EACJ,OAAO,GACR,MAAM,qBAAqB,CAAC;AAE7B,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,YAAY,IAAY;QACtB,KAAK,CAAC,4BAA4B,IAAI,mBAAmB,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,IAAY;QACtB,KAAK,CACH,yBAAyB,IAAI,iFAAiF,CAC/G,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAErD,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9D,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,OAAO,eAAe;IACT,SAAS,CAAY;IAEtC,YAAY,QAA4B;QACtC,IAAI,CAAC,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,UAAU,CAAC,OAAgB;QACzB,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1C,MAAM,IAAI,yBAAyB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC1B,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;
|
|
1
|
+
{"version":3,"file":"serviceRegistry.js","sourceRoot":"","sources":["../../src/serviceRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,28 @@ import { ApiCredentials } from '../apiCredentials/base.js';
|
|
|
6
6
|
import { Service, BrowserFollowupServiceSession } from './core/base.js';
|
|
7
7
|
declare class DropboxServiceSession extends BrowserFollowupServiceSession {
|
|
8
8
|
private isLoggedIn;
|
|
9
|
+
private currentAccountUid?;
|
|
9
10
|
onResponse(response: Response): void;
|
|
10
11
|
protected isLoginComplete(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* When more than one account is linked, Dropbox asks which account should own
|
|
14
|
+
* the app before enabling the "Create app" button. Prefer the account the
|
|
15
|
+
* user is currently logged in as, then the work account, then the personal
|
|
16
|
+
* account.
|
|
17
|
+
*/
|
|
18
|
+
private selectOwningAccount;
|
|
11
19
|
protected performBrowserFollowup(context: BrowserContext, _oldCredentials?: ApiCredentials): Promise<ApiCredentials | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Run the authorization-code + PKCE flow against the freshly created app to
|
|
22
|
+
* obtain a refresh token. The redirect URI is registered on the app first
|
|
23
|
+
* because Dropbox requires it to match the authorization request exactly.
|
|
24
|
+
*/
|
|
25
|
+
private authorizeApp;
|
|
26
|
+
/**
|
|
27
|
+
* Register the localhost redirect URI on the app's OAuth 2 settings so the
|
|
28
|
+
* subsequent authorization request is accepted.
|
|
29
|
+
*/
|
|
30
|
+
private registerRedirectUri;
|
|
12
31
|
}
|
|
13
32
|
export declare class Dropbox extends Service {
|
|
14
33
|
readonly name = "dropbox";
|
|
@@ -19,6 +38,7 @@ export declare class Dropbox extends Service {
|
|
|
19
38
|
readonly credentialCheckCurlArguments: readonly ["-X", "POST", "-H", "Content-Type: application/json", "https://api.dropboxapi.com/2/check/user", "--data", "{\"query\":\"foo\"}"];
|
|
20
39
|
setCredentialsExample(serviceName: string): string;
|
|
21
40
|
getSession(appNamePrefix: string): DropboxServiceSession;
|
|
41
|
+
refreshCredentials(apiCredentials: ApiCredentials): Promise<ApiCredentials | null>;
|
|
22
42
|
}
|
|
23
43
|
export declare const DROPBOX: Dropbox;
|
|
24
44
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropbox.d.ts","sourceRoot":"","sources":["../../../src/services/dropbox.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"dropbox.d.ts","sourceRoot":"","sources":["../../../src/services/dropbox.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAQ,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,cAAc,EAAoB,MAAM,2BAA2B,CAAC;AAS7E,OAAO,EACL,OAAO,EACP,6BAA6B,EAI9B,MAAM,gBAAgB,CAAC;AA8BxB,cAAM,qBAAsB,SAAQ,6BAA6B;IAC/D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAAC,CAAS;IAEnC,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IA6BpC,SAAS,CAAC,eAAe,IAAI,OAAO;IAIpC;;;;;OAKG;YACW,mBAAmB;cAwBjB,sBAAsB,CACpC,OAAO,EAAE,cAAc,EACvB,eAAe,CAAC,EAAE,cAAc,GAC/B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA4EjC;;;;OAIG;YACW,YAAY;IAoE1B;;;OAGG;YACW,mBAAmB;CAYlC;AAED,qBAAa,OAAQ,SAAQ,OAAO;IAClC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,WAAW,aAAa;IACjC,QAAQ,CAAC,WAAW,gHAIT;IACX,QAAQ,CAAC,QAAQ,mCAAmC;IACpD,QAAQ,CAAC,IAAI,SAE8F;IAE3G,QAAQ,CAAC,4BAA4B,8IAQ1B;IAEX,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAIzC,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,qBAAqB;IAIxD,kBAAkB,CAAC,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CA6B5F;AAED,eAAO,MAAM,OAAO,SAAgB,CAAC"}
|
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dropbox service implementation.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { OAuthCredentials } from '../apiCredentials/base.js';
|
|
5
5
|
import { typeLikeHuman } from '../playwrightUtils.js';
|
|
6
|
-
import {
|
|
6
|
+
import { exchangeCodeForTokens, generateCodeChallenge, generateCodeVerifier, refreshAccessToken, startOAuthCallbackServer, } from '../oauthUtils.js';
|
|
7
|
+
import { Service, BrowserFollowupServiceSession, LoginFailedError, isBrowserClosedError, LoginCancelledError, } from './core/base.js';
|
|
7
8
|
const DEFAULT_TIMEOUT_MS = 8000;
|
|
9
|
+
// Dropbox deprecated non-expiring tokens, so we run the authorization-code flow
|
|
10
|
+
// with PKCE and `token_access_type=offline` to obtain a refresh token instead
|
|
11
|
+
// of relying on the app console's short-lived "Generate token" button.
|
|
12
|
+
const AUTHORIZE_ENDPOINT = 'https://www.dropbox.com/oauth2/authorize';
|
|
13
|
+
const TOKEN_ENDPOINT = 'https://api.dropboxapi.com/oauth2/token';
|
|
14
|
+
// Scopes enabled on the created app. The same list is requested during
|
|
15
|
+
// authorization so the resulting token carries exactly these permissions.
|
|
16
|
+
const DROPBOX_SCOPES = [
|
|
17
|
+
'account_info.read',
|
|
18
|
+
'files.metadata.write',
|
|
19
|
+
'files.metadata.read',
|
|
20
|
+
'files.content.write',
|
|
21
|
+
'files.content.read',
|
|
22
|
+
'sharing.read',
|
|
23
|
+
'sharing.write',
|
|
24
|
+
'file_requests.read',
|
|
25
|
+
'file_requests.write',
|
|
26
|
+
'contacts.read',
|
|
27
|
+
'contacts.write',
|
|
28
|
+
];
|
|
29
|
+
const IMPLICITLY_GRANTED_SCOPES = ['account_info.read', 'files.metadata.read'];
|
|
30
|
+
// Time allowed for the user to approve the authorization request in the browser.
|
|
31
|
+
const AUTHORIZATION_TIMEOUT_MS = 120000;
|
|
8
32
|
class DropboxServiceSession extends BrowserFollowupServiceSession {
|
|
9
33
|
isLoggedIn = false;
|
|
34
|
+
currentAccountUid;
|
|
10
35
|
onResponse(response) {
|
|
11
36
|
if (this.isLoggedIn) {
|
|
12
37
|
return;
|
|
@@ -26,11 +51,38 @@ class DropboxServiceSession extends BrowserFollowupServiceSession {
|
|
|
26
51
|
if (uidHeader === undefined || uidHeader === '-1') {
|
|
27
52
|
return;
|
|
28
53
|
}
|
|
54
|
+
// Remember the currently active account so the app can be created under the
|
|
55
|
+
// account the user is actually logged in as when several are linked.
|
|
56
|
+
this.currentAccountUid = uidHeader;
|
|
29
57
|
this.isLoggedIn = true;
|
|
30
58
|
}
|
|
31
59
|
isLoginComplete() {
|
|
32
60
|
return this.isLoggedIn;
|
|
33
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* When more than one account is linked, Dropbox asks which account should own
|
|
64
|
+
* the app before enabling the "Create app" button. Prefer the account the
|
|
65
|
+
* user is currently logged in as, then the work account, then the personal
|
|
66
|
+
* account.
|
|
67
|
+
*/
|
|
68
|
+
async selectOwningAccount(page) {
|
|
69
|
+
if (this.currentAccountUid !== undefined) {
|
|
70
|
+
const currentAccount = page.locator(`input[name="_subject_uid"][value="${this.currentAccountUid}"]`);
|
|
71
|
+
if ((await currentAccount.count()) > 0) {
|
|
72
|
+
await currentAccount.check();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const workAccount = page.locator('input#company[name="_subject_uid"]');
|
|
77
|
+
const personalAccount = page.locator('input#personal[name="_subject_uid"]');
|
|
78
|
+
if ((await workAccount.count()) > 0) {
|
|
79
|
+
await workAccount.check();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if ((await personalAccount.count()) > 0) {
|
|
83
|
+
await personalAccount.check();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
34
86
|
async performBrowserFollowup(context, _oldCredentials) {
|
|
35
87
|
const page = context.pages()[0];
|
|
36
88
|
if (!page) {
|
|
@@ -47,26 +99,22 @@ class DropboxServiceSession extends BrowserFollowupServiceSession {
|
|
|
47
99
|
const appNameInput = page.locator('input#app-name');
|
|
48
100
|
await appNameInput.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
49
101
|
await typeLikeHuman(page, appNameInput, appName);
|
|
50
|
-
|
|
102
|
+
await this.selectOwningAccount(page);
|
|
103
|
+
const createButton = page.locator('//button[@id="create-button" and @type="submit" and not(@disabled)]');
|
|
51
104
|
await createButton.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
52
105
|
await createButton.click();
|
|
53
106
|
await page.waitForURL(/https:\/\/www\.dropbox\.com\/developers\/apps\/info\b/, {
|
|
54
107
|
timeout: DEFAULT_TIMEOUT_MS,
|
|
55
108
|
});
|
|
56
|
-
// Configure permissions before
|
|
109
|
+
// Configure permissions before authorizing
|
|
57
110
|
const permissionsTab = page.locator('a.c-tabs__label[data-hash="permissions"]');
|
|
58
111
|
await permissionsTab.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
59
112
|
await permissionsTab.click();
|
|
60
113
|
// Enable all necessary permissions
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
'sharing.write',
|
|
66
|
-
'file_requests.write',
|
|
67
|
-
'contacts.write',
|
|
68
|
-
];
|
|
69
|
-
for (const permissionId of permissionIds) {
|
|
114
|
+
for (const permissionId of DROPBOX_SCOPES) {
|
|
115
|
+
if (IMPLICITLY_GRANTED_SCOPES.includes(permissionId)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
70
118
|
const escapedPermissionId = permissionId.replace(/\./g, '\\.');
|
|
71
119
|
const checkbox = page.locator(`input#${escapedPermissionId}`);
|
|
72
120
|
await checkbox.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
@@ -78,21 +126,81 @@ class DropboxServiceSession extends BrowserFollowupServiceSession {
|
|
|
78
126
|
await submitButton.click();
|
|
79
127
|
// Wait for permissions to be saved
|
|
80
128
|
await page.waitForTimeout(512);
|
|
81
|
-
// Return to Settings tab to
|
|
129
|
+
// Return to Settings tab to read the app key and register the redirect URI
|
|
82
130
|
const settingsTab = page.locator('a.c-tabs__label[data-hash="settings"]');
|
|
83
131
|
await settingsTab.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
84
132
|
await settingsTab.click();
|
|
85
|
-
const
|
|
86
|
-
await
|
|
87
|
-
await
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
133
|
+
const appKeyLocator = page.locator('.app-key');
|
|
134
|
+
await appKeyLocator.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
135
|
+
const appKey = (await appKeyLocator.textContent())?.trim();
|
|
136
|
+
if (!appKey) {
|
|
137
|
+
throw new LoginFailedError('Failed to read Dropbox app key.');
|
|
138
|
+
}
|
|
139
|
+
return await this.authorizeApp(page, appKey);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Run the authorization-code + PKCE flow against the freshly created app to
|
|
143
|
+
* obtain a refresh token. The redirect URI is registered on the app first
|
|
144
|
+
* because Dropbox requires it to match the authorization request exactly.
|
|
145
|
+
*/
|
|
146
|
+
async authorizeApp(page, appKey) {
|
|
147
|
+
const abortController = new AbortController();
|
|
148
|
+
const closeHandler = () => {
|
|
149
|
+
abortController.abort();
|
|
150
|
+
};
|
|
151
|
+
page.on('close', closeHandler);
|
|
152
|
+
page.context().on('close', closeHandler);
|
|
153
|
+
try {
|
|
154
|
+
const { port, codePromise } = await startOAuthCallbackServer(AUTHORIZATION_TIMEOUT_MS, abortController.signal);
|
|
155
|
+
const redirectUri = `http://localhost:${port.toString()}/oauth2callback`;
|
|
156
|
+
await this.registerRedirectUri(page, redirectUri);
|
|
157
|
+
const codeVerifier = generateCodeVerifier();
|
|
158
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
159
|
+
const authorizeUrl = new URL(AUTHORIZE_ENDPOINT);
|
|
160
|
+
authorizeUrl.searchParams.set('client_id', appKey);
|
|
161
|
+
authorizeUrl.searchParams.set('response_type', 'code');
|
|
162
|
+
authorizeUrl.searchParams.set('redirect_uri', redirectUri);
|
|
163
|
+
authorizeUrl.searchParams.set('token_access_type', 'offline');
|
|
164
|
+
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
|
|
165
|
+
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
|
|
166
|
+
authorizeUrl.searchParams.set('scope', DROPBOX_SCOPES.join(' '));
|
|
167
|
+
// The finalize spinner runs in a separate tab that is kept in the
|
|
168
|
+
// foreground. Bring the working page forward so the user can actually see
|
|
169
|
+
// and confirm the authorization dialog.
|
|
170
|
+
await page.bringToFront();
|
|
171
|
+
await page.goto(authorizeUrl.toString());
|
|
172
|
+
const code = await codePromise;
|
|
173
|
+
const tokens = exchangeCodeForTokens(TOKEN_ENDPOINT, code, appKey, '', // public client using PKCE, no secret
|
|
174
|
+
redirectUri, codeVerifier);
|
|
175
|
+
const accessTokenExpiresAt = new Date(Date.now() + tokens.expires_in * 1000).toISOString();
|
|
176
|
+
await page.close();
|
|
177
|
+
return new OAuthCredentials(appKey, '', // public client, no secret stored
|
|
178
|
+
tokens.access_token, tokens.refresh_token, accessTokenExpiresAt);
|
|
93
179
|
}
|
|
94
|
-
|
|
95
|
-
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error instanceof Error && isBrowserClosedError(error)) {
|
|
182
|
+
throw new LoginCancelledError();
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
page.off('close', closeHandler);
|
|
188
|
+
page.context().off('close', closeHandler);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Register the localhost redirect URI on the app's OAuth 2 settings so the
|
|
193
|
+
* subsequent authorization request is accepted.
|
|
194
|
+
*/
|
|
195
|
+
async registerRedirectUri(page, redirectUri) {
|
|
196
|
+
const redirectUriInput = page.locator('#oauth-add-uri-form input[name="oauth_uri"]');
|
|
197
|
+
await redirectUriInput.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
198
|
+
await typeLikeHuman(page, redirectUriInput, redirectUri);
|
|
199
|
+
const addButton = page.locator('#oauth-add-uri-form input[type="submit"]:not([disabled])');
|
|
200
|
+
await addButton.waitFor({ timeout: DEFAULT_TIMEOUT_MS });
|
|
201
|
+
await addButton.click();
|
|
202
|
+
// Wait for the redirect URI to be saved before navigating away.
|
|
203
|
+
await page.waitForTimeout(512);
|
|
96
204
|
}
|
|
97
205
|
}
|
|
98
206
|
export class Dropbox extends Service {
|
|
@@ -121,6 +229,17 @@ export class Dropbox extends Service {
|
|
|
121
229
|
getSession(appNamePrefix) {
|
|
122
230
|
return new DropboxServiceSession(this, appNamePrefix);
|
|
123
231
|
}
|
|
232
|
+
refreshCredentials(apiCredentials) {
|
|
233
|
+
if (!(apiCredentials instanceof OAuthCredentials) || !apiCredentials.refreshToken) {
|
|
234
|
+
return Promise.resolve(null);
|
|
235
|
+
}
|
|
236
|
+
const tokens = refreshAccessToken(TOKEN_ENDPOINT, apiCredentials.refreshToken, apiCredentials.clientId, apiCredentials.clientSecret);
|
|
237
|
+
if (tokens === null) {
|
|
238
|
+
return Promise.resolve(null);
|
|
239
|
+
}
|
|
240
|
+
const accessTokenExpiresAt = new Date(Date.now() + tokens.expires_in * 1000).toISOString();
|
|
241
|
+
return Promise.resolve(new OAuthCredentials(apiCredentials.clientId, apiCredentials.clientSecret, tokens.access_token, tokens.refresh_token ?? apiCredentials.refreshToken, accessTokenExpiresAt, apiCredentials.refreshTokenExpiresAt));
|
|
242
|
+
}
|
|
124
243
|
}
|
|
125
244
|
export const DROPBOX = new Dropbox();
|
|
126
245
|
//# sourceMappingURL=dropbox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropbox.js","sourceRoot":"","sources":["../../../src/services/dropbox.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAkB,
|
|
1
|
+
{"version":3,"file":"dropbox.js","sourceRoot":"","sources":["../../../src/services/dropbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { GoogleService, type GoogleServiceConfig } from './base.js';
|
|
|
2
2
|
export declare class GoogleDocs extends GoogleService {
|
|
3
3
|
readonly name = "google-docs";
|
|
4
4
|
readonly displayName = "Google Docs";
|
|
5
|
-
readonly baseApiUrls: readonly ["https://docs.googleapis.com/"];
|
|
5
|
+
readonly baseApiUrls: readonly ["https://docs.googleapis.com/", RegExp];
|
|
6
6
|
readonly info: string;
|
|
7
7
|
readonly credentialCheckCurlArguments: readonly ["https://www.googleapis.com/drive/v3/files?pageSize=1&fields=files(id)&q=mimeType%3D'application/vnd.google-apps.document'"];
|
|
8
8
|
protected readonly config: GoogleServiceConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../../../src/services/google/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAUpE,qBAAa,UAAW,SAAQ,aAAa;IAC3C,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,iBAAiB;
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../../../src/services/google/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAUpE,qBAAa,UAAW,SAAQ,aAAa;IAC3C,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,iBAAiB;IAKrC,QAAQ,CAAC,WAAW,oDAGT;IACX,QAAQ,CAAC,IAAI,SAG0D;IAEvE,QAAQ,CAAC,4BAA4B,yIAE1B;IAEX,SAAS,CAAC,QAAQ,CAAC,MAAM,sBAAU;CACpC;AAED,eAAO,MAAM,WAAW,YAAmB,CAAC"}
|
|
@@ -9,7 +9,14 @@ const CONFIG = {
|
|
|
9
9
|
export class GoogleDocs extends GoogleService {
|
|
10
10
|
name = 'google-docs';
|
|
11
11
|
displayName = 'Google Docs';
|
|
12
|
-
|
|
12
|
+
// Docs workflows also reach into the Drive files API to find, read, and
|
|
13
|
+
// export documents, so match that subset of the Drive API too. The routing
|
|
14
|
+
// layer resolves the overlap with Google Drive by preferring whichever
|
|
15
|
+
// matching service has usable credentials.
|
|
16
|
+
baseApiUrls = [
|
|
17
|
+
'https://docs.googleapis.com/',
|
|
18
|
+
/^https:\/\/www\.googleapis\.com\/drive\/v\d+\/files\b/,
|
|
19
|
+
];
|
|
13
20
|
info = 'https://developers.google.com/docs/api/reference/rest. ' +
|
|
14
21
|
'If needed, run "latchkey auth browser-prepare google-docs" to create an OAuth client first. ' +
|
|
15
22
|
'It may take a few minutes before the OAuth client is ready to use.';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../../src/services/google/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA4B,MAAM,WAAW,CAAC;AAEpE,MAAM,MAAM,GAAwB;IAClC,IAAI,EAAE,CAAC,qBAAqB,EAAE,sBAAsB,CAAC;IACrD,MAAM,EAAE;QACN,2CAA2C;QAC3C,gDAAgD;KACjD;CACF,CAAC;AAEF,MAAM,OAAO,UAAW,SAAQ,aAAa;IAClC,IAAI,GAAG,aAAa,CAAC;IACrB,WAAW,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../../src/services/google/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA4B,MAAM,WAAW,CAAC;AAEpE,MAAM,MAAM,GAAwB;IAClC,IAAI,EAAE,CAAC,qBAAqB,EAAE,sBAAsB,CAAC;IACrD,MAAM,EAAE;QACN,2CAA2C;QAC3C,gDAAgD;KACjD;CACF,CAAC;AAEF,MAAM,OAAO,UAAW,SAAQ,aAAa;IAClC,IAAI,GAAG,aAAa,CAAC;IACrB,WAAW,GAAG,aAAa,CAAC;IACrC,wEAAwE;IACxE,2EAA2E;IAC3E,uEAAuE;IACvE,2CAA2C;IAClC,WAAW,GAAG;QACrB,8BAA8B;QAC9B,uDAAuD;KAC/C,CAAC;IACF,IAAI,GACX,yDAAyD;QACzD,8FAA8F;QAC9F,oEAAoE,CAAC;IAE9D,4BAA4B,GAAG;QACtC,2HAA2H;KACnH,CAAC;IAEQ,MAAM,GAAG,MAAM,CAAC;CACpC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,UAAU,EAAE,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { GoogleService, type GoogleServiceConfig } from './base.js';
|
|
|
2
2
|
export declare class GoogleSheets extends GoogleService {
|
|
3
3
|
readonly name = "google-sheets";
|
|
4
4
|
readonly displayName = "Google Sheets";
|
|
5
|
-
readonly baseApiUrls: readonly ["https://sheets.googleapis.com/"];
|
|
5
|
+
readonly baseApiUrls: readonly ["https://sheets.googleapis.com/", RegExp];
|
|
6
6
|
readonly info: string;
|
|
7
7
|
readonly credentialCheckCurlArguments: readonly ["https://www.googleapis.com/drive/v3/files?pageSize=1&fields=files(id)&q=mimeType%3D'application/vnd.google-apps.spreadsheet'"];
|
|
8
8
|
protected readonly config: GoogleServiceConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheets.d.ts","sourceRoot":"","sources":["../../../../src/services/google/sheets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAUpE,qBAAa,YAAa,SAAQ,aAAa;IAC7C,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,WAAW,mBAAmB;
|
|
1
|
+
{"version":3,"file":"sheets.d.ts","sourceRoot":"","sources":["../../../../src/services/google/sheets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAUpE,qBAAa,YAAa,SAAQ,aAAa;IAC7C,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,WAAW,mBAAmB;IAKvC,QAAQ,CAAC,WAAW,sDAGT;IACX,QAAQ,CAAC,IAAI,SAG0D;IAEvE,QAAQ,CAAC,4BAA4B,4IAE1B;IAEX,SAAS,CAAC,QAAQ,CAAC,MAAM,sBAAU;CACpC;AAED,eAAO,MAAM,aAAa,cAAqB,CAAC"}
|
|
@@ -9,7 +9,14 @@ const CONFIG = {
|
|
|
9
9
|
export class GoogleSheets extends GoogleService {
|
|
10
10
|
name = 'google-sheets';
|
|
11
11
|
displayName = 'Google Sheets';
|
|
12
|
-
|
|
12
|
+
// Sheets workflows also reach into the Drive files API to find, read, and
|
|
13
|
+
// export spreadsheets, so match that subset of the Drive API too. The
|
|
14
|
+
// routing layer resolves the overlap with Google Drive by preferring
|
|
15
|
+
// whichever matching service has usable credentials.
|
|
16
|
+
baseApiUrls = [
|
|
17
|
+
'https://sheets.googleapis.com/',
|
|
18
|
+
/^https:\/\/www\.googleapis\.com\/drive\/v\d+\/files\b/,
|
|
19
|
+
];
|
|
13
20
|
info = 'https://developers.google.com/sheets/api/reference/rest. ' +
|
|
14
21
|
'If needed, run "latchkey auth browser-prepare google-sheets" to create an OAuth client first. ' +
|
|
15
22
|
'It may take a few minutes before the OAuth client is ready to use.';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheets.js","sourceRoot":"","sources":["../../../../src/services/google/sheets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA4B,MAAM,WAAW,CAAC;AAEpE,MAAM,MAAM,GAAwB;IAClC,IAAI,EAAE,CAAC,uBAAuB,EAAE,sBAAsB,CAAC;IACvD,MAAM,EAAE;QACN,8CAA8C;QAC9C,gDAAgD;KACjD;CACF,CAAC;AAEF,MAAM,OAAO,YAAa,SAAQ,aAAa;IACpC,IAAI,GAAG,eAAe,CAAC;IACvB,WAAW,GAAG,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sheets.js","sourceRoot":"","sources":["../../../../src/services/google/sheets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA4B,MAAM,WAAW,CAAC;AAEpE,MAAM,MAAM,GAAwB;IAClC,IAAI,EAAE,CAAC,uBAAuB,EAAE,sBAAsB,CAAC;IACvD,MAAM,EAAE;QACN,8CAA8C;QAC9C,gDAAgD;KACjD;CACF,CAAC;AAEF,MAAM,OAAO,YAAa,SAAQ,aAAa;IACpC,IAAI,GAAG,eAAe,CAAC;IACvB,WAAW,GAAG,eAAe,CAAC;IACvC,0EAA0E;IAC1E,sEAAsE;IACtE,qEAAqE;IACrE,qDAAqD;IAC5C,WAAW,GAAG;QACrB,gCAAgC;QAChC,uDAAuD;KAC/C,CAAC;IACF,IAAI,GACX,2DAA2D;QAC3D,gGAAgG;QAChG,oEAAoE,CAAC;IAE9D,4BAA4B,GAAG;QACtC,8HAA8H;KACtH,CAAC;IAEQ,MAAM,GAAG,MAAM,CAAC;CACpC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,YAAY,EAAE,CAAC"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "2.
|
|
1
|
+
export declare const VERSION = "2.20.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/src/version.js
CHANGED