svix 2.2.0 → 2.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.
Files changed (42) hide show
  1. package/dist/index.d.mts +1039 -604
  2. package/dist/index.d.mts.map +1 -1
  3. package/dist/index.mjs +4410 -3642
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/src/api/destination.ts +133 -0
  7. package/src/api/destinationTransformation.ts +55 -0
  8. package/src/api_internal/destination.ts +12 -0
  9. package/src/api_internal/destinationAutoconfig.ts +27 -0
  10. package/src/api_internal/endpoint.ts +8 -3
  11. package/src/api_internal/{endpointAutoConfig.ts → endpointAutoConfigDeprecated.ts} +1 -1
  12. package/src/api_internal/endpointAutoconfig.ts +50 -0
  13. package/src/autoconfig.test.ts +169 -4
  14. package/src/autoconfig.ts +89 -26
  15. package/src/autoconfigConsumer.ts +90 -16
  16. package/src/index.ts +5 -0
  17. package/src/models/autoConfigSubscriptionOut.ts +38 -0
  18. package/src/models/destinationIn.ts +303 -0
  19. package/src/models/destinationOut.ts +295 -0
  20. package/src/models/destinationPatch.ts +302 -0
  21. package/src/models/destinationStatus.ts +18 -0
  22. package/src/models/destinationStatusIn.ts +16 -0
  23. package/src/models/destinationTransformIn.ts +19 -0
  24. package/src/models/destinationTransformationOut.ts +22 -0
  25. package/src/models/fifoEndpointConfigIn.ts +25 -0
  26. package/src/models/index.ts +14 -0
  27. package/src/models/ingestSourceIn.ts +12 -0
  28. package/src/models/ingestSourceOut.ts +12 -0
  29. package/src/models/listResponseDestinationOut.ts +31 -0
  30. package/src/models/mergeConfig.ts +19 -0
  31. package/src/models/mergeConfigOut.ts +15 -0
  32. package/src/models/postgresConfigIn.ts +44 -0
  33. package/src/models/postgresConfigOut.ts +25 -0
  34. package/src/models/postgresConfigPatch.ts +28 -0
  35. package/src/models/s3ConfigIn.ts +15 -3
  36. package/src/models/s3ConfigOut.ts +7 -1
  37. package/src/models/s3ConfigPatch.ts +6 -0
  38. package/src/models/status.ts +16 -0
  39. package/src/models/streamSinkIn.ts +12 -0
  40. package/src/models/streamSinkOut.ts +27 -0
  41. package/src/models/streamSinkPatch.ts +15 -0
  42. package/src/request.ts +1 -1
@@ -1,66 +1,112 @@
1
1
  import { SvixInternal } from "./api_internal";
2
+ import { Destination as InternalDestination } from "./api_internal/destination";
2
3
  import { Endpoint as InternalEndpoint } from "./api_internal/endpoint";
3
4
  import {
4
5
  MessagePollerv2 as InternalMessagePollerv2,
5
6
  type MessagePollerv2ConsumerCommitOptions,
6
7
  type MessagePollerv2ConsumerPollOptions,
7
8
  } from "./api_internal/messagePollerv2";
8
- import { decodeAutoconfigTokenV1 } from "./autoconfig";
9
+ import { decodeAutoconfigToken } from "./autoconfig";
10
+ import type { DestinationIn } from "./models/destinationIn";
11
+ import type { DestinationOut } from "./models/destinationOut";
9
12
  import type { EndpointOut } from "./models/endpointOut";
10
13
  import type { PollerV2PollOut } from "./models/pollerV2PollOut";
11
14
  import type { SinkInCommon } from "./models/sinkInCommon";
15
+ import { DestinationStatus } from "./models/destinationStatus";
12
16
  import type { SvixRequestContext } from "./request";
13
17
 
14
18
  export class AutoConfigConsumer {
15
19
  private readonly appId: string;
16
- private readonly sinkId: string;
17
20
  private readonly sinkIn: SinkInCommon;
18
21
  private readonly requestCtx: SvixRequestContext;
22
+ private sinkId?: string;
23
+ private readonly autoconfigId?: string;
19
24
 
20
25
  public constructor(token: string, sinkIn: SinkInCommon) {
21
- const content = decodeAutoconfigTokenV1(token);
26
+ const decoded = decodeAutoconfigToken(token);
22
27
 
23
- this.appId = content.aid;
24
- this.sinkId = content.eid;
28
+ this.appId = decoded.content.aid;
25
29
  this.sinkIn = sinkIn;
26
30
 
27
- const svix = new SvixInternal(content.tok, { serverUrl: content.surl });
31
+ if (decoded.version === "v1") {
32
+ this.sinkId = decoded.content.eid;
33
+ } else {
34
+ this.autoconfigId = decoded.content.sid;
35
+ }
36
+
37
+ const svix = new SvixInternal(decoded.content.tok, {
38
+ serverUrl: decoded.content.surl,
39
+ });
28
40
  this.requestCtx = svix.getRequestCtx();
29
41
  }
30
42
 
31
- public subscribe(): Promise<EndpointOut> {
32
- return new InternalEndpoint(this.requestCtx).autoConfig.update(
33
- this.appId,
34
- this.sinkId,
35
- {
43
+ public async subscribe(): Promise<DestinationOut> {
44
+ const endpoint = new InternalEndpoint(this.requestCtx);
45
+ if (this.autoconfigId != null) {
46
+ // v2
47
+ const destination = await new InternalDestination(
48
+ this.requestCtx
49
+ ).autoconfig.subscribe(
50
+ this.appId,
51
+ this.autoconfigId,
52
+ sinkInCommonToPollingDestination(this.sinkIn)
53
+ );
54
+ this.sinkId = destination.id;
55
+ return destination;
56
+ }
57
+
58
+ // v1
59
+ return destinationOutFromV1Endpoint(
60
+ await endpoint.autoConfigDeprecated.update(this.appId, this.sinkId as string, {
36
61
  sink: {
37
62
  type: "poller",
38
63
  config: this.sinkIn,
39
64
  },
40
- }
65
+ })
41
66
  );
42
67
  }
43
68
 
44
- public receive(
69
+ private async getSinkId(): Promise<string> {
70
+ if (this.sinkId != null) {
71
+ // Already have the sink id from subscribe() or the v1 token
72
+ return this.sinkId;
73
+ }
74
+
75
+ // Get the sink id from the autoconfig id (v2)
76
+ const destId = (
77
+ await new InternalEndpoint(this.requestCtx).autoconfig.get(
78
+ this.appId,
79
+ this.autoconfigId as string
80
+ )
81
+ ).destId;
82
+ if (destId == null) {
83
+ throw new Error("autoconfig subscription is pending. Have you called subscribe()?");
84
+ }
85
+ return destId;
86
+ }
87
+
88
+ public async receive(
45
89
  consumerId: string,
46
90
  options?: MessagePollerv2ConsumerPollOptions
47
91
  ): Promise<PollerV2PollOut> {
92
+ const sinkId = await this.getSinkId();
48
93
  return new InternalMessagePollerv2(this.requestCtx).consumerPoll(
49
94
  this.appId,
50
- this.sinkId,
95
+ sinkId,
51
96
  consumerId,
52
97
  options
53
98
  );
54
99
  }
55
100
 
56
- public commit(
101
+ public async commit(
57
102
  consumerId: string,
58
103
  offset: number,
59
104
  options?: MessagePollerv2ConsumerCommitOptions
60
105
  ): Promise<void> {
106
+ const sinkId = await this.getSinkId();
61
107
  return new InternalMessagePollerv2(this.requestCtx).consumerCommit(
62
108
  this.appId,
63
- this.sinkId,
109
+ sinkId,
64
110
  consumerId,
65
111
  {
66
112
  offset,
@@ -69,3 +115,31 @@ export class AutoConfigConsumer {
69
115
  );
70
116
  }
71
117
  }
118
+
119
+ function sinkInCommonToPollingDestination(sink: SinkInCommon): DestinationIn {
120
+ return {
121
+ type: "pollingEndpoint",
122
+ eventTypes: sink.eventTypes ?? undefined,
123
+ channels: sink.channels ?? undefined,
124
+ metadata: sink.metadata,
125
+ uid: sink.uid,
126
+ };
127
+ }
128
+
129
+ function destinationOutFromV1Endpoint(endpoint: EndpointOut): DestinationOut {
130
+ return {
131
+ id: endpoint.id,
132
+ uid: endpoint.uid,
133
+ status: endpoint.disabled ? DestinationStatus.Disabled : DestinationStatus.Enabled,
134
+ currentIterator: "",
135
+ createdAt: endpoint.createdAt,
136
+ updatedAt: endpoint.updatedAt,
137
+ batchSize: 0,
138
+ maxWaitSecs: 0,
139
+ eventTypes: endpoint.eventTypes ?? undefined,
140
+ channels: endpoint.channels ?? undefined,
141
+ metadata: endpoint.metadata,
142
+ type: "pollingEndpoint",
143
+ config: {},
144
+ };
145
+ }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import { Application } from "./api/application";
3
3
  import { Authentication } from "./api/authentication";
4
4
  import { BackgroundTask } from "./api/backgroundTask";
5
5
  import { Connector } from "./api/connector";
6
+ import { Destination } from "./api/destination";
6
7
  import { Endpoint } from "./api/endpoint";
7
8
  import { Environment } from "./api/environment";
8
9
  import { EventType } from "./api/eventType";
@@ -77,6 +78,10 @@ export class Svix {
77
78
  return new Connector(this.requestCtx);
78
79
  }
79
80
 
81
+ public get destination() {
82
+ return new Destination(this.requestCtx);
83
+ }
84
+
80
85
  public get endpoint() {
81
86
  return new Endpoint(this.requestCtx);
82
87
  }
@@ -0,0 +1,38 @@
1
+ // this file is @generated
2
+ import { type Status, StatusSerializer } from "./status";
3
+
4
+ export interface AutoConfigSubscriptionOut {
5
+ createdAt: Date;
6
+ tokenCensored: string;
7
+ /** The AutoConfigSubscription's ID. */
8
+ id: string;
9
+ /** The Endpoint's ID. */
10
+ endpId?: string | null;
11
+ /** The StreamSink's ID. */
12
+ destId?: string | null;
13
+ status: Status;
14
+ }
15
+
16
+ export const AutoConfigSubscriptionOutSerializer = {
17
+ _fromJsonObject(object: any): AutoConfigSubscriptionOut {
18
+ return {
19
+ createdAt: new Date(object["createdAt"]),
20
+ tokenCensored: object["tokenCensored"],
21
+ id: object["id"],
22
+ endpId: object["endpId"],
23
+ destId: object["destId"],
24
+ status: StatusSerializer._fromJsonObject(object["status"]),
25
+ };
26
+ },
27
+
28
+ _toJsonObject(self: AutoConfigSubscriptionOut): any {
29
+ return {
30
+ createdAt: self.createdAt,
31
+ tokenCensored: self.tokenCensored,
32
+ id: self.id,
33
+ endpId: self.endpId,
34
+ destId: self.destId,
35
+ status: StatusSerializer._toJsonObject(self.status),
36
+ };
37
+ },
38
+ };
@@ -0,0 +1,303 @@
1
+ // this file is @generated
2
+ import {
3
+ type AzureBlobStorageConfigIn,
4
+ AzureBlobStorageConfigInSerializer,
5
+ } from "./azureBlobStorageConfigIn";
6
+ import { type BigQueryConfigIn, BigQueryConfigInSerializer } from "./bigQueryConfigIn";
7
+ import {
8
+ type ClickhouseConfigIn,
9
+ ClickhouseConfigInSerializer,
10
+ } from "./clickhouseConfigIn";
11
+ import {
12
+ type DestinationStatusIn,
13
+ DestinationStatusInSerializer,
14
+ } from "./destinationStatusIn";
15
+ import {
16
+ type EventBridgeConfigIn,
17
+ EventBridgeConfigInSerializer,
18
+ } from "./eventBridgeConfigIn";
19
+ import {
20
+ type FifoEndpointConfigIn,
21
+ FifoEndpointConfigInSerializer,
22
+ } from "./fifoEndpointConfigIn";
23
+ import {
24
+ type GoogleCloudPubSubConfigIn,
25
+ GoogleCloudPubSubConfigInSerializer,
26
+ } from "./googleCloudPubSubConfigIn";
27
+ import {
28
+ type GoogleCloudStorageConfigIn,
29
+ GoogleCloudStorageConfigInSerializer,
30
+ } from "./googleCloudStorageConfigIn";
31
+ import {
32
+ type OtelTracingConfigIn,
33
+ OtelTracingConfigInSerializer,
34
+ } from "./otelTracingConfigIn";
35
+ import { type PostgresConfigIn, PostgresConfigInSerializer } from "./postgresConfigIn";
36
+ import { type RabbitMqConfigIn, RabbitMqConfigInSerializer } from "./rabbitMqConfigIn";
37
+ import { type RedshiftConfigIn, RedshiftConfigInSerializer } from "./redshiftConfigIn";
38
+ import { type S3ConfigIn, S3ConfigInSerializer } from "./s3ConfigIn";
39
+ import { type SnowflakeConfigIn, SnowflakeConfigInSerializer } from "./snowflakeConfigIn";
40
+ import { type SnsConfigIn, SnsConfigInSerializer } from "./snsConfigIn";
41
+ import { type SqsConfigIn, SqsConfigInSerializer } from "./sqsConfigIn";
42
+
43
+ interface _DestinationInFields {
44
+ /** An optional unique identifier for the destination. */
45
+ uid?: string | null;
46
+ /**
47
+ * Whether the destination will receive events.
48
+ *
49
+ * If the destination is `enabled`, events sent to the application will be dispatched to the destination in order.
50
+ *
51
+ * If the destination is `disabled`, events will not be dispatched until the destination is reenabled.
52
+ */
53
+ status?: DestinationStatusIn;
54
+ /** How many events will be batched in a request to the destination. */
55
+ batchSize?: number;
56
+ /**
57
+ * How long to wait before a batch of events is sent, if the `batchSize` is not reached.
58
+ *
59
+ * For example, with a `batchSize` of 100 and `maxWaitSecs` of 10, a request is sent after 10 seconds or 100 events, whichever comes first.
60
+ *
61
+ * Note that an empty batch is never sent to the destination.
62
+ */
63
+ maxWaitSecs?: number;
64
+ /** A list of event types that filter which events are dispatched to the destination. An empty list (or null) will not filter out any events. */
65
+ eventTypes?: string[];
66
+ /** A list of channels that filter which events are dispatched to the destination. An empty list (or null) will not filter out any events. */
67
+ channels?: string[];
68
+ metadata?: { [key: string]: string };
69
+ }
70
+
71
+ // biome-ignore lint/suspicious/noEmptyInterface: backwards compat
72
+ interface DestinationInPollingEndpointConfig {}
73
+
74
+ interface DestinationInPollingEndpoint {
75
+ type: "pollingEndpoint";
76
+ config?: DestinationInPollingEndpointConfig;
77
+ }
78
+
79
+ interface DestinationInAzureBlobStorage {
80
+ type: "azureBlobStorage";
81
+ config: AzureBlobStorageConfigIn;
82
+ }
83
+
84
+ interface DestinationInOtelTracing {
85
+ type: "otelTracing";
86
+ config: OtelTracingConfigIn;
87
+ }
88
+
89
+ interface DestinationInFifoEndpoint {
90
+ type: "fifoEndpoint";
91
+ config: FifoEndpointConfigIn;
92
+ }
93
+
94
+ interface DestinationInAmazonS3 {
95
+ type: "amazonS3";
96
+ config: S3ConfigIn;
97
+ }
98
+
99
+ interface DestinationInGoogleCloudStorage {
100
+ type: "googleCloudStorage";
101
+ config: GoogleCloudStorageConfigIn;
102
+ }
103
+
104
+ interface DestinationInGoogleCloudPubSub {
105
+ type: "googleCloudPubSub";
106
+ config: GoogleCloudPubSubConfigIn;
107
+ }
108
+
109
+ interface DestinationInSqs {
110
+ type: "sqs";
111
+ config: SqsConfigIn;
112
+ }
113
+
114
+ interface DestinationInSns {
115
+ type: "sns";
116
+ config: SnsConfigIn;
117
+ }
118
+
119
+ interface DestinationInBigQuery {
120
+ type: "bigQuery";
121
+ config: BigQueryConfigIn;
122
+ }
123
+
124
+ interface DestinationInClickhouse {
125
+ type: "clickhouse";
126
+ config: ClickhouseConfigIn;
127
+ }
128
+
129
+ interface DestinationInEventBridge {
130
+ type: "eventBridge";
131
+ config: EventBridgeConfigIn;
132
+ }
133
+
134
+ interface DestinationInSnowflake {
135
+ type: "snowflake";
136
+ config: SnowflakeConfigIn;
137
+ }
138
+
139
+ interface DestinationInRabbitMq {
140
+ type: "rabbitMq";
141
+ config: RabbitMqConfigIn;
142
+ }
143
+
144
+ interface DestinationInRedshift {
145
+ type: "redshift";
146
+ config: RedshiftConfigIn;
147
+ }
148
+
149
+ interface DestinationInPostgres {
150
+ type: "postgres";
151
+ config: PostgresConfigIn;
152
+ }
153
+
154
+ /** The destination's type and type-specific configuration. */
155
+ export type DestinationIn = _DestinationInFields &
156
+ (
157
+ | DestinationInPollingEndpoint
158
+ | DestinationInAzureBlobStorage
159
+ | DestinationInOtelTracing
160
+ | DestinationInFifoEndpoint
161
+ | DestinationInAmazonS3
162
+ | DestinationInGoogleCloudStorage
163
+ | DestinationInGoogleCloudPubSub
164
+ | DestinationInSqs
165
+ | DestinationInSns
166
+ | DestinationInBigQuery
167
+ | DestinationInClickhouse
168
+ | DestinationInEventBridge
169
+ | DestinationInSnowflake
170
+ | DestinationInRabbitMq
171
+ | DestinationInRedshift
172
+ | DestinationInPostgres
173
+ );
174
+
175
+ export const DestinationInSerializer = {
176
+ _fromJsonObject(object: any): DestinationIn {
177
+ const type = object["type"];
178
+
179
+ function getConfig(type: string): any {
180
+ switch (type) {
181
+ case "pollingEndpoint":
182
+ return {};
183
+ case "azureBlobStorage":
184
+ return AzureBlobStorageConfigInSerializer._fromJsonObject(object["config"]);
185
+ case "otelTracing":
186
+ return OtelTracingConfigInSerializer._fromJsonObject(object["config"]);
187
+ case "fifoEndpoint":
188
+ return FifoEndpointConfigInSerializer._fromJsonObject(object["config"]);
189
+ case "amazonS3":
190
+ return S3ConfigInSerializer._fromJsonObject(object["config"]);
191
+ case "googleCloudStorage":
192
+ return GoogleCloudStorageConfigInSerializer._fromJsonObject(object["config"]);
193
+ case "googleCloudPubSub":
194
+ return GoogleCloudPubSubConfigInSerializer._fromJsonObject(object["config"]);
195
+ case "sqs":
196
+ return SqsConfigInSerializer._fromJsonObject(object["config"]);
197
+ case "sns":
198
+ return SnsConfigInSerializer._fromJsonObject(object["config"]);
199
+ case "bigQuery":
200
+ return BigQueryConfigInSerializer._fromJsonObject(object["config"]);
201
+ case "clickhouse":
202
+ return ClickhouseConfigInSerializer._fromJsonObject(object["config"]);
203
+ case "eventBridge":
204
+ return EventBridgeConfigInSerializer._fromJsonObject(object["config"]);
205
+ case "snowflake":
206
+ return SnowflakeConfigInSerializer._fromJsonObject(object["config"]);
207
+ case "rabbitMq":
208
+ return RabbitMqConfigInSerializer._fromJsonObject(object["config"]);
209
+ case "redshift":
210
+ return RedshiftConfigInSerializer._fromJsonObject(object["config"]);
211
+ case "postgres":
212
+ return PostgresConfigInSerializer._fromJsonObject(object["config"]);
213
+ default:
214
+ throw new Error(`Unexpected type: ${type}`);
215
+ }
216
+ }
217
+
218
+ return {
219
+ type,
220
+ config: getConfig(type),
221
+ uid: object["uid"],
222
+ status:
223
+ object["status"] != null
224
+ ? DestinationStatusInSerializer._fromJsonObject(object["status"])
225
+ : undefined,
226
+ batchSize: object["batchSize"],
227
+ maxWaitSecs: object["maxWaitSecs"],
228
+ eventTypes: object["eventTypes"],
229
+ channels: object["channels"],
230
+ metadata: object["metadata"],
231
+ };
232
+ },
233
+
234
+ _toJsonObject(self: DestinationIn): any {
235
+ // biome-ignore lint/suspicious/noImplicitAnyLet: the return type needs to be any
236
+ let config;
237
+ switch (self.type) {
238
+ case "pollingEndpoint":
239
+ config = {};
240
+ break;
241
+ case "azureBlobStorage":
242
+ config = AzureBlobStorageConfigInSerializer._toJsonObject(self.config);
243
+ break;
244
+ case "otelTracing":
245
+ config = OtelTracingConfigInSerializer._toJsonObject(self.config);
246
+ break;
247
+ case "fifoEndpoint":
248
+ config = FifoEndpointConfigInSerializer._toJsonObject(self.config);
249
+ break;
250
+ case "amazonS3":
251
+ config = S3ConfigInSerializer._toJsonObject(self.config);
252
+ break;
253
+ case "googleCloudStorage":
254
+ config = GoogleCloudStorageConfigInSerializer._toJsonObject(self.config);
255
+ break;
256
+ case "googleCloudPubSub":
257
+ config = GoogleCloudPubSubConfigInSerializer._toJsonObject(self.config);
258
+ break;
259
+ case "sqs":
260
+ config = SqsConfigInSerializer._toJsonObject(self.config);
261
+ break;
262
+ case "sns":
263
+ config = SnsConfigInSerializer._toJsonObject(self.config);
264
+ break;
265
+ case "bigQuery":
266
+ config = BigQueryConfigInSerializer._toJsonObject(self.config);
267
+ break;
268
+ case "clickhouse":
269
+ config = ClickhouseConfigInSerializer._toJsonObject(self.config);
270
+ break;
271
+ case "eventBridge":
272
+ config = EventBridgeConfigInSerializer._toJsonObject(self.config);
273
+ break;
274
+ case "snowflake":
275
+ config = SnowflakeConfigInSerializer._toJsonObject(self.config);
276
+ break;
277
+ case "rabbitMq":
278
+ config = RabbitMqConfigInSerializer._toJsonObject(self.config);
279
+ break;
280
+ case "redshift":
281
+ config = RedshiftConfigInSerializer._toJsonObject(self.config);
282
+ break;
283
+ case "postgres":
284
+ config = PostgresConfigInSerializer._toJsonObject(self.config);
285
+ break;
286
+ }
287
+
288
+ return {
289
+ type: self.type,
290
+ config: config,
291
+ uid: self.uid,
292
+ status:
293
+ self.status != null
294
+ ? DestinationStatusInSerializer._toJsonObject(self.status)
295
+ : undefined,
296
+ batchSize: self.batchSize,
297
+ maxWaitSecs: self.maxWaitSecs,
298
+ eventTypes: self.eventTypes,
299
+ channels: self.channels,
300
+ metadata: self.metadata,
301
+ };
302
+ },
303
+ };