botinabox 0.5.1 → 0.5.3
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 +6 -0
- package/dist/chunk-3X3YKI4T.js +357 -0
- package/dist/chunk-D47AIFOD.js +351 -0
- package/dist/chunk-DSNJKNEW.js +328 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +220 -0
- package/dist/connector-B4Mj0P1b.d.ts +79 -0
- package/dist/connectors/google/index.d.ts +40 -18
- package/dist/connectors/google/index.js +69 -309
- package/dist/gmail-connector-2FVYTQJH.js +6 -0
- package/dist/gmail-connector-MNUBRNFM.js +6 -0
- package/dist/gmail-connector-URRFX6A3.js +6 -0
- package/dist/index.d.ts +2 -2
- package/package.json +10 -2
- package/CHANGELOG.md +0 -68
- package/CONTRIBUTING.md +0 -92
package/dist/cli.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import * as readline from "readline";
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import { execSync } from "child_process";
|
|
7
|
+
|
|
8
|
+
// src/update-check.ts
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
import { homedir } from "os";
|
|
12
|
+
var ONE_DAY_MS = 864e5;
|
|
13
|
+
function isNewer(latest, current) {
|
|
14
|
+
const a = latest.split(".").map(Number);
|
|
15
|
+
const b = current.split(".").map(Number);
|
|
16
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
17
|
+
const av = a[i] ?? 0;
|
|
18
|
+
const bv = b[i] ?? 0;
|
|
19
|
+
if (av > bv) return true;
|
|
20
|
+
if (av < bv) return false;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
async function checkForUpdate(pkgName, currentVersion) {
|
|
25
|
+
const cacheDir = join(homedir(), `.${pkgName}`);
|
|
26
|
+
const cachePath = join(cacheDir, "update-check.json");
|
|
27
|
+
try {
|
|
28
|
+
if (existsSync(cachePath)) {
|
|
29
|
+
const cached = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
30
|
+
if (Date.now() - cached.checked < ONE_DAY_MS) {
|
|
31
|
+
return isNewer(cached.latest, currentVersion) ? cached.latest : null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
const res = await fetch(`https://registry.npmjs.org/${pkgName}/latest`, {
|
|
37
|
+
headers: { accept: "application/json" },
|
|
38
|
+
signal: AbortSignal.timeout(5e3)
|
|
39
|
+
});
|
|
40
|
+
if (!res.ok) return null;
|
|
41
|
+
const data = await res.json();
|
|
42
|
+
const latest = data.version;
|
|
43
|
+
try {
|
|
44
|
+
if (!existsSync(cacheDir)) mkdirSync(cacheDir, { recursive: true });
|
|
45
|
+
writeFileSync(cachePath, JSON.stringify({ latest, checked: Date.now() }));
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
return isNewer(latest, currentVersion) ? latest : null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/cli.ts
|
|
52
|
+
function getVersion() {
|
|
53
|
+
try {
|
|
54
|
+
const pkgPath = new URL("../package.json", import.meta.url).pathname;
|
|
55
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
56
|
+
return pkg.version;
|
|
57
|
+
} catch {
|
|
58
|
+
return "unknown";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function main(args) {
|
|
62
|
+
const [command, subcommand, ...rest] = args;
|
|
63
|
+
const version = getVersion();
|
|
64
|
+
if (version !== "unknown") {
|
|
65
|
+
checkForUpdate("botinabox", version).then((latest) => {
|
|
66
|
+
if (latest) {
|
|
67
|
+
process.on("exit", () => {
|
|
68
|
+
console.log(
|
|
69
|
+
`
|
|
70
|
+
Update available: ${version} \u2192 ${latest} \u2014 run "botinabox update" to upgrade`
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}).catch(() => {
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (command === "update") {
|
|
78
|
+
await runUpdate(version);
|
|
79
|
+
} else if (command === "--version" || command === "-v") {
|
|
80
|
+
console.log(version);
|
|
81
|
+
} else if (command === "auth" && subcommand === "google") {
|
|
82
|
+
await authGoogle(rest);
|
|
83
|
+
} else {
|
|
84
|
+
console.log("Usage:");
|
|
85
|
+
console.log(" botinabox auth google <account-email> [options]");
|
|
86
|
+
console.log(" botinabox update Upgrade to the latest version");
|
|
87
|
+
console.log(" botinabox --version Print version");
|
|
88
|
+
console.log("");
|
|
89
|
+
console.log("Options:");
|
|
90
|
+
console.log(" --client-id=<id> Google OAuth client ID");
|
|
91
|
+
console.log(" --client-secret=<secret> Google OAuth client secret");
|
|
92
|
+
console.log(" --credentials=<path> Path to Google credentials JSON");
|
|
93
|
+
console.log(" --db=<path> Path to SQLite database (default: ./data/lattice.db)");
|
|
94
|
+
console.log(" --scopes=<scopes> Comma-separated OAuth scopes");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function runUpdate(currentVersion) {
|
|
99
|
+
console.log(`Current version: ${currentVersion}`);
|
|
100
|
+
const latest = await checkForUpdate("botinabox", currentVersion);
|
|
101
|
+
if (!latest) {
|
|
102
|
+
console.log("Already up to date.");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
console.log(`Updating to ${latest}...`);
|
|
106
|
+
try {
|
|
107
|
+
execSync("npm install -g botinabox@latest", { stdio: "inherit" });
|
|
108
|
+
console.log(`Updated botinabox ${currentVersion} \u2192 ${latest}`);
|
|
109
|
+
} catch {
|
|
110
|
+
console.error("Update failed. Try running manually: npm install -g botinabox@latest");
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function authGoogle(args) {
|
|
115
|
+
const flags = /* @__PURE__ */ new Map();
|
|
116
|
+
let account;
|
|
117
|
+
for (const arg of args) {
|
|
118
|
+
if (arg.startsWith("--")) {
|
|
119
|
+
const [key, ...valParts] = arg.slice(2).split("=");
|
|
120
|
+
flags.set(key, valParts.join("="));
|
|
121
|
+
} else if (!account) {
|
|
122
|
+
account = arg;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!account) {
|
|
126
|
+
console.error("Error: account email is required.");
|
|
127
|
+
console.error(" botinabox auth google <account-email> --client-id=... --client-secret=...");
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
let clientId = flags.get("client-id") ?? process.env.GOOGLE_CLIENT_ID;
|
|
131
|
+
let clientSecret = flags.get("client-secret") ?? process.env.GOOGLE_CLIENT_SECRET;
|
|
132
|
+
const credPath = flags.get("credentials");
|
|
133
|
+
if ((!clientId || !clientSecret) && credPath) {
|
|
134
|
+
if (fs.existsSync(credPath)) {
|
|
135
|
+
const creds = JSON.parse(fs.readFileSync(credPath, "utf-8"));
|
|
136
|
+
const installed = creds.installed ?? creds.web;
|
|
137
|
+
clientId = clientId ?? installed?.client_id;
|
|
138
|
+
clientSecret = clientSecret ?? installed?.client_secret;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (!clientId || !clientSecret) {
|
|
142
|
+
console.error(
|
|
143
|
+
"Error: Google OAuth credentials required.\n Set --client-id and --client-secret, or --credentials=path/to/credentials.json,\n or GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables."
|
|
144
|
+
);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
const defaultScopes = [
|
|
148
|
+
"https://www.googleapis.com/auth/gmail.readonly",
|
|
149
|
+
"https://www.googleapis.com/auth/gmail.send",
|
|
150
|
+
"https://www.googleapis.com/auth/calendar.readonly"
|
|
151
|
+
];
|
|
152
|
+
const scopes = flags.has("scopes") ? flags.get("scopes").split(",") : defaultScopes;
|
|
153
|
+
const dbPath = flags.get("db") ?? process.env.DATABASE_PATH ?? "./data/lattice.db";
|
|
154
|
+
const { DataStore, defineCoreTables } = await import("./index.js");
|
|
155
|
+
const db = new DataStore({ dbPath });
|
|
156
|
+
defineCoreTables(db);
|
|
157
|
+
await db.init();
|
|
158
|
+
const tokenLoader = async (key) => {
|
|
159
|
+
const rows = await db.query("secrets", { where: { name: key } });
|
|
160
|
+
const row = rows.find((r) => r["deleted_at"] == null);
|
|
161
|
+
return row?.["value"] ?? null;
|
|
162
|
+
};
|
|
163
|
+
const tokenSaver = async (key, value) => {
|
|
164
|
+
const rows = await db.query("secrets", { where: { name: key } });
|
|
165
|
+
const existing = rows.find((r) => r["deleted_at"] == null);
|
|
166
|
+
if (existing) {
|
|
167
|
+
await db.update("secrets", { id: existing["id"] }, {
|
|
168
|
+
value,
|
|
169
|
+
type: "oauth2",
|
|
170
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
171
|
+
});
|
|
172
|
+
} else {
|
|
173
|
+
await db.insert("secrets", {
|
|
174
|
+
name: key,
|
|
175
|
+
type: "oauth2",
|
|
176
|
+
value,
|
|
177
|
+
description: `Google OAuth tokens for ${account}`
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const { GoogleGmailConnector } = await import("./gmail-connector-MNUBRNFM.js");
|
|
182
|
+
const connector = new GoogleGmailConnector({ tokenLoader, tokenSaver });
|
|
183
|
+
connector.config = {
|
|
184
|
+
account,
|
|
185
|
+
oauth: { clientId, clientSecret, redirectUri: "urn:ietf:wg:oauth:2.0:oob" },
|
|
186
|
+
scopes
|
|
187
|
+
};
|
|
188
|
+
const codeProvider = async (authUrl) => {
|
|
189
|
+
console.log(`
|
|
190
|
+
Authorize account: ${account}`);
|
|
191
|
+
console.log(`
|
|
192
|
+
Open this URL in your browser:
|
|
193
|
+
|
|
194
|
+
${authUrl}
|
|
195
|
+
`);
|
|
196
|
+
const rl = readline.createInterface({
|
|
197
|
+
input: process.stdin,
|
|
198
|
+
output: process.stdout
|
|
199
|
+
});
|
|
200
|
+
return new Promise((resolve) => {
|
|
201
|
+
rl.question("Enter the authorization code: ", (answer) => {
|
|
202
|
+
rl.close();
|
|
203
|
+
resolve(answer.trim());
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
const result = await connector.authenticate(codeProvider);
|
|
208
|
+
if (result.success) {
|
|
209
|
+
console.log(`
|
|
210
|
+
Tokens saved for ${account}. Connector is ready.`);
|
|
211
|
+
} else {
|
|
212
|
+
console.error(`
|
|
213
|
+
Authentication failed: ${result.error}`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
db.close();
|
|
217
|
+
}
|
|
218
|
+
export {
|
|
219
|
+
main
|
|
220
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Connector types — generic external service integrations. */
|
|
2
|
+
interface ConnectorMeta {
|
|
3
|
+
displayName: string;
|
|
4
|
+
/** Provider identifier, e.g. "google", "trello", "jira", "salesforce" */
|
|
5
|
+
provider: string;
|
|
6
|
+
/** Data type this connector handles, e.g. "email", "calendar", "board", "crm" */
|
|
7
|
+
dataType: string;
|
|
8
|
+
}
|
|
9
|
+
interface SyncOptions {
|
|
10
|
+
/** Only sync records after this ISO 8601 timestamp */
|
|
11
|
+
since?: string;
|
|
12
|
+
/** Provider-specific incremental sync token */
|
|
13
|
+
cursor?: string;
|
|
14
|
+
/** Maximum number of records to fetch */
|
|
15
|
+
limit?: number;
|
|
16
|
+
/** Provider-specific query filters */
|
|
17
|
+
filters?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
interface SyncResult<T = Record<string, unknown>> {
|
|
20
|
+
/** Typed records produced by the connector — consumer decides where to store */
|
|
21
|
+
records: T[];
|
|
22
|
+
/** Next incremental sync token (persist for future calls) */
|
|
23
|
+
cursor?: string;
|
|
24
|
+
/** Whether more records are available (pagination) */
|
|
25
|
+
hasMore: boolean;
|
|
26
|
+
/** Errors encountered during sync (non-fatal per-record failures) */
|
|
27
|
+
errors: Array<{
|
|
28
|
+
id?: string;
|
|
29
|
+
error: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
interface PushResult {
|
|
33
|
+
success: boolean;
|
|
34
|
+
externalId?: string;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
interface AuthResult {
|
|
38
|
+
success: boolean;
|
|
39
|
+
account?: string;
|
|
40
|
+
/** URL the user must visit to authorize (for OAuth flows) */
|
|
41
|
+
authUrl?: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
type ConnectorConfig = Record<string, unknown>;
|
|
45
|
+
/**
|
|
46
|
+
* Generic connector interface for external service integrations.
|
|
47
|
+
*
|
|
48
|
+
* Connectors pull and optionally push data to/from external services
|
|
49
|
+
* (Gmail, Calendar, Trello, Jira, Salesforce, etc.). They produce
|
|
50
|
+
* typed records — the consuming application decides where to store them.
|
|
51
|
+
*
|
|
52
|
+
* @typeParam T - The record type this connector produces/consumes.
|
|
53
|
+
*/
|
|
54
|
+
interface Connector<T = Record<string, unknown>> {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly meta: ConnectorMeta;
|
|
57
|
+
connect(config: ConnectorConfig): Promise<void>;
|
|
58
|
+
disconnect(): Promise<void>;
|
|
59
|
+
healthCheck(): Promise<{
|
|
60
|
+
ok: boolean;
|
|
61
|
+
account?: string;
|
|
62
|
+
error?: string;
|
|
63
|
+
}>;
|
|
64
|
+
/** Pull records from external source */
|
|
65
|
+
sync(options?: SyncOptions): Promise<SyncResult<T>>;
|
|
66
|
+
/** Push a record to external source (optional) */
|
|
67
|
+
push?(payload: T): Promise<PushResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Run the authentication/authorization flow for this connector.
|
|
70
|
+
* For OAuth connectors, this generates the auth URL and exchanges the code for tokens.
|
|
71
|
+
*
|
|
72
|
+
* @param codeProvider - called with the auth URL; must return the authorization code.
|
|
73
|
+
* For CLI flows, this prints the URL and reads from stdin.
|
|
74
|
+
* For programmatic flows, the caller handles the redirect.
|
|
75
|
+
*/
|
|
76
|
+
authenticate?(codeProvider: (authUrl: string) => Promise<string>): Promise<AuthResult>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type { AuthResult as A, ConnectorConfig as C, PushResult as P, SyncOptions as S, Connector as a, ConnectorMeta as b, SyncResult as c };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ConnectorConfig, a as Connector, b as ConnectorMeta, S as SyncOptions, c as SyncResult, P as PushResult } from '../../connector-
|
|
1
|
+
import { C as ConnectorConfig, a as Connector, b as ConnectorMeta, A as AuthResult, S as SyncOptions, c as SyncResult, P as PushResult } from '../../connector-B4Mj0P1b.js';
|
|
2
2
|
|
|
3
3
|
/** Google connector types. */
|
|
4
4
|
|
|
@@ -13,11 +13,26 @@ interface GoogleTokens {
|
|
|
13
13
|
expiry_date?: number;
|
|
14
14
|
token_type: string;
|
|
15
15
|
}
|
|
16
|
+
interface GoogleServiceAccountConfig {
|
|
17
|
+
/** Path to service account key JSON file */
|
|
18
|
+
keyFile?: string;
|
|
19
|
+
/** Inline service account credentials (alternative to keyFile) */
|
|
20
|
+
credentials?: {
|
|
21
|
+
client_email: string;
|
|
22
|
+
private_key: string;
|
|
23
|
+
project_id?: string;
|
|
24
|
+
};
|
|
25
|
+
/** Email of the user to impersonate via domain-wide delegation */
|
|
26
|
+
subject: string;
|
|
27
|
+
}
|
|
16
28
|
interface GoogleConnectorConfig extends ConnectorConfig {
|
|
17
29
|
/** Google account email */
|
|
18
30
|
account: string;
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
/** OAuth2 user auth (requires browser flow) */
|
|
32
|
+
oauth?: GoogleOAuthConfig;
|
|
33
|
+
/** Service account auth (headless, for cloud deployments) */
|
|
34
|
+
serviceAccount?: GoogleServiceAccountConfig;
|
|
35
|
+
scopes?: string[];
|
|
21
36
|
}
|
|
22
37
|
interface EmailAddress {
|
|
23
38
|
name?: string;
|
|
@@ -84,6 +99,11 @@ declare function getAuthUrl(client: OAuth2Client, scopes: string[]): string;
|
|
|
84
99
|
* Exchange an authorization code for tokens.
|
|
85
100
|
*/
|
|
86
101
|
declare function exchangeCode(client: OAuth2Client, code: string): Promise<GoogleTokens>;
|
|
102
|
+
/**
|
|
103
|
+
* Create an authenticated client using a service account with
|
|
104
|
+
* domain-wide delegation (impersonation). No browser flow needed.
|
|
105
|
+
*/
|
|
106
|
+
declare function createServiceAccountClient(config: GoogleServiceAccountConfig, scopes: string[]): Promise<OAuth2Client>;
|
|
87
107
|
/**
|
|
88
108
|
* Load persisted tokens via a generic getter callback.
|
|
89
109
|
*
|
|
@@ -115,21 +135,21 @@ declare function refreshIfNeeded(client: OAuth2Client, tokens: GoogleTokens, sav
|
|
|
115
135
|
*/
|
|
116
136
|
|
|
117
137
|
interface GmailConnectorOpts {
|
|
118
|
-
/** Load persisted tokens for a given account key. */
|
|
119
|
-
tokenLoader
|
|
120
|
-
/** Persist tokens for a given account key. */
|
|
121
|
-
tokenSaver
|
|
138
|
+
/** Load persisted tokens for a given account key (OAuth2 flow only). */
|
|
139
|
+
tokenLoader?: (key: string) => Promise<string | null>;
|
|
140
|
+
/** Persist tokens for a given account key (OAuth2 flow only). */
|
|
141
|
+
tokenSaver?: (key: string, value: string) => Promise<void>;
|
|
122
142
|
}
|
|
123
143
|
declare class GoogleGmailConnector implements Connector<EmailRecord> {
|
|
124
144
|
readonly id = "google-gmail";
|
|
125
145
|
readonly meta: ConnectorMeta;
|
|
126
|
-
private tokenLoader
|
|
127
|
-
private tokenSaver
|
|
146
|
+
private tokenLoader?;
|
|
147
|
+
private tokenSaver?;
|
|
128
148
|
private client;
|
|
129
149
|
private config;
|
|
130
150
|
private tokens;
|
|
131
151
|
private gmail;
|
|
132
|
-
constructor(opts
|
|
152
|
+
constructor(opts?: GmailConnectorOpts);
|
|
133
153
|
connect(config: GoogleConnectorConfig): Promise<void>;
|
|
134
154
|
disconnect(): Promise<void>;
|
|
135
155
|
healthCheck(): Promise<{
|
|
@@ -137,6 +157,7 @@ declare class GoogleGmailConnector implements Connector<EmailRecord> {
|
|
|
137
157
|
account?: string;
|
|
138
158
|
error?: string;
|
|
139
159
|
}>;
|
|
160
|
+
authenticate(codeProvider: (authUrl: string) => Promise<string>): Promise<AuthResult>;
|
|
140
161
|
sync(options?: SyncOptions): Promise<SyncResult<EmailRecord>>;
|
|
141
162
|
/** Incremental sync using Gmail history API. */
|
|
142
163
|
private syncIncremental;
|
|
@@ -156,21 +177,21 @@ declare class GoogleGmailConnector implements Connector<EmailRecord> {
|
|
|
156
177
|
*/
|
|
157
178
|
|
|
158
179
|
interface CalendarConnectorOpts {
|
|
159
|
-
/** Load persisted tokens for a given account key. */
|
|
160
|
-
tokenLoader
|
|
161
|
-
/** Persist tokens for a given account key. */
|
|
162
|
-
tokenSaver
|
|
180
|
+
/** Load persisted tokens for a given account key (OAuth2 flow only). */
|
|
181
|
+
tokenLoader?: (key: string) => Promise<string | null>;
|
|
182
|
+
/** Persist tokens for a given account key (OAuth2 flow only). */
|
|
183
|
+
tokenSaver?: (key: string, value: string) => Promise<void>;
|
|
163
184
|
}
|
|
164
185
|
declare class GoogleCalendarConnector implements Connector<CalendarEventRecord> {
|
|
165
186
|
readonly id = "google-calendar";
|
|
166
187
|
readonly meta: ConnectorMeta;
|
|
167
|
-
private tokenLoader
|
|
168
|
-
private tokenSaver
|
|
188
|
+
private tokenLoader?;
|
|
189
|
+
private tokenSaver?;
|
|
169
190
|
private client;
|
|
170
191
|
private config;
|
|
171
192
|
private tokens;
|
|
172
193
|
private calendar;
|
|
173
|
-
constructor(opts
|
|
194
|
+
constructor(opts?: CalendarConnectorOpts);
|
|
174
195
|
connect(config: GoogleConnectorConfig): Promise<void>;
|
|
175
196
|
disconnect(): Promise<void>;
|
|
176
197
|
healthCheck(): Promise<{
|
|
@@ -178,6 +199,7 @@ declare class GoogleCalendarConnector implements Connector<CalendarEventRecord>
|
|
|
178
199
|
account?: string;
|
|
179
200
|
error?: string;
|
|
180
201
|
}>;
|
|
202
|
+
authenticate(codeProvider: (authUrl: string) => Promise<string>): Promise<AuthResult>;
|
|
181
203
|
sync(options?: SyncOptions): Promise<SyncResult<CalendarEventRecord>>;
|
|
182
204
|
/** Incremental sync using Calendar syncToken. */
|
|
183
205
|
private syncIncremental;
|
|
@@ -187,4 +209,4 @@ declare class GoogleCalendarConnector implements Connector<CalendarEventRecord>
|
|
|
187
209
|
private mapEvent;
|
|
188
210
|
}
|
|
189
211
|
|
|
190
|
-
export { type CalendarAttendee, type CalendarConnectorOpts, type CalendarEventRecord, type EmailAddress, type EmailRecord, type GmailConnectorOpts, GoogleCalendarConnector, type GoogleConnectorConfig, GoogleGmailConnector, type GoogleOAuthConfig, type GoogleTokens, createOAuth2Client, exchangeCode, getAuthUrl, loadTokens, refreshIfNeeded, saveTokens };
|
|
212
|
+
export { type CalendarAttendee, type CalendarConnectorOpts, type CalendarEventRecord, type EmailAddress, type EmailRecord, type GmailConnectorOpts, GoogleCalendarConnector, type GoogleConnectorConfig, GoogleGmailConnector, type GoogleOAuthConfig, type GoogleServiceAccountConfig, type GoogleTokens, createOAuth2Client, createServiceAccountClient, exchangeCode, getAuthUrl, loadTokens, refreshIfNeeded, saveTokens };
|