@zapier/zapier-sdk 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/dist/index.cjs +2001 -0
- package/dist/index.d.mts +840 -0
- package/dist/index.d.ts +840 -20
- package/dist/index.mjs +1955 -0
- package/package.json +19 -7
- package/src/api/client.ts +84 -16
- package/src/api/types.ts +9 -1
- package/src/auth.ts +19 -287
- package/src/functions/fetch/index.ts +180 -0
- package/src/functions/fetch/info.ts +8 -0
- package/src/functions/fetch/schemas.ts +46 -0
- package/src/functions/findFirstAuthentication/schemas.ts +3 -13
- package/src/functions/findUniqueAuthentication/schemas.ts +3 -13
- package/src/functions/generateTypes/index.ts +15 -0
- package/src/functions/generateTypes/schemas.ts +3 -10
- package/src/functions/getAction/schemas.ts +3 -13
- package/src/functions/getApp/schemas.ts +2 -13
- package/src/functions/getAuthentication/index.ts +0 -1
- package/src/functions/getAuthentication/schemas.ts +3 -17
- package/src/functions/listActions/schemas.ts +3 -13
- package/src/functions/listApps/schemas.ts +2 -13
- package/src/functions/listAuthentications/index.ts +0 -1
- package/src/functions/listAuthentications/schemas.ts +3 -15
- package/src/functions/listFields/schemas.ts +3 -13
- package/src/functions/runAction/index.ts +0 -1
- package/src/functions/runAction/schemas.ts +6 -15
- package/src/index.ts +4 -2
- package/src/plugins/apps/index.ts +35 -9
- package/src/sdk.ts +20 -22
- package/src/types/domain.ts +16 -0
- package/src/types/sdk.ts +13 -1
- package/tsconfig.json +2 -2
- package/tsup.config.ts +21 -0
- package/dist/api/auth.d.ts +0 -8
- package/dist/api/auth.js +0 -29
- package/dist/api/client.d.ts +0 -8
- package/dist/api/client.js +0 -119
- package/dist/api/debug.d.ts +0 -12
- package/dist/api/debug.js +0 -50
- package/dist/api/index.d.ts +0 -28
- package/dist/api/index.js +0 -52
- package/dist/api/polling.d.ts +0 -17
- package/dist/api/polling.js +0 -34
- package/dist/api/types.d.ts +0 -147
- package/dist/api/types.js +0 -9
- package/dist/auth.d.ts +0 -59
- package/dist/auth.js +0 -261
- package/dist/functions/bundleCode/index.d.ts +0 -11
- package/dist/functions/bundleCode/index.js +0 -91
- package/dist/functions/bundleCode/info.d.ts +0 -27
- package/dist/functions/bundleCode/info.js +0 -11
- package/dist/functions/bundleCode/schemas.d.ts +0 -27
- package/dist/functions/bundleCode/schemas.js +0 -22
- package/dist/functions/findFirstAuthentication/index.d.ts +0 -12
- package/dist/functions/findFirstAuthentication/index.js +0 -21
- package/dist/functions/findFirstAuthentication/info.d.ts +0 -30
- package/dist/functions/findFirstAuthentication/info.js +0 -11
- package/dist/functions/findFirstAuthentication/schemas.d.ts +0 -42
- package/dist/functions/findFirstAuthentication/schemas.js +0 -25
- package/dist/functions/findUniqueAuthentication/index.d.ts +0 -13
- package/dist/functions/findUniqueAuthentication/index.js +0 -28
- package/dist/functions/findUniqueAuthentication/info.d.ts +0 -30
- package/dist/functions/findUniqueAuthentication/info.js +0 -11
- package/dist/functions/findUniqueAuthentication/schemas.d.ts +0 -42
- package/dist/functions/findUniqueAuthentication/schemas.js +0 -25
- package/dist/functions/generateTypes/index.d.ts +0 -11
- package/dist/functions/generateTypes/index.js +0 -305
- package/dist/functions/generateTypes/info.d.ts +0 -21
- package/dist/functions/generateTypes/info.js +0 -11
- package/dist/functions/generateTypes/schemas.d.ts +0 -30
- package/dist/functions/generateTypes/schemas.js +0 -14
- package/dist/functions/getAction/index.d.ts +0 -12
- package/dist/functions/getAction/index.js +0 -26
- package/dist/functions/getAction/info.d.ts +0 -18
- package/dist/functions/getAction/info.js +0 -11
- package/dist/functions/getAction/schemas.d.ts +0 -30
- package/dist/functions/getAction/schemas.js +0 -13
- package/dist/functions/getApp/index.d.ts +0 -12
- package/dist/functions/getApp/index.js +0 -37
- package/dist/functions/getApp/info.d.ts +0 -12
- package/dist/functions/getApp/info.js +0 -11
- package/dist/functions/getApp/schemas.d.ts +0 -24
- package/dist/functions/getApp/schemas.js +0 -11
- package/dist/functions/getAuthentication/index.d.ts +0 -13
- package/dist/functions/getAuthentication/index.js +0 -38
- package/dist/functions/getAuthentication/info.d.ts +0 -12
- package/dist/functions/getAuthentication/info.js +0 -11
- package/dist/functions/getAuthentication/schemas.d.ts +0 -26
- package/dist/functions/getAuthentication/schemas.js +0 -16
- package/dist/functions/listActions/index.d.ts +0 -12
- package/dist/functions/listActions/index.js +0 -128
- package/dist/functions/listActions/info.d.ts +0 -15
- package/dist/functions/listActions/info.js +0 -11
- package/dist/functions/listActions/schemas.d.ts +0 -27
- package/dist/functions/listActions/schemas.js +0 -14
- package/dist/functions/listApps/index.d.ts +0 -12
- package/dist/functions/listApps/index.js +0 -50
- package/dist/functions/listApps/info.d.ts +0 -18
- package/dist/functions/listApps/info.js +0 -11
- package/dist/functions/listApps/schemas.d.ts +0 -30
- package/dist/functions/listApps/schemas.js +0 -15
- package/dist/functions/listAuthentications/index.d.ts +0 -12
- package/dist/functions/listAuthentications/index.js +0 -131
- package/dist/functions/listAuthentications/info.d.ts +0 -30
- package/dist/functions/listAuthentications/info.js +0 -11
- package/dist/functions/listAuthentications/schemas.d.ts +0 -44
- package/dist/functions/listAuthentications/schemas.js +0 -25
- package/dist/functions/listFields/index.d.ts +0 -12
- package/dist/functions/listFields/index.js +0 -65
- package/dist/functions/listFields/info.d.ts +0 -24
- package/dist/functions/listFields/info.js +0 -11
- package/dist/functions/listFields/schemas.d.ts +0 -36
- package/dist/functions/listFields/schemas.js +0 -17
- package/dist/functions/runAction/index.d.ts +0 -12
- package/dist/functions/runAction/index.js +0 -86
- package/dist/functions/runAction/info.d.ts +0 -24
- package/dist/functions/runAction/info.js +0 -11
- package/dist/functions/runAction/schemas.d.ts +0 -38
- package/dist/functions/runAction/schemas.js +0 -15
- package/dist/index.js +0 -57
- package/dist/plugins/apps/index.d.ts +0 -8
- package/dist/plugins/apps/index.js +0 -77
- package/dist/plugins/apps/info.d.ts +0 -6
- package/dist/plugins/apps/info.js +0 -13
- package/dist/plugins/apps/types.d.ts +0 -21
- package/dist/plugins/apps/types.js +0 -2
- package/dist/resolvers/actionKey.d.ts +0 -8
- package/dist/resolvers/actionKey.js +0 -20
- package/dist/resolvers/actionType.d.ts +0 -8
- package/dist/resolvers/actionType.js +0 -21
- package/dist/resolvers/appKey.d.ts +0 -6
- package/dist/resolvers/appKey.js +0 -8
- package/dist/resolvers/authenticationId.d.ts +0 -8
- package/dist/resolvers/authenticationId.js +0 -29
- package/dist/resolvers/index.d.ts +0 -39
- package/dist/resolvers/index.js +0 -105
- package/dist/resolvers/inputs.d.ts +0 -7
- package/dist/resolvers/inputs.js +0 -15
- package/dist/schema-utils.d.ts +0 -44
- package/dist/schema-utils.js +0 -76
- package/dist/schemas/Action.d.ts +0 -21
- package/dist/schemas/Action.js +0 -31
- package/dist/schemas/App.d.ts +0 -19
- package/dist/schemas/App.js +0 -32
- package/dist/schemas/Auth.d.ts +0 -27
- package/dist/schemas/Auth.js +0 -42
- package/dist/schemas/Field.d.ts +0 -15
- package/dist/schemas/Field.js +0 -25
- package/dist/sdk.d.ts +0 -6
- package/dist/sdk.js +0 -90
- package/dist/types/domain.d.ts +0 -25
- package/dist/types/domain.js +0 -21
- package/dist/types/events.d.ts +0 -37
- package/dist/types/events.js +0 -8
- package/dist/types/properties.d.ts +0 -21
- package/dist/types/properties.js +0 -52
- package/dist/types/sdk.d.ts +0 -24
- package/dist/types/sdk.js +0 -2
package/package.json
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zapier/zapier-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Complete Zapier SDK - combines all Zapier SDK packages",
|
|
5
|
-
"main": "dist/index.
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"require": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.cjs"
|
|
13
|
+
},
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"default": "./dist/index.mjs"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
7
20
|
"keywords": [
|
|
8
21
|
"zapier",
|
|
9
22
|
"sdk",
|
|
@@ -18,18 +31,17 @@
|
|
|
18
31
|
"access": "restricted"
|
|
19
32
|
},
|
|
20
33
|
"dependencies": {
|
|
21
|
-
"conf": "^14.0.0",
|
|
22
34
|
"esbuild": "^0.25.5",
|
|
23
|
-
"jsonwebtoken": "^9.0.2",
|
|
24
35
|
"zod": "^3.25.67"
|
|
25
36
|
},
|
|
26
37
|
"devDependencies": {
|
|
27
|
-
"@types/jsonwebtoken": "^9.0.10",
|
|
28
38
|
"@types/node": "^24.0.1",
|
|
29
|
-
"
|
|
39
|
+
"tsup": "^8.5.0",
|
|
40
|
+
"typescript": "^5.8.3",
|
|
41
|
+
"@zapier/zapier-sdk-cli-login": "0.3.1"
|
|
30
42
|
},
|
|
31
43
|
"scripts": {
|
|
32
|
-
"build": "
|
|
44
|
+
"build": "tsup",
|
|
33
45
|
"clean": "rm -rf dist",
|
|
34
46
|
"rebuild": "pnpm clean && pnpm build",
|
|
35
47
|
"dev": "tsc --watch",
|
package/src/api/client.ts
CHANGED
|
@@ -14,7 +14,10 @@ import type {
|
|
|
14
14
|
import { getAuthorizationHeader } from "./auth";
|
|
15
15
|
import { createDebugLogger, createDebugFetch } from "./debug";
|
|
16
16
|
import { pollUntilComplete } from "./polling";
|
|
17
|
-
import {
|
|
17
|
+
import { getTokenFromEnvOrConfig } from "../auth";
|
|
18
|
+
|
|
19
|
+
// Set of path prefixes that should be treated as subdomains
|
|
20
|
+
const SUBDOMAIN_PREFIXES = new Set(["relay"]);
|
|
18
21
|
|
|
19
22
|
export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
20
23
|
const {
|
|
@@ -23,6 +26,7 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
23
26
|
getToken,
|
|
24
27
|
debug = false,
|
|
25
28
|
fetch: originalFetch = globalThis.fetch,
|
|
29
|
+
onEvent,
|
|
26
30
|
} = options;
|
|
27
31
|
|
|
28
32
|
const debugLog = createDebugLogger(debug);
|
|
@@ -33,7 +37,23 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
33
37
|
path: string,
|
|
34
38
|
searchParams?: Record<string, string>,
|
|
35
39
|
): string {
|
|
36
|
-
|
|
40
|
+
// Check if this is a path that needs subdomain routing
|
|
41
|
+
const pathSegments = path.split("/").filter(Boolean);
|
|
42
|
+
let finalBaseUrl = baseUrl;
|
|
43
|
+
|
|
44
|
+
if (pathSegments.length > 0 && SUBDOMAIN_PREFIXES.has(pathSegments[0])) {
|
|
45
|
+
// Transform paths to use subdomain routing
|
|
46
|
+
// /prefix/domain/path -> prefix.zapier.com/domain/path
|
|
47
|
+
const subdomain = pathSegments[0];
|
|
48
|
+
const baseUrlObj = new URL(baseUrl);
|
|
49
|
+
baseUrlObj.hostname = `${subdomain}.${baseUrlObj.hostname}`;
|
|
50
|
+
finalBaseUrl = baseUrlObj.toString();
|
|
51
|
+
|
|
52
|
+
// Remove the subdomain prefix from the path
|
|
53
|
+
path = "/" + pathSegments.slice(1).join("/");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const url = new URL(path, finalBaseUrl);
|
|
37
57
|
if (searchParams) {
|
|
38
58
|
Object.entries(searchParams).forEach(([key, value]) => {
|
|
39
59
|
url.searchParams.set(key, value);
|
|
@@ -54,13 +74,16 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
54
74
|
if (options.authRequired !== false) {
|
|
55
75
|
let resolvedToken = token;
|
|
56
76
|
|
|
57
|
-
// Token resolution precedence: explicit token > getToken() > env
|
|
77
|
+
// Token resolution precedence: explicit token > getToken() > env/config fallback
|
|
58
78
|
if (!resolvedToken && getToken) {
|
|
59
79
|
resolvedToken = await getToken();
|
|
60
80
|
}
|
|
61
81
|
|
|
62
82
|
if (!resolvedToken) {
|
|
63
|
-
resolvedToken =
|
|
83
|
+
resolvedToken = await getTokenFromEnvOrConfig({
|
|
84
|
+
onEvent,
|
|
85
|
+
fetch: originalFetch,
|
|
86
|
+
});
|
|
64
87
|
}
|
|
65
88
|
|
|
66
89
|
if (resolvedToken) {
|
|
@@ -75,6 +98,7 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
75
98
|
async function handleResponse(
|
|
76
99
|
response: Response,
|
|
77
100
|
customErrorHandler?: (response: Response) => Error | undefined,
|
|
101
|
+
hadAuthToken?: boolean,
|
|
78
102
|
): Promise<any> {
|
|
79
103
|
if (!response.ok) {
|
|
80
104
|
// Check for custom error handling first
|
|
@@ -85,6 +109,13 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
85
109
|
}
|
|
86
110
|
}
|
|
87
111
|
|
|
112
|
+
// If we get a 4xx error and no auth token was provided, give helpful message
|
|
113
|
+
if (response.status >= 400 && response.status < 500 && !hadAuthToken) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
`Authentication required (HTTP ${response.status}). Please provide a token in options or set ZAPIER_TOKEN environment variable.`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
88
119
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
89
120
|
}
|
|
90
121
|
|
|
@@ -96,6 +127,38 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
96
127
|
}
|
|
97
128
|
}
|
|
98
129
|
|
|
130
|
+
// Plain fetch method that matches the standard fetch signature
|
|
131
|
+
async function plainFetch(
|
|
132
|
+
input: string | URL,
|
|
133
|
+
init?: RequestInit & {
|
|
134
|
+
searchParams?: Record<string, string>;
|
|
135
|
+
authRequired?: boolean;
|
|
136
|
+
customErrorHandler?: (response: Response) => Error | undefined;
|
|
137
|
+
},
|
|
138
|
+
): Promise<Response> {
|
|
139
|
+
const url =
|
|
140
|
+
typeof input === "string" && !input.startsWith("http")
|
|
141
|
+
? buildUrl(input, init?.searchParams)
|
|
142
|
+
: input.toString();
|
|
143
|
+
|
|
144
|
+
const headers = await buildHeaders(init as RequestOptions);
|
|
145
|
+
|
|
146
|
+
// Merge headers from init with our built headers
|
|
147
|
+
const finalHeaders = {
|
|
148
|
+
...headers,
|
|
149
|
+
...(init?.headers
|
|
150
|
+
? init.headers instanceof Headers
|
|
151
|
+
? Object.fromEntries(init.headers.entries())
|
|
152
|
+
: (init.headers as Record<string, string>)
|
|
153
|
+
: {}),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return await fetch(url, {
|
|
157
|
+
...init,
|
|
158
|
+
headers: finalHeaders,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
99
162
|
// Helper to perform HTTP requests with JSON handling
|
|
100
163
|
async function fetchJson(
|
|
101
164
|
method: string,
|
|
@@ -103,21 +166,24 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
103
166
|
data?: any,
|
|
104
167
|
options: RequestOptions = {},
|
|
105
168
|
): Promise<any> {
|
|
106
|
-
const
|
|
107
|
-
const headers = await buildHeaders(options);
|
|
169
|
+
const headers = { ...options.headers };
|
|
108
170
|
|
|
109
171
|
// Add Content-Type for JSON requests with body data
|
|
110
172
|
if (data && typeof data === "object") {
|
|
111
173
|
headers["Content-Type"] = "application/json";
|
|
112
174
|
}
|
|
113
175
|
|
|
114
|
-
const response = await
|
|
176
|
+
const response = await plainFetch(path, {
|
|
115
177
|
method,
|
|
116
|
-
headers,
|
|
117
178
|
body: data ? JSON.stringify(data) : undefined,
|
|
179
|
+
headers,
|
|
180
|
+
searchParams: options.searchParams,
|
|
181
|
+
authRequired: options.authRequired,
|
|
182
|
+
customErrorHandler: options.customErrorHandler,
|
|
118
183
|
});
|
|
119
184
|
|
|
120
|
-
|
|
185
|
+
const hadAuthToken = !!(await buildHeaders(options)).Authorization;
|
|
186
|
+
return handleResponse(response, options.customErrorHandler, hadAuthToken);
|
|
121
187
|
}
|
|
122
188
|
|
|
123
189
|
return {
|
|
@@ -162,13 +228,15 @@ export function createZapierApi(options: ApiClientOptions): ApiClient {
|
|
|
162
228
|
});
|
|
163
229
|
},
|
|
164
230
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
);
|
|
171
|
-
}
|
|
231
|
+
async fetch(
|
|
232
|
+
input: string | URL,
|
|
233
|
+
init?: RequestInit & {
|
|
234
|
+
searchParams?: Record<string, string>;
|
|
235
|
+
authRequired?: boolean;
|
|
236
|
+
customErrorHandler?: (response: Response) => Error | undefined;
|
|
237
|
+
},
|
|
238
|
+
): Promise<Response> {
|
|
239
|
+
return plainFetch(input, init);
|
|
172
240
|
},
|
|
173
241
|
};
|
|
174
242
|
}
|
package/src/api/types.ts
CHANGED
|
@@ -16,6 +16,7 @@ export interface ApiClientOptions {
|
|
|
16
16
|
getToken?: () => Promise<string | undefined>;
|
|
17
17
|
debug?: boolean;
|
|
18
18
|
fetch?: typeof globalThis.fetch;
|
|
19
|
+
onEvent?: (event: any) => void;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export interface ApiClient {
|
|
@@ -24,7 +25,14 @@ export interface ApiClient {
|
|
|
24
25
|
put: (path: string, data?: any, options?: RequestOptions) => Promise<any>;
|
|
25
26
|
delete: (path: string, options?: RequestOptions) => Promise<any>;
|
|
26
27
|
poll: (path: string, options?: PollOptions) => Promise<any>;
|
|
27
|
-
|
|
28
|
+
fetch: (
|
|
29
|
+
input: string | URL,
|
|
30
|
+
init?: RequestInit & {
|
|
31
|
+
searchParams?: Record<string, string>;
|
|
32
|
+
authRequired?: boolean;
|
|
33
|
+
customErrorHandler?: (response: Response) => Error | undefined;
|
|
34
|
+
},
|
|
35
|
+
) => Promise<Response>;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
export interface RequestOptions {
|
package/src/auth.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SDK Authentication Utilities
|
|
3
3
|
*
|
|
4
|
-
* This module provides SDK-level authentication utilities
|
|
5
|
-
* token acquisition
|
|
4
|
+
* This module provides SDK-level authentication utilities focused
|
|
5
|
+
* solely on token acquisition. CLI-specific functionality like login/logout
|
|
6
|
+
* is handled by the @zapier/zapier-sdk-cli-login package.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
|
-
// Import type { RequestOptions } from "./api/types"; // Commented out - not used yet
|
|
9
|
-
|
|
10
|
-
let config: any;
|
|
11
|
-
|
|
12
9
|
// Import event types from common location
|
|
13
10
|
import type { EventCallback } from "./types/events";
|
|
14
11
|
|
|
@@ -27,194 +24,37 @@ export interface AuthOptions {
|
|
|
27
24
|
fetch?: typeof globalThis.fetch;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
|
-
// JWT payload interfaces
|
|
31
|
-
interface JwtPayload {
|
|
32
|
-
payload: Record<string, any>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface LoginData {
|
|
36
|
-
access_token: string;
|
|
37
|
-
refresh_token: string;
|
|
38
|
-
expires_in: number;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Constants needed for token refresh
|
|
42
|
-
const ZAPIER_BASE = "https://zapier.com";
|
|
43
|
-
const LOGIN_CLIENT_ID = "K5eEnRE9TTmSFATdkkWhKF8NOKwoiOnYAyIqJjae";
|
|
44
|
-
const AUTH_MODE_HEADER = "X-Auth";
|
|
45
|
-
|
|
46
|
-
// Utility functions for config management
|
|
47
|
-
function getConfig() {
|
|
48
|
-
if (!config) {
|
|
49
|
-
const ConfModule = require("conf");
|
|
50
|
-
const Conf = ConfModule.default || ConfModule;
|
|
51
|
-
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
52
|
-
}
|
|
53
|
-
return config;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function updateLogin(loginData: LoginData): void {
|
|
57
|
-
const cfg = getConfig();
|
|
58
|
-
cfg.set("login_jwt", loginData.access_token);
|
|
59
|
-
cfg.set("login_refresh_token", loginData.refresh_token);
|
|
60
|
-
cfg.set("login_expires_at", Date.now() + loginData.expires_in * 1000);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function clearLogin(): void {
|
|
64
|
-
const cfg = getConfig();
|
|
65
|
-
cfg.delete("login_jwt");
|
|
66
|
-
cfg.delete("login_refresh_token");
|
|
67
|
-
cfg.delete("login_expires_at");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// JWT utility functions
|
|
71
|
-
function decodeJwtOrThrow(jwt: unknown): JwtPayload {
|
|
72
|
-
if (typeof jwt !== "string") {
|
|
73
|
-
throw new Error("Expected JWT to be a string");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
let jsonwebtoken: any;
|
|
77
|
-
try {
|
|
78
|
-
jsonwebtoken = require("jsonwebtoken");
|
|
79
|
-
} catch {
|
|
80
|
-
throw new Error(
|
|
81
|
-
"jsonwebtoken not available - this function requires CLI dependencies",
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const decodedJwt = jsonwebtoken.decode(jwt, { complete: true });
|
|
86
|
-
|
|
87
|
-
if (!decodedJwt) {
|
|
88
|
-
throw new Error("Could not decode JWT");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (typeof decodedJwt.payload === "string") {
|
|
92
|
-
throw new Error("Did not expect JWT payload to be a string");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return decodedJwt;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
27
|
/**
|
|
99
|
-
*
|
|
100
|
-
* Returns
|
|
28
|
+
* Gets the ZAPIER_TOKEN from environment variables.
|
|
29
|
+
* Returns undefined if not set.
|
|
101
30
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
options: AuthOptions = {},
|
|
105
|
-
): Promise<string> {
|
|
106
|
-
const { onEvent, fetch = globalThis.fetch } = options;
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
onEvent?.({
|
|
110
|
-
type: "auth_refreshing",
|
|
111
|
-
payload: {
|
|
112
|
-
message: "Refreshing your token...",
|
|
113
|
-
operation: "token_refresh",
|
|
114
|
-
},
|
|
115
|
-
timestamp: Date.now(),
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const response = await fetch(`${ZAPIER_BASE}/oauth/token/`, {
|
|
119
|
-
method: "POST",
|
|
120
|
-
headers: {
|
|
121
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
122
|
-
[AUTH_MODE_HEADER]: "no",
|
|
123
|
-
},
|
|
124
|
-
body: new URLSearchParams({
|
|
125
|
-
client_id: LOGIN_CLIENT_ID,
|
|
126
|
-
refresh_token: refreshToken,
|
|
127
|
-
grant_type: "refresh_token",
|
|
128
|
-
}),
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
if (!response.ok) {
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Token refresh failed: ${response.status} ${response.statusText}`,
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const data: LoginData = await response.json();
|
|
138
|
-
|
|
139
|
-
// Update stored login data
|
|
140
|
-
updateLogin(data);
|
|
141
|
-
|
|
142
|
-
onEvent?.({
|
|
143
|
-
type: "auth_success",
|
|
144
|
-
payload: {
|
|
145
|
-
message: "Token refreshed successfully",
|
|
146
|
-
operation: "token_refresh",
|
|
147
|
-
},
|
|
148
|
-
timestamp: Date.now(),
|
|
149
|
-
});
|
|
150
|
-
return data.access_token;
|
|
151
|
-
} catch (error) {
|
|
152
|
-
// If refresh fails, clear stored login
|
|
153
|
-
clearLogin();
|
|
154
|
-
const errorMessage = `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`;
|
|
155
|
-
onEvent?.({
|
|
156
|
-
type: "auth_error",
|
|
157
|
-
payload: {
|
|
158
|
-
message: errorMessage,
|
|
159
|
-
error: errorMessage,
|
|
160
|
-
operation: "token_refresh",
|
|
161
|
-
},
|
|
162
|
-
timestamp: Date.now(),
|
|
163
|
-
});
|
|
164
|
-
throw error;
|
|
165
|
-
}
|
|
31
|
+
export function getTokenFromEnv(): string | undefined {
|
|
32
|
+
return process.env.ZAPIER_TOKEN;
|
|
166
33
|
}
|
|
167
34
|
|
|
168
35
|
/**
|
|
169
|
-
* Attempts to
|
|
170
|
-
*
|
|
171
|
-
*
|
|
36
|
+
* Attempts to get a token by optionally importing from CLI login package.
|
|
37
|
+
* This provides a graceful fallback when the CLI login package is not available.
|
|
38
|
+
*
|
|
39
|
+
* Returns undefined if no valid token is found or CLI package is not available.
|
|
172
40
|
*/
|
|
173
|
-
export async function
|
|
41
|
+
export async function getTokenFromCliLogin(
|
|
174
42
|
options: AuthOptions = {},
|
|
175
43
|
): Promise<string | undefined> {
|
|
176
44
|
try {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const refreshToken = cfg.get("login_refresh_token") as string | undefined;
|
|
181
|
-
const expiresAt = cfg.get("login_expires_at") as number | undefined;
|
|
182
|
-
|
|
183
|
-
// Check if we have all required fields
|
|
184
|
-
if (!jwt || !refreshToken || !expiresAt) {
|
|
185
|
-
return undefined;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Check if token is still valid (with 30 second buffer)
|
|
189
|
-
if (expiresAt > Date.now() + 30 * 1000) {
|
|
190
|
-
return jwt;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Token is expired - attempt to refresh
|
|
194
|
-
try {
|
|
195
|
-
return await refreshJwt(refreshToken, options);
|
|
196
|
-
} catch {
|
|
197
|
-
// If refresh fails, return undefined
|
|
198
|
-
return undefined;
|
|
199
|
-
}
|
|
45
|
+
// Dynamically import the CLI login package if available
|
|
46
|
+
const { getToken } = await import("@zapier/zapier-sdk-cli-login");
|
|
47
|
+
return await getToken(options);
|
|
200
48
|
} catch {
|
|
201
|
-
//
|
|
49
|
+
// CLI login package is not available, return undefined
|
|
202
50
|
return undefined;
|
|
203
51
|
}
|
|
204
52
|
}
|
|
205
53
|
|
|
206
|
-
/**
|
|
207
|
-
* Gets the ZAPIER_TOKEN from environment variables.
|
|
208
|
-
* Returns undefined if not set.
|
|
209
|
-
*/
|
|
210
|
-
export function getTokenFromEnv(): string | undefined {
|
|
211
|
-
return process.env.ZAPIER_TOKEN;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
54
|
/**
|
|
215
55
|
* Attempts to get a token with the following precedence:
|
|
216
56
|
* 1. ZAPIER_TOKEN environment variable
|
|
217
|
-
* 2.
|
|
57
|
+
* 2. CLI login package (if available) with auto-refresh
|
|
218
58
|
*
|
|
219
59
|
* Returns undefined if no valid token is found.
|
|
220
60
|
*/
|
|
@@ -227,114 +67,6 @@ export async function getTokenFromEnvOrConfig(
|
|
|
227
67
|
return envToken;
|
|
228
68
|
}
|
|
229
69
|
|
|
230
|
-
// Second priority: CLI
|
|
231
|
-
return
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Gets the current JWT token, refreshing if necessary.
|
|
236
|
-
* Returns undefined if no valid token is available.
|
|
237
|
-
*/
|
|
238
|
-
export async function getValidJwt(
|
|
239
|
-
options: AuthOptions = {},
|
|
240
|
-
): Promise<string | undefined> {
|
|
241
|
-
try {
|
|
242
|
-
const cfg = getConfig();
|
|
243
|
-
|
|
244
|
-
const jwt = cfg.get("login_jwt") as string | undefined;
|
|
245
|
-
const refreshToken = cfg.get("login_refresh_token") as string | undefined;
|
|
246
|
-
const expiresAt = cfg.get("login_expires_at") as number | undefined;
|
|
247
|
-
|
|
248
|
-
// Check if we have all required fields
|
|
249
|
-
if (!jwt || !refreshToken || !expiresAt) {
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Check if token is still valid (with 30 second buffer)
|
|
254
|
-
if (expiresAt > Date.now() + 30 * 1000) {
|
|
255
|
-
return jwt;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Token is expired - attempt to refresh
|
|
259
|
-
return await refreshJwt(refreshToken, options);
|
|
260
|
-
} catch {
|
|
261
|
-
return undefined;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Gets the logged-in user information from JWT token.
|
|
267
|
-
* Automatically refreshes token if expired.
|
|
268
|
-
*/
|
|
269
|
-
export async function getLoggedInUser(options: AuthOptions = {}): Promise<{
|
|
270
|
-
accountId: number;
|
|
271
|
-
customUserId: number;
|
|
272
|
-
email: string;
|
|
273
|
-
}> {
|
|
274
|
-
const jwt = await getValidJwt(options);
|
|
275
|
-
|
|
276
|
-
if (!jwt) {
|
|
277
|
-
throw new Error(
|
|
278
|
-
"No valid authentication token available. Please login first.",
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
let decodedJwt = decodeJwtOrThrow(jwt);
|
|
283
|
-
|
|
284
|
-
if (decodedJwt.payload["sub_type"] == "service") {
|
|
285
|
-
decodedJwt = decodeJwtOrThrow(decodedJwt.payload["njwt"]);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (typeof decodedJwt.payload["zap:acc"] !== "string") {
|
|
289
|
-
throw new Error("JWT payload does not contain accountId");
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const accountId = parseInt(decodedJwt.payload["zap:acc"], 10);
|
|
293
|
-
if (isNaN(accountId)) {
|
|
294
|
-
throw new Error("JWT accountId is not a number");
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (
|
|
298
|
-
decodedJwt.payload["sub_type"] !== "customuser" ||
|
|
299
|
-
typeof decodedJwt.payload["sub"] !== "string"
|
|
300
|
-
) {
|
|
301
|
-
throw new Error("JWT payload does not contain customUserId");
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const customUserId = parseInt(decodedJwt.payload["sub"], 10);
|
|
305
|
-
if (isNaN(customUserId)) {
|
|
306
|
-
throw new Error("JWT customUserId is not a number");
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const email = decodedJwt.payload["zap:uname"];
|
|
310
|
-
if (typeof email !== "string") {
|
|
311
|
-
throw new Error("JWT payload does not contain email");
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return {
|
|
315
|
-
accountId,
|
|
316
|
-
customUserId,
|
|
317
|
-
email,
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Clears stored login information.
|
|
323
|
-
*/
|
|
324
|
-
export function logout(options: Pick<AuthOptions, "onEvent"> = {}): void {
|
|
325
|
-
const { onEvent } = options;
|
|
326
|
-
clearLogin();
|
|
327
|
-
onEvent?.({
|
|
328
|
-
type: "auth_logout",
|
|
329
|
-
payload: { message: "Logged out successfully", operation: "logout" },
|
|
330
|
-
timestamp: Date.now(),
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Gets the path to the configuration file.
|
|
336
|
-
*/
|
|
337
|
-
export function getConfigPath(): string {
|
|
338
|
-
const cfg = getConfig();
|
|
339
|
-
return cfg.path;
|
|
70
|
+
// Second priority: CLI login package (if available)
|
|
71
|
+
return getTokenFromCliLogin(options);
|
|
340
72
|
}
|