@zapier/zapier-sdk 0.15.2 → 0.15.4

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 (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/api/auth.d.ts +10 -0
  3. package/dist/api/auth.d.ts.map +1 -1
  4. package/dist/api/auth.js +35 -0
  5. package/dist/api/schemas.d.ts +38 -38
  6. package/dist/index.cjs +209 -27
  7. package/dist/index.d.mts +151 -59
  8. package/dist/index.mjs +209 -27
  9. package/dist/plugins/eventEmission/index.d.ts +1 -1
  10. package/dist/plugins/eventEmission/index.d.ts.map +1 -1
  11. package/dist/plugins/eventEmission/index.js +90 -22
  12. package/dist/plugins/eventEmission/index.test.js +179 -2
  13. package/dist/plugins/fetch/schemas.d.ts +2 -2
  14. package/dist/plugins/getAction/schemas.d.ts +2 -2
  15. package/dist/plugins/getInputFieldsSchema/schemas.d.ts +2 -2
  16. package/dist/plugins/listActions/index.test.js +25 -0
  17. package/dist/plugins/listActions/schemas.d.ts +2 -2
  18. package/dist/plugins/listAuthentications/index.test.js +20 -0
  19. package/dist/plugins/listInputFieldChoices/schemas.d.ts +6 -6
  20. package/dist/plugins/listInputFields/schemas.d.ts +6 -6
  21. package/dist/plugins/manifest/index.d.ts +42 -3
  22. package/dist/plugins/manifest/index.d.ts.map +1 -1
  23. package/dist/plugins/manifest/index.js +68 -1
  24. package/dist/plugins/manifest/index.test.js +513 -1
  25. package/dist/plugins/manifest/schemas.d.ts +75 -2
  26. package/dist/plugins/manifest/schemas.d.ts.map +1 -1
  27. package/dist/plugins/manifest/schemas.js +27 -3
  28. package/dist/plugins/request/schemas.d.ts +4 -4
  29. package/dist/plugins/runAction/schemas.d.ts +6 -6
  30. package/dist/schemas/Action.d.ts +1 -1
  31. package/dist/schemas/Auth.d.ts +6 -6
  32. package/dist/sdk.d.ts +23 -1
  33. package/dist/sdk.d.ts.map +1 -1
  34. package/package.json +1 -1
@@ -12,9 +12,16 @@ const mockTransport = {
12
12
  vi.mock("./transport", () => ({
13
13
  createTransport: vi.fn(() => mockTransport),
14
14
  }));
15
+ // Mock CLI login package - default to returning null context
16
+ const mockGetToken = vi.fn().mockResolvedValue(undefined);
17
+ vi.mock("@zapier/zapier-sdk-cli-login", () => ({
18
+ getToken: mockGetToken,
19
+ }));
15
20
  describe("eventEmissionPlugin", () => {
16
21
  beforeEach(() => {
17
22
  vi.clearAllMocks();
23
+ // Reset to default behavior - no token available
24
+ mockGetToken.mockResolvedValue(undefined);
18
25
  });
19
26
  it("should create plugin with default configuration", () => {
20
27
  const plugin = eventEmissionPlugin({
@@ -64,8 +71,13 @@ describe("eventEmissionPlugin", () => {
64
71
  const testSubject = "test.event.TestEvent";
65
72
  plugin.context.eventEmission.emit(testSubject, testEvent);
66
73
  // Give async emission time to complete
67
- await new Promise((resolve) => setTimeout(resolve, 0));
68
- expect(mockTransport.emit).toHaveBeenCalledWith(testSubject, testEvent);
74
+ await new Promise((resolve) => setTimeout(resolve, 50));
75
+ // The event will be enriched with user context (null values)
76
+ expect(mockTransport.emit).toHaveBeenCalledWith(testSubject, {
77
+ ...testEvent,
78
+ customuser_id: null,
79
+ account_id: null,
80
+ });
69
81
  });
70
82
  it("should handle transport creation failures silently", () => {
71
83
  // Mock createTransport to throw an error
@@ -220,6 +232,8 @@ describe("eventEmissionPlugin", () => {
220
232
  mockConsoleWarn.mockRestore();
221
233
  });
222
234
  it("should merge options with defaults", () => {
235
+ // Override env var to ensure proper transport is used
236
+ vi.stubEnv("ZAPIER_SDK_TELEMETRY_TRANSPORT", undefined);
223
237
  const plugin = eventEmissionPlugin({
224
238
  sdk: {},
225
239
  context: {
@@ -239,5 +253,168 @@ describe("eventEmissionPlugin", () => {
239
253
  type: "http",
240
254
  endpoint: "https://example.com",
241
255
  });
256
+ vi.unstubAllEnvs();
257
+ });
258
+ it("should extract user IDs from JWT token and include in events", async () => {
259
+ // Create a test JWT token with user data
260
+ // JWT format: header.payload.signature
261
+ const header = { alg: "HS256", typ: "JWT" };
262
+ const payload = {
263
+ "zap:acc": "12345",
264
+ sub: "67890",
265
+ sub_type: "customuser",
266
+ "zap:uname": "test@example.com",
267
+ };
268
+ const encodedHeader = Buffer.from(JSON.stringify(header)).toString("base64url");
269
+ const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url");
270
+ const testJwt = `${encodedHeader}.${encodedPayload}.fake-signature`;
271
+ // Mock getToken to return the JWT
272
+ mockGetToken.mockResolvedValue(testJwt);
273
+ const plugin = eventEmissionPlugin({
274
+ sdk: {},
275
+ context: {
276
+ meta: {},
277
+ options: {
278
+ eventEmission: {
279
+ enabled: true,
280
+ transport: { type: "console" },
281
+ },
282
+ },
283
+ },
284
+ });
285
+ // Test that createBaseEvent includes the extracted user IDs
286
+ const baseEvent = await plugin.context.eventEmission.createBaseEvent();
287
+ expect(baseEvent.customuser_id).toBe(67890);
288
+ expect(baseEvent.account_id).toBe(12345);
289
+ });
290
+ it("should handle service tokens with nested JWT", async () => {
291
+ // Create a nested JWT for service token testing
292
+ const nestedHeader = { alg: "HS256", typ: "JWT" };
293
+ const nestedPayload = {
294
+ "zap:acc": "99999",
295
+ sub: "88888",
296
+ sub_type: "customuser",
297
+ };
298
+ const nestedEncodedHeader = Buffer.from(JSON.stringify(nestedHeader)).toString("base64url");
299
+ const nestedEncodedPayload = Buffer.from(JSON.stringify(nestedPayload)).toString("base64url");
300
+ const nestedJwt = `${nestedEncodedHeader}.${nestedEncodedPayload}.nested-signature`;
301
+ // Create the service token that wraps the nested JWT
302
+ const serviceHeader = { alg: "HS256", typ: "JWT" };
303
+ const servicePayload = {
304
+ "zap:acc": "11111",
305
+ sub: "22222",
306
+ sub_type: "service",
307
+ njwt: nestedJwt,
308
+ };
309
+ const serviceEncodedHeader = Buffer.from(JSON.stringify(serviceHeader)).toString("base64url");
310
+ const serviceEncodedPayload = Buffer.from(JSON.stringify(servicePayload)).toString("base64url");
311
+ const serviceJwt = `${serviceEncodedHeader}.${serviceEncodedPayload}.service-signature`;
312
+ // Mock getToken to return the service JWT
313
+ mockGetToken.mockResolvedValue(serviceJwt);
314
+ const plugin = eventEmissionPlugin({
315
+ sdk: {},
316
+ context: {
317
+ meta: {},
318
+ options: {
319
+ eventEmission: {
320
+ enabled: true,
321
+ transport: { type: "console" },
322
+ },
323
+ },
324
+ },
325
+ });
326
+ const baseEvent = await plugin.context.eventEmission.createBaseEvent();
327
+ // Should extract from nested JWT, not the service token
328
+ expect(baseEvent.customuser_id).toBe(88888);
329
+ expect(baseEvent.account_id).toBe(99999);
330
+ });
331
+ it("should handle invalid JWT tokens gracefully", async () => {
332
+ // Mock getToken to return an invalid JWT
333
+ mockGetToken.mockResolvedValue("not-a-valid-jwt-token");
334
+ const plugin = eventEmissionPlugin({
335
+ sdk: {},
336
+ context: {
337
+ meta: {},
338
+ options: {
339
+ eventEmission: {
340
+ enabled: true,
341
+ transport: { type: "console" },
342
+ },
343
+ },
344
+ },
345
+ });
346
+ const baseEvent = await plugin.context.eventEmission.createBaseEvent();
347
+ // Should default to null when JWT is invalid
348
+ expect(baseEvent.customuser_id).toBe(null);
349
+ expect(baseEvent.account_id).toBe(null);
350
+ });
351
+ it("should handle missing token gracefully", async () => {
352
+ // mockGetToken defaults to returning undefined (no token)
353
+ const plugin = eventEmissionPlugin({
354
+ sdk: {},
355
+ context: {
356
+ meta: {},
357
+ options: {
358
+ eventEmission: {
359
+ enabled: true,
360
+ transport: { type: "console" },
361
+ },
362
+ },
363
+ },
364
+ });
365
+ const baseEvent = await plugin.context.eventEmission.createBaseEvent();
366
+ // Should default to null when no token is provided
367
+ expect(baseEvent.customuser_id).toBe(null);
368
+ expect(baseEvent.account_id).toBe(null);
369
+ });
370
+ it("should extract user IDs when getToken returns valid JWT", async () => {
371
+ // Create a test JWT token
372
+ const header = { alg: "HS256", typ: "JWT" };
373
+ const payload = {
374
+ "zap:acc": "98765",
375
+ sub: "54321",
376
+ sub_type: "customuser",
377
+ };
378
+ const encodedHeader = Buffer.from(JSON.stringify(header)).toString("base64url");
379
+ const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url");
380
+ const testJwt = `${encodedHeader}.${encodedPayload}.test-signature`;
381
+ // Mock getToken to return the JWT
382
+ mockGetToken.mockResolvedValue(testJwt);
383
+ const plugin = eventEmissionPlugin({
384
+ sdk: {},
385
+ context: {
386
+ meta: {},
387
+ options: {
388
+ eventEmission: {
389
+ enabled: true,
390
+ transport: { type: "console" },
391
+ },
392
+ },
393
+ },
394
+ });
395
+ // Test that createBaseEvent includes the extracted user IDs
396
+ const baseEvent = await plugin.context.eventEmission.createBaseEvent();
397
+ expect(baseEvent.customuser_id).toBe(54321);
398
+ expect(baseEvent.account_id).toBe(98765);
399
+ });
400
+ it("should handle getToken failures gracefully", async () => {
401
+ // Mock getToken to reject/throw
402
+ mockGetToken.mockRejectedValue(new Error("Token fetch failed"));
403
+ const plugin = eventEmissionPlugin({
404
+ sdk: {},
405
+ context: {
406
+ meta: {},
407
+ options: {
408
+ eventEmission: {
409
+ enabled: true,
410
+ transport: { type: "console" },
411
+ },
412
+ },
413
+ },
414
+ });
415
+ const baseEvent = await plugin.context.eventEmission.createBaseEvent();
416
+ // Should gracefully fall back to null context
417
+ expect(baseEvent.customuser_id).toBe(null);
418
+ expect(baseEvent.account_id).toBe(null);
242
419
  });
243
420
  });
@@ -9,16 +9,16 @@ export declare const FetchInitSchema: z.ZodOptional<z.ZodObject<{
9
9
  authenticationTemplate: z.ZodOptional<z.ZodString>;
10
10
  }, "strip", z.ZodTypeAny, {
11
11
  method?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | undefined;
12
+ authenticationId?: number | undefined;
12
13
  headers?: Record<string, string> | undefined;
13
14
  body?: string | FormData | URLSearchParams | undefined;
14
- authenticationId?: number | undefined;
15
15
  callbackUrl?: string | undefined;
16
16
  authenticationTemplate?: string | undefined;
17
17
  }, {
18
18
  method?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | undefined;
19
+ authenticationId?: number | undefined;
19
20
  headers?: Record<string, string> | undefined;
20
21
  body?: string | FormData | URLSearchParams | undefined;
21
- authenticationId?: number | undefined;
22
22
  callbackUrl?: string | undefined;
23
23
  authenticationTemplate?: string | undefined;
24
24
  }>>;
@@ -9,12 +9,12 @@ export declare const GetActionSchema: z.ZodObject<{
9
9
  actionKey: z.ZodString;
10
10
  }, "strip", z.ZodTypeAny, {
11
11
  appKey: string;
12
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
13
12
  actionKey: string;
13
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
14
14
  }, {
15
15
  appKey: string;
16
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
17
16
  actionKey: string;
17
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
18
18
  }>;
19
19
  export type GetActionOptions = z.infer<typeof GetActionSchema>;
20
20
  export type GetActionError = ZapierAuthenticationError | ZapierApiError | ZapierAppNotFoundError | ZapierValidationError | ZapierResourceNotFoundError | ZapierUnknownError;
@@ -10,14 +10,14 @@ export declare const GetInputFieldsSchemaSchema: z.ZodObject<{
10
10
  inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
11
  }, "strip", z.ZodTypeAny, {
12
12
  appKey: string;
13
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
14
13
  actionKey: string;
14
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
15
15
  authenticationId?: number | null | undefined;
16
16
  inputs?: Record<string, unknown> | undefined;
17
17
  }, {
18
18
  appKey: string;
19
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
20
19
  actionKey: string;
20
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
21
21
  authenticationId?: number | null | undefined;
22
22
  inputs?: Record<string, unknown> | undefined;
23
23
  }>;
@@ -73,6 +73,31 @@ describe("listActions plugin", () => {
73
73
  updateManifestEntry: vi
74
74
  .fn()
75
75
  .mockResolvedValue(["test-key", {}, { apps: {} }]),
76
+ addActionEntry: vi
77
+ .fn()
78
+ .mockResolvedValue(["test-key", {}, { apps: {} }]),
79
+ findActionEntry: vi.fn().mockResolvedValue({
80
+ key: "test-key",
81
+ entry: {},
82
+ manifest: { apps: {} },
83
+ }),
84
+ hasActionEntry: vi.fn().mockResolvedValue(true),
85
+ listActionEntries: vi
86
+ .fn()
87
+ .mockResolvedValue([
88
+ [
89
+ "test-key",
90
+ { key: "test-key", entry: {}, manifest: { apps: {} } },
91
+ ],
92
+ ]),
93
+ deleteActionEntry: vi.fn().mockResolvedValue({ apps: {} }),
94
+ findManifestEntry: vi
95
+ .fn()
96
+ .mockResolvedValue([
97
+ "test-key",
98
+ { key: "test-key", entry: {}, manifest: { apps: {} } },
99
+ ]),
100
+ readManifestFromFile: vi.fn().mockResolvedValue({ apps: {} }),
76
101
  },
77
102
  }))
78
103
  .addPlugin(listAppsPlugin)
@@ -12,16 +12,16 @@ export declare const ListActionsSchema: z.ZodObject<{
12
12
  cursor: z.ZodOptional<z.ZodString>;
13
13
  }, "strip", z.ZodTypeAny, {
14
14
  appKey: string;
15
+ actionType?: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write" | undefined;
15
16
  pageSize?: number | undefined;
16
17
  maxItems?: number | undefined;
17
18
  cursor?: string | undefined;
18
- actionType?: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write" | undefined;
19
19
  }, {
20
20
  appKey: string;
21
+ actionType?: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write" | undefined;
21
22
  pageSize?: number | undefined;
22
23
  maxItems?: number | undefined;
23
24
  cursor?: string | undefined;
24
- actionType?: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write" | undefined;
25
25
  }>;
26
26
  export type ListActionsOptions = z.infer<typeof ListActionsSchema>;
27
27
  export interface ListActionsPage {
@@ -61,6 +61,26 @@ describe("listAuthentications plugin", () => {
61
61
  updateManifestEntry: vi
62
62
  .fn()
63
63
  .mockResolvedValue(["test-key", {}, { apps: {} }]),
64
+ addActionEntry: vi.fn().mockResolvedValue(["test-key", {}, { apps: {} }]),
65
+ findActionEntry: vi.fn().mockResolvedValue({
66
+ key: "test-key",
67
+ entry: {},
68
+ manifest: { apps: {} },
69
+ }),
70
+ hasActionEntry: vi.fn().mockResolvedValue(true),
71
+ listActionEntries: vi
72
+ .fn()
73
+ .mockResolvedValue([
74
+ ["test-key", { key: "test-key", entry: {}, manifest: { apps: {} } }],
75
+ ]),
76
+ deleteActionEntry: vi.fn().mockResolvedValue({ apps: {} }),
77
+ findManifestEntry: vi
78
+ .fn()
79
+ .mockResolvedValue([
80
+ "test-key",
81
+ { key: "test-key", entry: {}, manifest: { apps: {} } },
82
+ ]),
83
+ readManifestFromFile: vi.fn().mockResolvedValue({ apps: {} }),
64
84
  },
65
85
  });
66
86
  function createTestSdk() {
@@ -33,26 +33,26 @@ export declare const ListInputFieldChoicesSchema: z.ZodObject<{
33
33
  cursor: z.ZodOptional<z.ZodString>;
34
34
  }, "strip", z.ZodTypeAny, {
35
35
  appKey: string;
36
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
37
36
  actionKey: string;
37
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
38
38
  inputFieldKey: string;
39
39
  page?: number | undefined;
40
+ authenticationId?: number | null | undefined;
41
+ inputs?: Record<string, unknown> | undefined;
40
42
  pageSize?: number | undefined;
41
43
  maxItems?: number | undefined;
42
44
  cursor?: string | undefined;
43
- authenticationId?: number | null | undefined;
44
- inputs?: Record<string, unknown> | undefined;
45
45
  }, {
46
46
  appKey: string;
47
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
48
47
  actionKey: string;
48
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
49
49
  inputFieldKey: string;
50
50
  page?: number | undefined;
51
+ authenticationId?: number | null | undefined;
52
+ inputs?: Record<string, unknown> | undefined;
51
53
  pageSize?: number | undefined;
52
54
  maxItems?: number | undefined;
53
55
  cursor?: string | undefined;
54
- authenticationId?: number | null | undefined;
55
- inputs?: Record<string, unknown> | undefined;
56
56
  }>;
57
57
  export type ListInputFieldChoicesOptions = z.infer<typeof ListInputFieldChoicesSchema>;
58
58
  export type ListInputFieldChoicesError = ZapierConfigurationError | ZapierApiError | ZapierAuthenticationError | ZapierAppNotFoundError | ZapierValidationError | ZapierUnknownError;
@@ -15,22 +15,22 @@ export declare const ListInputFieldsSchema: z.ZodObject<{
15
15
  cursor: z.ZodOptional<z.ZodString>;
16
16
  }, "strip", z.ZodTypeAny, {
17
17
  appKey: string;
18
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
19
18
  actionKey: string;
19
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
20
+ authenticationId?: number | null | undefined;
21
+ inputs?: Record<string, unknown> | undefined;
20
22
  pageSize?: number | undefined;
21
23
  maxItems?: number | undefined;
22
24
  cursor?: string | undefined;
23
- authenticationId?: number | null | undefined;
24
- inputs?: Record<string, unknown> | undefined;
25
25
  }, {
26
26
  appKey: string;
27
- actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
28
27
  actionKey: string;
28
+ actionType: "search" | "filter" | "read" | "read_bulk" | "run" | "search_and_write" | "search_or_write" | "write";
29
+ authenticationId?: number | null | undefined;
30
+ inputs?: Record<string, unknown> | undefined;
29
31
  pageSize?: number | undefined;
30
32
  maxItems?: number | undefined;
31
33
  cursor?: string | undefined;
32
- authenticationId?: number | null | undefined;
33
- inputs?: Record<string, unknown> | undefined;
34
34
  }>;
35
35
  export type ListInputFieldsOptions = z.infer<typeof ListInputFieldsSchema>;
36
36
  export type ListInputFieldsError = ZapierConfigurationError | ZapierApiError | ZapierAuthenticationError | ZapierAppNotFoundError | ZapierValidationError | ZapierUnknownError;
@@ -1,4 +1,4 @@
1
- import type { GetVersionedImplementationId, Manifest, ManifestEntry, ManifestPluginOptionsSchema, ResolveAppKeys } from "./schemas";
1
+ import type { GetVersionedImplementationId, Manifest, ManifestEntry, ManifestPluginOptionsSchema, ResolveAppKeys, ActionEntry } from "./schemas";
2
2
  import type { Plugin } from "../../types/plugin";
3
3
  import type { z } from "zod";
4
4
  import type { ApiClient } from "../../api";
@@ -10,11 +10,50 @@ export interface UpdateManifestEntryOptions {
10
10
  skipWrite?: boolean;
11
11
  manifest?: Manifest;
12
12
  }
13
+ export interface UpdateManifestEntryResult {
14
+ key: string;
15
+ entry: ManifestEntry;
16
+ manifest: Manifest;
17
+ }
18
+ export interface AddActionEntryOptions {
19
+ name: string;
20
+ entry: ActionEntry;
21
+ configPath?: string;
22
+ skipWrite?: boolean;
23
+ manifest?: Manifest;
24
+ }
25
+ export interface AddActionEntryResult {
26
+ name: string;
27
+ entry: ActionEntry;
28
+ manifest: Manifest;
29
+ }
13
30
  export interface ManifestPluginProvides {
14
31
  context: {
15
32
  getVersionedImplementationId: GetVersionedImplementationId;
16
33
  resolveAppKeys: ResolveAppKeys;
17
- updateManifestEntry: (options: UpdateManifestEntryOptions) => Promise<[string, ManifestEntry, Manifest]>;
34
+ updateManifestEntry: (options: UpdateManifestEntryOptions) => Promise<UpdateManifestEntryResult>;
35
+ addActionEntry: (options: AddActionEntryOptions) => Promise<AddActionEntryResult>;
36
+ findActionEntry: (options: {
37
+ name: string;
38
+ manifest: Manifest;
39
+ }) => ActionEntry | null;
40
+ listActionEntries: (options?: {
41
+ configPath?: string;
42
+ }) => Promise<Array<[string, ActionEntry]>>;
43
+ deleteActionEntry: (options: {
44
+ name: string;
45
+ configPath?: string;
46
+ skipWrite?: boolean;
47
+ }) => Promise<Manifest>;
48
+ hasActionEntry: (options: {
49
+ name: string;
50
+ manifest: Manifest;
51
+ }) => boolean;
52
+ findManifestEntry: (options: {
53
+ appKey: string;
54
+ manifest: Manifest;
55
+ }) => [string, ManifestEntry] | null;
56
+ readManifestFromFile: (filePath: string) => Promise<Manifest | null>;
18
57
  };
19
58
  }
20
59
  /**
@@ -38,7 +77,7 @@ export declare function findManifestEntry({ appKey, manifest, }: {
38
77
  manifest: Manifest;
39
78
  }): [string, ManifestEntry] | null;
40
79
  export { DEFAULT_CONFIG_PATH } from "./schemas";
41
- export type { ManifestEntry, Manifest } from "./schemas";
80
+ export type { ManifestEntry, Manifest, ActionEntry } from "./schemas";
42
81
  export declare const manifestPlugin: Plugin<{}, // no SDK dependencies
43
82
  {
44
83
  api: ApiClient;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/manifest/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,QAAQ,EACR,aAAa,EACb,2BAA2B,EAC3B,cAAc,EACf,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAgB3C,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE;QACP,4BAA4B,EAAE,4BAA4B,CAAC;QAC3D,cAAc,EAAE,cAAc,CAAC;QAC/B,mBAAmB,EAAE,CACnB,OAAO,EAAE,0BAA0B,KAChC,OAAO,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;KACjD,CAAC;CACH;AA2BD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAU1B;AAcD;;;GAGG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,MAAM,EACN,GAAG,GACJ,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,SAAS,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkClB;AAoCD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;CACpB,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,IAAI,CAyBjC;AA8GD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEzD,eAAO,MAAM,cAAc,EAAE,MAAM,CACjC,EAAE,EAAE,sBAAsB;AAC1B;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,EAClB,sBAAsB,CAgIvB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/manifest/index.ts"],"names":[],"mappings":"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"}
@@ -293,7 +293,67 @@ export const manifestPlugin = (params) => {
293
293
  // Clear the cached manifest so it gets reloaded with the new data
294
294
  resolvedManifest = undefined;
295
295
  }
296
- return [manifestKey, entry, updatedManifest];
296
+ return {
297
+ key: manifestKey,
298
+ entry,
299
+ manifest: updatedManifest,
300
+ };
301
+ };
302
+ const addActionEntry = async (options) => {
303
+ const { name, entry, configPath = DEFAULT_CONFIG_PATH, skipWrite = false, manifest: inputManifest, } = options;
304
+ // Use provided manifest or read from file
305
+ const manifest = inputManifest ||
306
+ (await readManifestFromFile(configPath)) || { apps: {} };
307
+ // Ensure actions exists
308
+ const actions = manifest.actions || {};
309
+ // Validate uniqueness - if action with this name already exists, throw error
310
+ if (actions[name] && !skipWrite) {
311
+ throw new Error(`Action "${name}" already exists. Please choose a different name or remove the existing action first.`);
312
+ }
313
+ const updatedManifest = {
314
+ ...manifest,
315
+ actions: {
316
+ ...actions,
317
+ [name]: entry,
318
+ },
319
+ };
320
+ // Conditionally write to file
321
+ if (!skipWrite) {
322
+ await writeManifestToFile(updatedManifest, configPath);
323
+ // Clear the cached manifest so it gets reloaded with the new data
324
+ resolvedManifest = undefined;
325
+ }
326
+ return {
327
+ name,
328
+ entry,
329
+ manifest: updatedManifest,
330
+ };
331
+ };
332
+ const findActionEntry = ({ name, manifest, }) => {
333
+ return manifest.actions?.[name] || null;
334
+ };
335
+ const listActionEntries = async ({ configPath = DEFAULT_CONFIG_PATH, } = {}) => {
336
+ const manifest = (await readManifestFromFile(configPath)) || { apps: {} };
337
+ return Object.entries(manifest.actions || {});
338
+ };
339
+ const deleteActionEntry = async ({ name, configPath = DEFAULT_CONFIG_PATH, skipWrite = false, }) => {
340
+ const manifest = (await readManifestFromFile(configPath)) || { apps: {} };
341
+ if (!manifest.actions?.[name]) {
342
+ throw new Error(`Action "${name}" does not exist.`);
343
+ }
344
+ const { [name]: removed, ...remainingActions } = manifest.actions;
345
+ const updatedManifest = {
346
+ ...manifest,
347
+ actions: remainingActions,
348
+ };
349
+ if (!skipWrite) {
350
+ await writeManifestToFile(updatedManifest, configPath);
351
+ resolvedManifest = undefined;
352
+ }
353
+ return updatedManifest;
354
+ };
355
+ const hasActionEntry = ({ name, manifest, }) => {
356
+ return !!manifest.actions?.[name];
297
357
  };
298
358
  return {
299
359
  context: {
@@ -304,6 +364,13 @@ export const manifestPlugin = (params) => {
304
364
  manifest: (await getResolvedManifest()) ?? { apps: {} },
305
365
  }),
306
366
  updateManifestEntry,
367
+ addActionEntry,
368
+ findActionEntry,
369
+ listActionEntries,
370
+ deleteActionEntry,
371
+ hasActionEntry,
372
+ findManifestEntry,
373
+ readManifestFromFile,
307
374
  },
308
375
  };
309
376
  };