@tinybirdco/sdk 0.0.40 → 0.0.41

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.
@@ -70,7 +70,7 @@ describe("Project Schema", () => {
70
70
  expect(project.pipes.topEvents).toBe(topEvents);
71
71
  });
72
72
 
73
- it("creates tinybird client with pipe accessors and ingest methods", () => {
73
+ it("creates tinybird client with pipe and datasource accessors", () => {
74
74
  const events = defineDatasource("events", {
75
75
  schema: { id: t.string() },
76
76
  });
@@ -86,15 +86,15 @@ describe("Project Schema", () => {
86
86
  pipes: { topEvents },
87
87
  });
88
88
 
89
- expect(project.tinybird.ingest).toBeDefined();
90
89
  expect(typeof project.tinybird.topEvents.query).toBe("function");
91
- expect(typeof project.tinybird.ingest.events).toBe("function");
92
- expect(typeof project.tinybird.ingest.eventsBatch).toBe("function");
90
+ expect(typeof project.tinybird.events.ingest).toBe("function");
91
+ expect(typeof project.tinybird.events.append).toBe("function");
92
+ expect(typeof project.tinybird.events.replace).toBe("function");
93
93
  expect((project.tinybird as unknown as Record<string, unknown>).query).toBeUndefined();
94
94
  expect((project.tinybird as unknown as Record<string, unknown>).pipes).toBeUndefined();
95
95
  });
96
96
 
97
- it("creates datasource accessors with append/delete/truncate methods", () => {
97
+ it("creates datasource accessors with ingest/append/replace/delete/truncate methods", () => {
98
98
  const events = defineDatasource("events", {
99
99
  schema: { timestamp: t.dateTime() },
100
100
  });
@@ -104,7 +104,9 @@ describe("Project Schema", () => {
104
104
  });
105
105
 
106
106
  expect(project.tinybird.events).toBeDefined();
107
+ expect(typeof project.tinybird.events.ingest).toBe("function");
107
108
  expect(typeof project.tinybird.events.append).toBe("function");
109
+ expect(typeof project.tinybird.events.replace).toBe("function");
108
110
  expect(typeof project.tinybird.events.delete).toBe("function");
109
111
  expect(typeof project.tinybird.events.truncate).toBe("function");
110
112
  });
@@ -123,8 +125,12 @@ describe("Project Schema", () => {
123
125
 
124
126
  expect(project.tinybird.events).toBeDefined();
125
127
  expect(project.tinybird.pageViews).toBeDefined();
128
+ expect(typeof project.tinybird.events.ingest).toBe("function");
129
+ expect(typeof project.tinybird.pageViews.ingest).toBe("function");
126
130
  expect(typeof project.tinybird.events.append).toBe("function");
127
131
  expect(typeof project.tinybird.pageViews.append).toBe("function");
132
+ expect(typeof project.tinybird.events.replace).toBe("function");
133
+ expect(typeof project.tinybird.pageViews.replace).toBe("function");
128
134
  expect(typeof project.tinybird.events.delete).toBe("function");
129
135
  expect(typeof project.tinybird.pageViews.delete).toBe("function");
130
136
  expect(typeof project.tinybird.events.truncate).toBe("function");
@@ -284,7 +290,7 @@ describe("Project Schema", () => {
284
290
  process.env.NODE_ENV = originalNodeEnv;
285
291
  });
286
292
 
287
- it("creates a client with pipe accessors and ingest methods", () => {
293
+ it("creates a client with pipe and datasource accessors", () => {
288
294
  const events = defineDatasource("events", {
289
295
  schema: { id: t.string() },
290
296
  });
@@ -300,17 +306,17 @@ describe("Project Schema", () => {
300
306
  pipes: { topEvents },
301
307
  });
302
308
 
303
- expect(client.ingest).toBeDefined();
304
309
  expect(client.sql).toBeDefined();
305
310
  expect(typeof client.topEvents.query).toBe("function");
306
- expect(typeof client.ingest.events).toBe("function");
307
- expect(typeof client.ingest.eventsBatch).toBe("function");
311
+ expect(typeof client.events.ingest).toBe("function");
312
+ expect(typeof client.events.append).toBe("function");
313
+ expect(typeof client.events.replace).toBe("function");
308
314
  expect(typeof client.sql).toBe("function");
309
315
  expect((client as unknown as Record<string, unknown>).query).toBeUndefined();
310
316
  expect((client as unknown as Record<string, unknown>).pipes).toBeUndefined();
311
317
  });
312
318
 
313
- it("creates datasource accessors with append/delete/truncate methods", () => {
319
+ it("creates datasource accessors with ingest/append/replace/delete/truncate methods", () => {
314
320
  const events = defineDatasource("events", {
315
321
  schema: { id: t.string() },
316
322
  });
@@ -321,7 +327,9 @@ describe("Project Schema", () => {
321
327
  });
322
328
 
323
329
  expect(client.events).toBeDefined();
330
+ expect(typeof client.events.ingest).toBe("function");
324
331
  expect(typeof client.events.append).toBe("function");
332
+ expect(typeof client.events.replace).toBe("function");
325
333
  expect(typeof client.events.delete).toBe("function");
326
334
  expect(typeof client.events.truncate).toBe("function");
327
335
  });
@@ -341,8 +349,12 @@ describe("Project Schema", () => {
341
349
 
342
350
  expect(client.events).toBeDefined();
343
351
  expect(client.pageViews).toBeDefined();
352
+ expect(typeof client.events.ingest).toBe("function");
353
+ expect(typeof client.pageViews.ingest).toBe("function");
344
354
  expect(typeof client.events.append).toBe("function");
345
355
  expect(typeof client.pageViews.append).toBe("function");
356
+ expect(typeof client.events.replace).toBe("function");
357
+ expect(typeof client.pageViews.replace).toBe("function");
346
358
  expect(typeof client.events.delete).toBe("function");
347
359
  expect(typeof client.pageViews.delete).toBe("function");
348
360
  expect(typeof client.events.truncate).toBe("function");
@@ -361,7 +373,7 @@ describe("Project Schema", () => {
361
373
  devMode: true,
362
374
  });
363
375
 
364
- expect(clientWithDevMode.ingest).toBeDefined();
376
+ expect(clientWithDevMode.events.ingest).toBeDefined();
365
377
 
366
378
  const clientWithoutDevMode = createTinybirdClient({
367
379
  datasources: { events },
@@ -369,7 +381,7 @@ describe("Project Schema", () => {
369
381
  devMode: false,
370
382
  });
371
383
 
372
- expect(clientWithoutDevMode.ingest).toBeDefined();
384
+ expect(clientWithoutDevMode.events.ingest).toBeDefined();
373
385
  });
374
386
 
375
387
  it("accepts all configuration options", () => {
@@ -387,7 +399,7 @@ describe("Project Schema", () => {
387
399
  devMode: true,
388
400
  });
389
401
 
390
- expect(client.ingest).toBeDefined();
402
+ expect(client.events.ingest).toBeDefined();
391
403
  });
392
404
 
393
405
  it("throws error when accessing underlying client before initialization", () => {
@@ -14,6 +14,7 @@ import type {
14
14
  DatasourcesNamespace,
15
15
  DeleteOptions,
16
16
  DeleteResult,
17
+ IngestResult,
17
18
  QueryOptions,
18
19
  QueryResult,
19
20
  TruncateOptions,
@@ -62,35 +63,16 @@ type PipeEntityAccessors<T extends PipesDefinition> = {
62
63
  };
63
64
  };
64
65
 
65
- /**
66
- * Type for a single ingest method
67
- */
68
- type IngestMethod<T extends DatasourceDefinition<SchemaDefinition>> = (
69
- event: InferRow<T>
70
- ) => Promise<void>;
71
-
72
- /**
73
- * Type for a batch ingest method
74
- */
75
- type IngestBatchMethod<T extends DatasourceDefinition<SchemaDefinition>> = (
76
- events: InferRow<T>[]
77
- ) => Promise<void>;
78
-
79
- /**
80
- * Type for ingest methods object
81
- */
82
- type IngestMethods<T extends DatasourcesDefinition> = {
83
- [K in keyof T]: IngestMethod<T[K]>;
84
- } & {
85
- [K in keyof T as `${K & string}Batch`]: IngestBatchMethod<T[K]>;
86
- };
87
-
88
66
  /**
89
67
  * Type for a datasource accessor with import/mutation methods
90
68
  */
91
- type DatasourceAccessor = {
69
+ type DatasourceAccessor<T extends DatasourceDefinition<SchemaDefinition>> = {
70
+ /** Ingest a single event row */
71
+ ingest(event: InferRow<T>): Promise<IngestResult>;
92
72
  /** Append data from a URL or file */
93
73
  append(options: AppendOptions): Promise<AppendResult>;
74
+ /** Replace datasource content from a URL or file */
75
+ replace(options: AppendOptions): Promise<AppendResult>;
94
76
  /** Delete rows using a SQL condition */
95
77
  delete(options: DeleteOptions): Promise<DeleteResult>;
96
78
  /** Truncate all rows */
@@ -102,18 +84,16 @@ type DatasourceAccessor = {
102
84
  * Maps each datasource to an accessor with import/mutation methods
103
85
  */
104
86
  type DatasourceAccessors<T extends DatasourcesDefinition> = {
105
- [K in keyof T]: DatasourceAccessor;
87
+ [K in keyof T]: DatasourceAccessor<T[K]>;
106
88
  };
107
89
 
108
90
  /**
109
91
  * Base project client interface
110
92
  */
111
- interface ProjectClientBase<TDatasources extends DatasourcesDefinition> {
112
- /** Ingest events to datasources */
113
- ingest: IngestMethods<TDatasources>;
93
+ interface ProjectClientBase {
114
94
  /** Token operations (JWT creation, etc.) */
115
95
  readonly tokens: TokensNamespace;
116
- /** Datasource operations (append/delete/truncate) */
96
+ /** Datasource operations (ingest/append/replace/delete/truncate) */
117
97
  readonly datasources: DatasourcesNamespace;
118
98
  /** Execute raw SQL queries */
119
99
  sql<T = unknown>(sql: string, options?: QueryOptions): Promise<QueryResult<T>>;
@@ -128,7 +108,7 @@ interface ProjectClientBase<TDatasources extends DatasourcesDefinition> {
128
108
  export type ProjectClient<
129
109
  TDatasources extends DatasourcesDefinition,
130
110
  TPipes extends PipesDefinition
131
- > = ProjectClientBase<TDatasources> &
111
+ > = ProjectClientBase &
132
112
  DatasourceAccessors<TDatasources> &
133
113
  PipeEntityAccessors<TPipes>;
134
114
 
@@ -264,7 +244,7 @@ export function isProjectDefinition(value: unknown): value is ProjectDefinition
264
244
  /**
265
245
  * Build a typed Tinybird client from datasources and pipes
266
246
  *
267
- * This is an internal helper that builds pipe query and datasource ingest methods.
247
+ * This is an internal helper that builds pipe query and datasource methods.
268
248
  */
269
249
  function buildProjectClient<
270
250
  TDatasources extends DatasourcesDefinition,
@@ -275,7 +255,6 @@ function buildProjectClient<
275
255
  options?: { baseUrl?: string; token?: string; configDir?: string; devMode?: boolean }
276
256
  ): ProjectClient<TDatasources, TPipes> {
277
257
  const RESERVED_CLIENT_NAMES = new Set([
278
- "ingest",
279
258
  "tokens",
280
259
  "datasources",
281
260
  "sql",
@@ -346,8 +325,17 @@ function buildProjectClient<
346
325
  };
347
326
  }
348
327
 
349
- // Build ingest methods for datasources
350
- const ingestMethods: Record<string, (data: unknown) => Promise<void>> = {};
328
+ // Build datasource accessors for top-level access
329
+ const datasourceAccessors: Record<
330
+ string,
331
+ {
332
+ ingest: (event: unknown) => Promise<IngestResult>;
333
+ append: (options: AppendOptions) => Promise<AppendResult>;
334
+ replace: (options: AppendOptions) => Promise<AppendResult>;
335
+ delete: (options: DeleteOptions) => Promise<DeleteResult>;
336
+ truncate: (options?: TruncateOptions) => Promise<TruncateResult>;
337
+ }
338
+ > = {};
351
339
  for (const [name, datasource] of Object.entries(datasources)) {
352
340
  if (RESERVED_CLIENT_NAMES.has(name)) {
353
341
  throw new Error(
@@ -356,32 +344,21 @@ function buildProjectClient<
356
344
  );
357
345
  }
358
346
 
359
- // Use the Tinybird datasource name (snake_case)
360
- const tinybirdName = datasource._name;
361
-
362
- // Single event ingest
363
- ingestMethods[name] = async (event: unknown) => {
364
- const client = await getClient();
365
- await client.ingest(tinybirdName, event as Record<string, unknown>);
366
- };
367
-
368
- // Batch ingest
369
- ingestMethods[`${name}Batch`] = async (events: unknown) => {
370
- const client = await getClient();
371
- await client.ingestBatch(tinybirdName, events as Record<string, unknown>[]);
372
- };
373
- }
374
-
375
- // Build datasource accessors for top-level access
376
- const datasourceAccessors: Record<string, DatasourceAccessor> = {};
377
- for (const [name, datasource] of Object.entries(datasources)) {
378
347
  const tinybirdName = datasource._name;
379
348
 
380
349
  datasourceAccessors[name] = {
350
+ ingest: async (event: unknown) => {
351
+ const client = await getClient();
352
+ return client.datasources.ingest(tinybirdName, event as Record<string, unknown>);
353
+ },
381
354
  append: async (options: AppendOptions) => {
382
355
  const client = await getClient();
383
356
  return client.datasources.append(tinybirdName, options);
384
357
  },
358
+ replace: async (options: AppendOptions) => {
359
+ const client = await getClient();
360
+ return client.datasources.replace(tinybirdName, options);
361
+ },
385
362
  delete: async (options: DeleteOptions) => {
386
363
  const client = await getClient();
387
364
  return client.datasources.delete(tinybirdName, options);
@@ -397,7 +374,6 @@ function buildProjectClient<
397
374
  return {
398
375
  ...datasourceAccessors,
399
376
  ...pipeAccessors,
400
- ingest: ingestMethods,
401
377
  sql: async <T = unknown>(sql: string, options: QueryOptions = {}) => {
402
378
  const client = await getClient();
403
379
  return client.sql<T>(sql, options);
@@ -435,13 +411,13 @@ function buildProjectClient<
435
411
  /**
436
412
  * Create a typed Tinybird client
437
413
  *
438
- * Creates a client with typed pipe query and datasource ingest methods based on
414
+ * Creates a client with typed pipe query and datasource methods based on
439
415
  * the provided
440
416
  * datasources and pipes. This is the recommended way to create a Tinybird client
441
417
  * when using the SDK's auto-generated client file.
442
418
  *
443
419
  * @param config - Client configuration with datasources and pipes
444
- * @returns A typed client with pipe query and datasource ingest methods
420
+ * @returns A typed client with pipe query and datasource methods
445
421
  *
446
422
  * @example
447
423
  * ```ts
@@ -461,7 +437,7 @@ function buildProjectClient<
461
437
  * });
462
438
  *
463
439
  * // Ingest an event (fully typed)
464
- * await tinybird.ingest.pageViews({
440
+ * await tinybird.pageViews.ingest({
465
441
  * timestamp: new Date(),
466
442
  * pathname: '/home',
467
443
  * session_id: 'abc123',