@zapier/zapier-sdk 0.15.4 → 0.15.8

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/api/auth.d.ts.map +1 -1
  3. package/dist/api/auth.js +14 -4
  4. package/dist/api/auth.test.d.ts +2 -0
  5. package/dist/api/auth.test.d.ts.map +1 -0
  6. package/dist/api/auth.test.js +220 -0
  7. package/dist/api/client.d.ts.map +1 -1
  8. package/dist/api/client.js +18 -32
  9. package/dist/api/client.methods.test.d.ts +2 -0
  10. package/dist/api/client.methods.test.d.ts.map +1 -0
  11. package/dist/api/client.methods.test.js +158 -0
  12. package/dist/api/client.test.js +27 -11
  13. package/dist/api/router.d.ts +16 -0
  14. package/dist/api/router.d.ts.map +1 -0
  15. package/dist/api/router.js +37 -0
  16. package/dist/api/router.test.d.ts +2 -0
  17. package/dist/api/router.test.d.ts.map +1 -0
  18. package/dist/api/router.test.js +109 -0
  19. package/dist/auth.d.ts +15 -0
  20. package/dist/auth.d.ts.map +1 -1
  21. package/dist/auth.js +25 -0
  22. package/dist/index.cjs +246 -72
  23. package/dist/index.d.mts +402 -241
  24. package/dist/index.mjs +246 -73
  25. package/dist/plugins/eventEmission/index.d.ts.map +1 -1
  26. package/dist/plugins/eventEmission/index.js +9 -5
  27. package/dist/plugins/eventEmission/index.test.js +161 -0
  28. package/dist/plugins/getAuthentication/index.d.ts +2 -5
  29. package/dist/plugins/getAuthentication/index.d.ts.map +1 -1
  30. package/dist/plugins/getAuthentication/index.js +3 -24
  31. package/dist/plugins/getAuthentication/index.test.js +32 -144
  32. package/dist/plugins/getAuthentication/schemas.d.ts +4 -13
  33. package/dist/plugins/getAuthentication/schemas.d.ts.map +1 -1
  34. package/dist/plugins/getAuthentication/schemas.js +1 -11
  35. package/dist/sdk.d.ts +1 -1
  36. package/dist/temporary-internal-core/handlers/getAuthentication.d.ts +94 -0
  37. package/dist/temporary-internal-core/handlers/getAuthentication.d.ts.map +1 -0
  38. package/dist/temporary-internal-core/handlers/getAuthentication.js +68 -0
  39. package/dist/temporary-internal-core/handlers/getAuthentication.test.d.ts +2 -0
  40. package/dist/temporary-internal-core/handlers/getAuthentication.test.d.ts.map +1 -0
  41. package/dist/temporary-internal-core/handlers/getAuthentication.test.js +248 -0
  42. package/dist/temporary-internal-core/handlers/listApps.js +1 -1
  43. package/dist/temporary-internal-core/index.d.ts +2 -0
  44. package/dist/temporary-internal-core/index.d.ts.map +1 -1
  45. package/dist/temporary-internal-core/index.js +2 -0
  46. package/dist/temporary-internal-core/schemas/authentications/index.d.ts +454 -0
  47. package/dist/temporary-internal-core/schemas/authentications/index.d.ts.map +1 -0
  48. package/dist/temporary-internal-core/schemas/authentications/index.js +96 -0
  49. package/dist/temporary-internal-core/schemas/errors/index.d.ts +139 -0
  50. package/dist/temporary-internal-core/schemas/errors/index.d.ts.map +1 -0
  51. package/dist/temporary-internal-core/schemas/errors/index.js +129 -0
  52. package/dist/temporary-internal-core/utils/app-locators.d.ts +0 -20
  53. package/dist/temporary-internal-core/utils/app-locators.d.ts.map +1 -1
  54. package/dist/temporary-internal-core/utils/app-locators.js +1 -45
  55. package/dist/temporary-internal-core/utils/string-utils.d.ts +28 -0
  56. package/dist/temporary-internal-core/utils/string-utils.d.ts.map +1 -0
  57. package/dist/temporary-internal-core/utils/string-utils.js +52 -0
  58. package/dist/temporary-internal-core/utils/transformations.d.ts +14 -0
  59. package/dist/temporary-internal-core/utils/transformations.d.ts.map +1 -1
  60. package/dist/temporary-internal-core/utils/transformations.js +37 -1
  61. package/package.json +1 -1
@@ -0,0 +1,16 @@
1
+ import { type Handler } from "../temporary-internal-core";
2
+ export interface Route {
3
+ method: string;
4
+ pattern: RegExp;
5
+ handler: Handler<any, any, any>;
6
+ paramMap: string[];
7
+ }
8
+ export declare function findMatchingRoute(routeList: Route[], method: string, path: string): {
9
+ handler: Handler<any, any, any>;
10
+ params: Record<string, string>;
11
+ } | null;
12
+ export declare function matchRoute(method: string, path: string): {
13
+ handler: Handler<any, any, any>;
14
+ params: Record<string, string>;
15
+ } | null;
16
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/api/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EACb,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAiBD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,KAAK,EAAE,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM;;;SAsBb;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;SAEtD"}
@@ -0,0 +1,37 @@
1
+ import { handleListApps, handleGetAuthentication, } from "../temporary-internal-core";
2
+ const routes = [
3
+ {
4
+ method: "GET",
5
+ pattern: /^\/api\/v0\/apps$/,
6
+ handler: handleListApps,
7
+ paramMap: [],
8
+ },
9
+ {
10
+ method: "GET",
11
+ pattern: /^\/api\/v0\/authentications\/([^\/]+)$/,
12
+ handler: handleGetAuthentication,
13
+ paramMap: ["authenticationId"],
14
+ },
15
+ ];
16
+ export function findMatchingRoute(routeList, method, path) {
17
+ for (const route of routeList) {
18
+ if (route.method !== method) {
19
+ continue;
20
+ }
21
+ const match = path.match(route.pattern);
22
+ if (match) {
23
+ const params = {};
24
+ route.paramMap.forEach((name, index) => {
25
+ params[name] = match[index + 1];
26
+ });
27
+ return {
28
+ handler: route.handler,
29
+ params,
30
+ };
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+ export function matchRoute(method, path) {
36
+ return findMatchingRoute(routes, method, path);
37
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=router.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.test.d.ts","sourceRoot":"","sources":["../../src/api/router.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { matchRoute, findMatchingRoute } from "./router";
3
+ import { handleListApps, handleGetAuthentication, } from "../temporary-internal-core";
4
+ describe("Router", () => {
5
+ describe("matchRoute (Integration)", () => {
6
+ it("should match GET /api/v0/apps", () => {
7
+ const match = matchRoute("GET", "/api/v0/apps");
8
+ expect(match).not.toBeNull();
9
+ expect(match?.handler).toBe(handleListApps);
10
+ expect(match?.params).toEqual({});
11
+ });
12
+ it("should match GET /api/v0/authentications/:authenticationId", () => {
13
+ const match = matchRoute("GET", "/api/v0/authentications/12345");
14
+ expect(match).not.toBeNull();
15
+ expect(match?.handler).toBe(handleGetAuthentication);
16
+ expect(match?.params).toEqual({ authenticationId: "12345" });
17
+ });
18
+ it("should not match POST /api/v0/apps", () => {
19
+ const match = matchRoute("POST", "/api/v0/apps");
20
+ expect(match).toBeNull();
21
+ });
22
+ it("should not match unknown paths", () => {
23
+ expect(matchRoute("GET", "/api/v0/unknown")).toBeNull();
24
+ expect(matchRoute("GET", "/")).toBeNull();
25
+ });
26
+ it("should not match partial paths if regex is anchored", () => {
27
+ // The regex is /^\/api\/v0\/apps$/ so it shouldn't match suffix
28
+ expect(matchRoute("GET", "/api/v0/apps/something")).toBeNull();
29
+ });
30
+ });
31
+ describe("findMatchingRoute (Unit)", () => {
32
+ const mockHandler = vi.fn();
33
+ const testRoutes = [
34
+ {
35
+ method: "GET",
36
+ pattern: /^\/items$/,
37
+ handler: mockHandler,
38
+ paramMap: [],
39
+ },
40
+ {
41
+ method: "GET",
42
+ pattern: /^\/items\/(\d+)$/,
43
+ handler: mockHandler,
44
+ paramMap: ["id"],
45
+ },
46
+ {
47
+ method: "POST",
48
+ pattern: /^\/items$/,
49
+ handler: mockHandler,
50
+ paramMap: [],
51
+ },
52
+ {
53
+ method: "GET",
54
+ pattern: /^\/users\/(\w+)\/posts\/(\d+)$/,
55
+ handler: mockHandler,
56
+ paramMap: ["userId", "postId"],
57
+ },
58
+ ];
59
+ it("should match exact path", () => {
60
+ const match = findMatchingRoute(testRoutes, "GET", "/items");
61
+ expect(match).not.toBeNull();
62
+ expect(match?.handler).toBe(mockHandler);
63
+ expect(match?.params).toEqual({});
64
+ });
65
+ it("should extract single parameter", () => {
66
+ const match = findMatchingRoute(testRoutes, "GET", "/items/123");
67
+ expect(match).not.toBeNull();
68
+ expect(match?.params).toEqual({ id: "123" });
69
+ });
70
+ it("should extract multiple parameters", () => {
71
+ const match = findMatchingRoute(testRoutes, "GET", "/users/alice/posts/456");
72
+ expect(match).not.toBeNull();
73
+ expect(match?.params).toEqual({ userId: "alice", postId: "456" });
74
+ });
75
+ it("should respect HTTP method", () => {
76
+ // GET /items exists
77
+ expect(findMatchingRoute(testRoutes, "GET", "/items")).not.toBeNull();
78
+ // POST /items exists
79
+ expect(findMatchingRoute(testRoutes, "POST", "/items")).not.toBeNull();
80
+ // PUT /items does not exist
81
+ expect(findMatchingRoute(testRoutes, "PUT", "/items")).toBeNull();
82
+ });
83
+ it("should not match if regex does not match", () => {
84
+ // /items/abc does not match /^\/items\/(\d+)$/ (\d+ is digits only)
85
+ expect(findMatchingRoute(testRoutes, "GET", "/items/abc")).toBeNull();
86
+ });
87
+ it("should handle empty route list", () => {
88
+ expect(findMatchingRoute([], "GET", "/anything")).toBeNull();
89
+ });
90
+ it("should return first matching route", () => {
91
+ const overlappingRoutes = [
92
+ {
93
+ method: "GET",
94
+ pattern: /^\/overlapping$/,
95
+ handler: mockHandler,
96
+ paramMap: [],
97
+ },
98
+ {
99
+ method: "GET",
100
+ pattern: /^\/overlapping$/, // duplicate pattern
101
+ handler: () => Promise.resolve("second"),
102
+ paramMap: [],
103
+ },
104
+ ];
105
+ const match = findMatchingRoute(overlappingRoutes, "GET", "/overlapping");
106
+ expect(match?.handler).toBe(mockHandler); // Should match the first one
107
+ });
108
+ });
109
+ });
package/dist/auth.d.ts CHANGED
@@ -14,6 +14,10 @@ export interface AuthOptions {
14
14
  authBaseUrl?: string;
15
15
  authClientId?: string;
16
16
  }
17
+ export interface ResolveAuthTokenOptions extends AuthOptions {
18
+ token?: string;
19
+ getToken?: () => Promise<string | undefined> | string | undefined;
20
+ }
17
21
  /**
18
22
  * Gets the ZAPIER_TOKEN from environment variables.
19
23
  * Returns undefined if not set.
@@ -34,4 +38,15 @@ export declare function getTokenFromCliLogin(options?: AuthOptions): Promise<str
34
38
  * Returns undefined if no valid token is found.
35
39
  */
36
40
  export declare function getTokenFromEnvOrConfig(options?: AuthOptions): Promise<string | undefined>;
41
+ /**
42
+ * Resolves an auth token from all possible sources with the following precedence:
43
+ * 1. Explicitly provided token in options
44
+ * 2. Token from getToken callback in options
45
+ * 3. ZAPIER_TOKEN environment variable
46
+ * 4. CLI login package (if available)
47
+ *
48
+ * This is the canonical token resolution logic used throughout the SDK.
49
+ * Returns undefined if no valid token is found.
50
+ */
51
+ export declare function resolveAuthToken(options?: ResolveAuthTokenOptions): Promise<string | undefined>;
37
52
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,YAAY,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,aAAa,GACd,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpD;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,YAAY,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,aAAa,GACd,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAwB,SAAQ,WAAW;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;CACnE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpD;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgB7B"}
package/dist/auth.js CHANGED
@@ -45,3 +45,28 @@ export async function getTokenFromEnvOrConfig(options = {}) {
45
45
  // Second priority: CLI login package (if available)
46
46
  return getTokenFromCliLogin(options);
47
47
  }
48
+ /**
49
+ * Resolves an auth token from all possible sources with the following precedence:
50
+ * 1. Explicitly provided token in options
51
+ * 2. Token from getToken callback in options
52
+ * 3. ZAPIER_TOKEN environment variable
53
+ * 4. CLI login package (if available)
54
+ *
55
+ * This is the canonical token resolution logic used throughout the SDK.
56
+ * Returns undefined if no valid token is found.
57
+ */
58
+ export async function resolveAuthToken(options = {}) {
59
+ // First priority: explicitly provided token
60
+ if (options.token) {
61
+ return options.token;
62
+ }
63
+ // Second priority: getToken callback
64
+ if (options.getToken) {
65
+ const token = await options.getToken();
66
+ if (token) {
67
+ return token;
68
+ }
69
+ }
70
+ // Third and fourth priorities: environment variable or CLI login
71
+ return getTokenFromEnvOrConfig(options);
72
+ }
package/dist/index.cjs CHANGED
@@ -2305,49 +2305,68 @@ var getActionPlugin = ({ sdk }) => {
2305
2305
  }
2306
2306
  };
2307
2307
  };
2308
- var GetAuthenticationSchema = zod.z.object({
2308
+ var AuthenticationSchema2 = zod.z.object({
2309
+ id: zod.z.number(),
2310
+ date: zod.z.string(),
2311
+ lastchanged: zod.z.string().optional(),
2312
+ account_id: zod.z.number(),
2313
+ customuser_id: zod.z.number().optional(),
2314
+ selected_api: zod.z.string(),
2315
+ destination_selected_api: zod.z.string().nullable().optional(),
2316
+ is_invite_only: zod.z.boolean(),
2317
+ is_private: zod.z.boolean(),
2318
+ shared_with_all: zod.z.boolean(),
2319
+ is_stale: zod.z.string().optional(),
2320
+ is_shared: zod.z.string().optional(),
2321
+ marked_stale_at: zod.z.string().nullable().optional(),
2322
+ label: zod.z.string().nullable().optional(),
2323
+ identifier: zod.z.string().nullable().optional(),
2324
+ title: zod.z.string().nullable().optional(),
2325
+ url: zod.z.string().optional(),
2326
+ groups: zod.z.string().optional(),
2327
+ members: zod.z.string().optional(),
2328
+ permissions: zod.z.record(zod.z.boolean()).optional()
2329
+ });
2330
+ zod.z.object({
2331
+ count: zod.z.number(),
2332
+ next: zod.z.string().nullable().optional(),
2333
+ previous: zod.z.string().nullable().optional(),
2334
+ results: zod.z.array(AuthenticationSchema2)
2335
+ });
2336
+ var AuthenticationItemSchema2 = AuthenticationSchema2.omit({
2337
+ selected_api: true,
2338
+ customuser_id: true
2339
+ }).extend({
2340
+ // Renamed fields
2341
+ implementation_id: zod.z.string().optional(),
2342
+ user_id: zod.z.number().optional(),
2343
+ // Mapped fields (originals preserved in ...restOfAuth)
2344
+ is_expired: zod.z.string().optional(),
2345
+ expired_at: zod.z.string().nullable().optional(),
2346
+ // Computed fields
2347
+ app_key: zod.z.string().optional(),
2348
+ app_version: zod.z.string().optional()
2349
+ });
2350
+ var GetAuthenticationOptionsSchema = zod.z.object({
2309
2351
  authenticationId: zod.z.number().int().positive().describe("Authentication ID to retrieve")
2310
2352
  }).describe("Get a specific authentication by ID");
2353
+ var GetAuthenticationHandlerRequestSchema = zod.z.object({
2354
+ authenticationId: zod.z.union([zod.z.string(), zod.z.number()]).describe("Authentication ID - string from searchParams or number")
2355
+ }).transform((data) => ({
2356
+ authenticationId: typeof data.authenticationId === "string" ? parseInt(data.authenticationId, 10) : data.authenticationId
2357
+ }));
2358
+ zod.z.object({
2359
+ data: zod.z.lazy(() => AuthenticationItemSchema2)
2360
+ });
2311
2361
 
2312
2362
  // src/plugins/getAuthentication/index.ts
2313
2363
  var getAuthenticationPlugin = ({ context }) => {
2314
2364
  const getAuthentication = createFunction(async function getAuthentication2(options) {
2315
2365
  const { api } = context;
2316
- const { authenticationId } = options;
2317
- const data = await api.get(
2318
- `/zapier/api/v4/authentications/${authenticationId}/`,
2319
- {
2320
- customErrorHandler: ({ status }) => {
2321
- if (status === 401) {
2322
- return new ZapierAuthenticationError(
2323
- `Authentication failed. Your token may not have permission to access authentications or may be expired. (HTTP ${status})`,
2324
- { statusCode: status }
2325
- );
2326
- }
2327
- if (status === 403) {
2328
- return new ZapierAuthenticationError(
2329
- `Access forbidden. Your token may not have the required scopes to get authentication ${authenticationId}. (HTTP ${status})`,
2330
- { statusCode: status }
2331
- );
2332
- }
2333
- if (status === 404) {
2334
- return new ZapierResourceNotFoundError(
2335
- `Authentication ${authenticationId} not found. It may not exist or you may not have access to it. (HTTP ${status})`,
2336
- {
2337
- resourceType: "Authentication",
2338
- resourceId: String(authenticationId)
2339
- }
2340
- );
2341
- }
2342
- return void 0;
2343
- },
2344
- authRequired: true
2345
- }
2366
+ return await api.get(
2367
+ `/api/v0/authentications/${options.authenticationId}`
2346
2368
  );
2347
- return {
2348
- data: normalizeAuthenticationItem(data)
2349
- };
2350
- }, GetAuthenticationSchema);
2369
+ }, GetAuthenticationOptionsSchema);
2351
2370
  return {
2352
2371
  getAuthentication,
2353
2372
  context: {
@@ -2356,7 +2375,7 @@ var getAuthenticationPlugin = ({ context }) => {
2356
2375
  categories: ["authentication"],
2357
2376
  type: "item",
2358
2377
  itemType: "Authentication",
2359
- inputSchema: GetAuthenticationSchema,
2378
+ inputSchema: GetAuthenticationOptionsSchema,
2360
2379
  outputSchema: AuthenticationItemSchema,
2361
2380
  resolvers: {
2362
2381
  authenticationId: authenticationIdGenericResolver
@@ -3193,6 +3212,12 @@ function isJwt(token) {
3193
3212
  const base64UrlPattern = /^[A-Za-z0-9_-]+$/;
3194
3213
  return parts.every((part) => part.length > 0 && base64UrlPattern.test(part));
3195
3214
  }
3215
+ function parseJwt(token) {
3216
+ if (!isJwt(token)) {
3217
+ return null;
3218
+ }
3219
+ return token.split(".");
3220
+ }
3196
3221
  function getAuthorizationHeader(token) {
3197
3222
  if (isJwt(token)) {
3198
3223
  return `JWT ${token}`;
@@ -3200,11 +3225,11 @@ function getAuthorizationHeader(token) {
3200
3225
  return `Bearer ${token}`;
3201
3226
  }
3202
3227
  function extractUserIdsFromJwt(token) {
3228
+ const parts = parseJwt(token);
3229
+ if (!parts) {
3230
+ return { customuser_id: null, account_id: null };
3231
+ }
3203
3232
  try {
3204
- const parts = token.split(".");
3205
- if (parts.length !== 3) {
3206
- return { customuser_id: null, account_id: null };
3207
- }
3208
3233
  const payload = JSON.parse(
3209
3234
  Buffer.from(parts[1], "base64url").toString("utf-8")
3210
3235
  );
@@ -3511,6 +3536,18 @@ async function getTokenFromEnvOrConfig(options = {}) {
3511
3536
  }
3512
3537
  return getTokenFromCliLogin(options);
3513
3538
  }
3539
+ async function resolveAuthToken(options = {}) {
3540
+ if (options.token) {
3541
+ return options.token;
3542
+ }
3543
+ if (options.getToken) {
3544
+ const token = await options.getToken();
3545
+ if (token) {
3546
+ return token;
3547
+ }
3548
+ }
3549
+ return getTokenFromEnvOrConfig(options);
3550
+ }
3514
3551
 
3515
3552
  // src/utils/url-utils.ts
3516
3553
  function getZapierBaseUrl(baseUrl) {
@@ -3558,7 +3595,7 @@ function getTrackingBaseUrl({
3558
3595
  return ZAPIER_BASE_URL;
3559
3596
  }
3560
3597
 
3561
- // src/temporary-internal-core/utils/app-locators.ts
3598
+ // src/temporary-internal-core/utils/string-utils.ts
3562
3599
  function splitVersionedKey2(versionedKey) {
3563
3600
  const parts = versionedKey.split("@");
3564
3601
  if (parts.length >= 2) {
@@ -3593,6 +3630,44 @@ function extractPaginationCursor(response) {
3593
3630
  return void 0;
3594
3631
  }
3595
3632
  }
3633
+ function normalizeAuthenticationItem2(auth, options = {}) {
3634
+ let appKey = options.app_key;
3635
+ let appVersion = options.app_version;
3636
+ if (auth.selected_api) {
3637
+ const [extractedAppKey, extractedVersion] = splitVersionedKey2(
3638
+ auth.selected_api
3639
+ );
3640
+ if (!appKey) {
3641
+ appKey = extractedAppKey;
3642
+ }
3643
+ if (!appVersion) {
3644
+ appVersion = extractedVersion;
3645
+ }
3646
+ }
3647
+ const {
3648
+ selected_api: selectedApi,
3649
+ customuser_id: userId,
3650
+ ...restOfAuth
3651
+ } = auth;
3652
+ return {
3653
+ ...restOfAuth,
3654
+ // Pass through all other API response fields except selected_api
3655
+ implementation_id: selectedApi,
3656
+ // Rename selected_api to implementation_id
3657
+ title: auth.title || auth.label || void 0,
3658
+ // Coerce title from label if missing
3659
+ is_expired: auth.is_stale,
3660
+ // Map is_stale to is_expired
3661
+ expired_at: auth.marked_stale_at,
3662
+ // Map marked_stale_at to expired_at
3663
+ app_key: appKey,
3664
+ // App key from implementations endpoint or parsed from selected_api
3665
+ app_version: appVersion,
3666
+ // Version from selected_api or provided
3667
+ user_id: userId
3668
+ // Map customuser_id to user_id
3669
+ };
3670
+ }
3596
3671
 
3597
3672
  // src/temporary-internal-core/handlers/listApps.ts
3598
3673
  var DEFAULT_PAGE_SIZE = 20;
@@ -3687,6 +3762,111 @@ var handleListApps = async ({ request, deps }) => {
3687
3762
  };
3688
3763
  };
3689
3764
 
3765
+ // src/temporary-internal-core/schemas/errors/index.ts
3766
+ var ZapierError2 = class extends Error {
3767
+ constructor(message, options = {}) {
3768
+ super(message);
3769
+ this.statusCode = options.statusCode;
3770
+ this.errors = options.errors;
3771
+ this.cause = options.cause;
3772
+ this.response = options.response;
3773
+ Object.setPrototypeOf(this, new.target.prototype);
3774
+ }
3775
+ };
3776
+ var ZapierAuthenticationError2 = class extends ZapierError2 {
3777
+ constructor(message, options = {}) {
3778
+ super(message, options);
3779
+ this.name = "ZapierAuthenticationError";
3780
+ }
3781
+ };
3782
+ var ZapierResourceNotFoundError2 = class extends ZapierError2 {
3783
+ constructor(message, options = {}) {
3784
+ super(message, options);
3785
+ this.name = "ZapierResourceNotFoundError";
3786
+ this.resourceType = options.resourceType;
3787
+ this.resourceId = options.resourceId;
3788
+ }
3789
+ };
3790
+
3791
+ // src/temporary-internal-core/handlers/getAuthentication.ts
3792
+ var handleGetAuthentication = async ({ request, deps }) => {
3793
+ const validatedRequest = GetAuthenticationHandlerRequestSchema.parse(request);
3794
+ const { httpClient } = deps;
3795
+ const { authenticationId } = validatedRequest;
3796
+ const authentication = await httpClient.get(
3797
+ `/zapier/api/v4/authentications/${authenticationId}/`,
3798
+ {
3799
+ authRequired: true,
3800
+ customErrorHandler: ({ status }) => {
3801
+ if (status === 401) {
3802
+ return new ZapierAuthenticationError2(
3803
+ `Authentication failed. Your token may not have permission to access authentications or may be expired. (HTTP ${status})`,
3804
+ { statusCode: status }
3805
+ );
3806
+ }
3807
+ if (status === 403) {
3808
+ return new ZapierAuthenticationError2(
3809
+ `Access forbidden. Your token may not have the required scopes to get authentication ${authenticationId}. (HTTP ${status})`,
3810
+ { statusCode: status }
3811
+ );
3812
+ }
3813
+ if (status === 404) {
3814
+ return new ZapierResourceNotFoundError2(
3815
+ `Authentication ${authenticationId} not found. It may not exist or you may not have access to it. (HTTP ${status})`,
3816
+ {
3817
+ resourceType: "Authentication",
3818
+ resourceId: String(authenticationId)
3819
+ }
3820
+ );
3821
+ }
3822
+ return void 0;
3823
+ }
3824
+ }
3825
+ );
3826
+ const normalizedAuthentication = normalizeAuthenticationItem2(authentication);
3827
+ return {
3828
+ data: normalizedAuthentication
3829
+ };
3830
+ };
3831
+
3832
+ // src/api/router.ts
3833
+ var routes = [
3834
+ {
3835
+ method: "GET",
3836
+ pattern: /^\/api\/v0\/apps$/,
3837
+ handler: handleListApps,
3838
+ paramMap: []
3839
+ },
3840
+ {
3841
+ method: "GET",
3842
+ pattern: /^\/api\/v0\/authentications\/([^\/]+)$/,
3843
+ handler: handleGetAuthentication,
3844
+ paramMap: ["authenticationId"]
3845
+ }
3846
+ ];
3847
+ function findMatchingRoute(routeList, method, path) {
3848
+ for (const route of routeList) {
3849
+ if (route.method !== method) {
3850
+ continue;
3851
+ }
3852
+ const match = path.match(route.pattern);
3853
+ if (match) {
3854
+ const params = {};
3855
+ route.paramMap.forEach((name, index) => {
3856
+ params[name] = match[index + 1];
3857
+ });
3858
+ return {
3859
+ handler: route.handler,
3860
+ params
3861
+ };
3862
+ }
3863
+ }
3864
+ return null;
3865
+ }
3866
+ function matchRoute(method, path) {
3867
+ return findMatchingRoute(routes, method, path);
3868
+ }
3869
+
3690
3870
  // src/api/client.ts
3691
3871
  var pathConfig = {
3692
3872
  // e.g. /relay -> https://sdkapi.zapier.com/api/v0/sdk/relay/...
@@ -3698,9 +3878,6 @@ var pathConfig = {
3698
3878
  "/zapier": {
3699
3879
  authHeader: "Authorization",
3700
3880
  pathPrefix: "/api/v0/sdk/zapier"
3701
- },
3702
- "/api/v0/apps": {
3703
- handlerOverride: handleListApps
3704
3881
  }
3705
3882
  };
3706
3883
  var ZapierApiClient = class {
@@ -3746,16 +3923,9 @@ var ZapierApiClient = class {
3746
3923
  }
3747
3924
  // Helper to get a token from the different places it could be gotten
3748
3925
  async getAuthToken() {
3749
- if (this.options.token) {
3750
- return this.options.token;
3751
- }
3752
- if (this.options.getToken) {
3753
- const token = await this.options.getToken();
3754
- if (token) {
3755
- return token;
3756
- }
3757
- }
3758
- return getTokenFromEnvOrConfig({
3926
+ return resolveAuthToken({
3927
+ token: this.options.token,
3928
+ getToken: this.options.getToken,
3759
3929
  onEvent: this.options.onEvent,
3760
3930
  fetch: this.options.fetch,
3761
3931
  baseUrl: this.options.baseUrl,
@@ -3858,14 +4028,6 @@ var ZapierApiClient = class {
3858
4028
  }
3859
4029
  return void 0;
3860
4030
  }
3861
- // Helper to check if a path config has a handler override
3862
- hasHandlerOverride(pathConfig2) {
3863
- return pathConfig2 !== void 0 && "handlerOverride" in pathConfig2 && typeof pathConfig2.handlerOverride === "function";
3864
- }
3865
- // Helper to check if a path config is a standard path config
3866
- isStandardPathConfig(pathConfig2) {
3867
- return pathConfig2 !== void 0 && !this.hasHandlerOverride(pathConfig2);
3868
- }
3869
4031
  // Helper to parse API error response
3870
4032
  parseErrorResponse(errorInfo) {
3871
4033
  const fallbackMessage = `HTTP ${errorInfo.status}: ${errorInfo.statusText}`;
@@ -3917,8 +4079,10 @@ var ZapierApiClient = class {
3917
4079
  pathConfig: config
3918
4080
  };
3919
4081
  }
4082
+ const baseUrl = new URL(this.options.baseUrl);
4083
+ const fullPath = baseUrl.pathname.replace(/\/$/, "") + path;
3920
4084
  return {
3921
- url: new URL(path, this.options.baseUrl),
4085
+ url: new URL(fullPath, baseUrl.origin),
3922
4086
  pathConfig: config
3923
4087
  };
3924
4088
  }
@@ -3937,7 +4101,7 @@ var ZapierApiClient = class {
3937
4101
  const headers = new Headers(options.headers ?? {});
3938
4102
  const authToken = await this.getAuthToken();
3939
4103
  if (authToken) {
3940
- const authHeaderName = this.isStandardPathConfig(pathConfig2) && pathConfig2.authHeader ? pathConfig2.authHeader : "Authorization";
4104
+ const authHeaderName = pathConfig2 && pathConfig2.authHeader ? pathConfig2.authHeader : "Authorization";
3941
4105
  headers.set(authHeaderName, getAuthorizationHeader(authToken));
3942
4106
  }
3943
4107
  if (options.authRequired) {
@@ -3951,10 +4115,14 @@ var ZapierApiClient = class {
3951
4115
  }
3952
4116
  // Helper to perform HTTP requests with JSON handling
3953
4117
  async fetchJson(method, path, data, options = {}) {
3954
- const { pathConfig: pathConfig2 } = this.buildUrl(path, options.searchParams);
3955
- if (this.hasHandlerOverride(pathConfig2)) {
3956
- const handlerRequest = method === "GET" ? options.searchParams : data;
3957
- return pathConfig2.handlerOverride({
4118
+ const routeMatch = matchRoute(method, path);
4119
+ if (routeMatch) {
4120
+ const handlerRequest = {
4121
+ ...typeof data === "object" ? data : {},
4122
+ ...options.searchParams,
4123
+ ...routeMatch.params
4124
+ };
4125
+ return routeMatch.handler({
3958
4126
  request: handlerRequest,
3959
4127
  deps: {
3960
4128
  httpClient: this
@@ -4623,7 +4791,7 @@ function getCpuTime() {
4623
4791
 
4624
4792
  // package.json
4625
4793
  var package_default = {
4626
- version: "0.15.4"};
4794
+ version: "0.15.8"};
4627
4795
 
4628
4796
  // src/plugins/eventEmission/builders.ts
4629
4797
  function createBaseEvent(context = {}) {
@@ -4763,9 +4931,14 @@ var eventEmissionPlugin = ({ context }) => {
4763
4931
  };
4764
4932
  const getUserContext = (async () => {
4765
4933
  try {
4766
- const { getToken } = await import('@zapier/zapier-sdk-cli-login');
4767
- const token = await getToken({
4768
- baseUrl: context.options.baseUrl
4934
+ const token = await resolveAuthToken({
4935
+ token: context.options.token,
4936
+ getToken: context.options.getToken,
4937
+ baseUrl: context.options.baseUrl,
4938
+ authBaseUrl: context.options.authBaseUrl,
4939
+ authClientId: context.options.authClientId,
4940
+ onEvent: context.options.onEvent,
4941
+ fetch: context.options.fetch
4769
4942
  });
4770
4943
  if (token) {
4771
4944
  return extractUserIdsFromJwt(token);
@@ -5083,6 +5256,7 @@ exports.manifestPlugin = manifestPlugin;
5083
5256
  exports.readManifestFromFile = readManifestFromFile;
5084
5257
  exports.registryPlugin = registryPlugin;
5085
5258
  exports.requestPlugin = requestPlugin;
5259
+ exports.resolveAuthToken = resolveAuthToken;
5086
5260
  exports.runActionPlugin = runActionPlugin;
5087
5261
  exports.toSnakeCase = toSnakeCase;
5088
5262
  exports.toTitleCase = toTitleCase;