@tinybirdco/sdk 0.0.42 → 0.0.44

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 (43) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +3 -3
  3. package/dist/cli/commands/init.js +2 -2
  4. package/dist/cli/commands/init.test.js +1 -1
  5. package/dist/cli/commands/init.test.js.map +1 -1
  6. package/dist/cli/config.d.ts +10 -0
  7. package/dist/cli/config.d.ts.map +1 -1
  8. package/dist/cli/config.js +22 -0
  9. package/dist/cli/config.js.map +1 -1
  10. package/dist/client/preview.js +1 -1
  11. package/dist/client/preview.js.map +1 -1
  12. package/dist/codegen/index.js +4 -4
  13. package/dist/codegen/index.js.map +1 -1
  14. package/dist/codegen/index.test.js +3 -3
  15. package/dist/codegen/index.test.js.map +1 -1
  16. package/dist/generator/client.js +3 -3
  17. package/dist/generator/client.js.map +1 -1
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.test.d.ts +2 -0
  23. package/dist/index.test.d.ts.map +1 -0
  24. package/dist/index.test.js +12 -0
  25. package/dist/index.test.js.map +1 -0
  26. package/dist/schema/project.d.ts +20 -9
  27. package/dist/schema/project.d.ts.map +1 -1
  28. package/dist/schema/project.js +127 -136
  29. package/dist/schema/project.js.map +1 -1
  30. package/dist/schema/project.test.js +22 -0
  31. package/dist/schema/project.test.js.map +1 -1
  32. package/package.json +2 -1
  33. package/src/cli/commands/init.test.ts +1 -1
  34. package/src/cli/commands/init.ts +2 -2
  35. package/src/cli/config.ts +26 -0
  36. package/src/client/preview.ts +1 -1
  37. package/src/codegen/index.test.ts +3 -3
  38. package/src/codegen/index.ts +4 -4
  39. package/src/generator/client.ts +3 -3
  40. package/src/index.test.ts +13 -0
  41. package/src/index.ts +9 -3
  42. package/src/schema/project.test.ts +28 -0
  43. package/src/schema/project.ts +173 -181
@@ -304,7 +304,7 @@ describe("generateClientFile", () => {
304
304
 
305
305
  const file = generateClientFile(datasources, pipes);
306
306
 
307
- expect(file).toContain('import { createTinybirdClient } from "@tinybirdco/sdk"');
307
+ expect(file).toContain('import { Tinybird } from "@tinybirdco/sdk"');
308
308
  expect(file).toContain('import { events, type EventsRow } from "./datasources.js"');
309
309
  expect(file).toContain('import { topEvents, type TopEventsParams, type TopEventsOutput } from "./pipes.js"');
310
310
  expect(file).toContain("datasources: { events }");
@@ -321,7 +321,7 @@ describe("generateClientFile", () => {
321
321
  expect(file).toContain('import { dirname } from "path"');
322
322
  // Should derive __configDir from import.meta.url
323
323
  expect(file).toContain("const __configDir = dirname(fileURLToPath(import.meta.url))");
324
- // Should pass configDir to createTinybirdClient
324
+ // Should pass configDir to Tinybird constructor
325
325
  expect(file).toContain("configDir: __configDir");
326
326
  });
327
327
 
@@ -386,6 +386,6 @@ describe("generateAllFiles", () => {
386
386
  expect(result.pipeCount).toBe(1);
387
387
  expect(result.datasourcesContent).toContain("defineDatasource");
388
388
  expect(result.pipesContent).toContain("defineEndpoint");
389
- expect(result.clientContent).toContain("createTinybirdClient");
389
+ expect(result.clientContent).toContain("new Tinybird");
390
390
  });
391
391
  });
@@ -267,7 +267,7 @@ export function generateClientFile(
267
267
  " * Generated from existing workspace resources.",
268
268
  " */",
269
269
  "",
270
- 'import { createTinybirdClient } from "@tinybirdco/sdk";',
270
+ 'import { Tinybird } from "@tinybirdco/sdk";',
271
271
  // Node imports for deriving configDir from import.meta.url (monorepo support)
272
272
  'import { fileURLToPath } from "url";',
273
273
  'import { dirname } from "path";',
@@ -313,7 +313,7 @@ export function generateClientFile(
313
313
  lines.push("const __configDir = dirname(fileURLToPath(import.meta.url));");
314
314
  lines.push("");
315
315
  lines.push("// Create the typed Tinybird client");
316
- lines.push("export const tinybird = createTinybirdClient({");
316
+ lines.push("export const tinybird = new Tinybird({");
317
317
 
318
318
  if (datasources.length > 0) {
319
319
  const dsNames = datasources.map((ds) => toCamelCase(ds.name)).join(", ");
@@ -417,7 +417,7 @@ export function generateCombinedFile(
417
417
  ];
418
418
 
419
419
  // Build imports
420
- const sdkImports: string[] = ["createTinybirdClient", "t"];
420
+ const sdkImports: string[] = ["Tinybird", "t"];
421
421
 
422
422
  if (datasources.length > 0) {
423
423
  sdkImports.push("defineDatasource", "engine", "type InferRow");
@@ -505,7 +505,7 @@ export function generateCombinedFile(
505
505
  lines.push("// This ensures tinybird.json is found regardless of where the app runs from");
506
506
  lines.push("const __configDir = dirname(fileURLToPath(import.meta.url));");
507
507
  lines.push("");
508
- lines.push("export const tinybird = createTinybirdClient({");
508
+ lines.push("export const tinybird = new Tinybird({");
509
509
  lines.push(` datasources: { ${dsNames} },`);
510
510
  lines.push(` pipes: { ${pipeNames} },`);
511
511
  lines.push(" configDir: __configDir,");
@@ -108,7 +108,7 @@ export function generateClientFile(options: GenerateClientOptions): GeneratedCli
108
108
  sdkTypes.push("InferParams", "InferOutputRow");
109
109
  }
110
110
  importLines.push(
111
- `import { createTinybirdClient, type ${sdkTypes.join(", type ")} } from "@tinybirdco/sdk";`
111
+ `import { Tinybird, type ${sdkTypes.join(", type ")} } from "@tinybirdco/sdk";`
112
112
  );
113
113
  // Node imports for deriving configDir from import.meta.url (monorepo support)
114
114
  importLines.push(`import { fileURLToPath } from "url";`);
@@ -127,7 +127,7 @@ export function generateClientFile(options: GenerateClientOptions): GeneratedCli
127
127
  reexportLines.push(`export { ${allExports.join(", ")} } from "${relativePath}";`);
128
128
  }
129
129
 
130
- // Build createTinybirdClient call
130
+ // Build Tinybird constructor call
131
131
  const datasourceNames = Object.keys(entities.datasources);
132
132
  const pipeNames = Object.keys(entities.pipes);
133
133
 
@@ -136,7 +136,7 @@ export function generateClientFile(options: GenerateClientOptions): GeneratedCli
136
136
  // This ensures tinybird.json is found regardless of where the app runs from
137
137
  clientLines.push("const __configDir = dirname(fileURLToPath(import.meta.url));");
138
138
  clientLines.push("");
139
- clientLines.push("export const tinybird = createTinybirdClient({");
139
+ clientLines.push("export const tinybird = new Tinybird({");
140
140
 
141
141
  if (datasourceNames.length > 0) {
142
142
  clientLines.push(` datasources: { ${datasourceNames.join(", ")} },`);
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as sdk from "./index.js";
3
+
4
+ describe("root public exports", () => {
5
+ it("does not expose legacy project-client aliases", () => {
6
+ expect("createTinybirdClient" in sdk).toBe(false);
7
+ });
8
+
9
+ it("keeps documented project constructors", () => {
10
+ expect(typeof sdk.defineProject).toBe("function");
11
+ expect(typeof sdk.Tinybird).toBe("function");
12
+ });
13
+ });
package/src/index.ts CHANGED
@@ -168,12 +168,18 @@ export type {
168
168
  } from "./schema/pipe.js";
169
169
 
170
170
  // ============ Project ============
171
- export { defineProject, isProjectDefinition, getDatasourceNames, getPipeNames, getDatasource, getPipe, createTinybirdClient } from "./schema/project.js";
171
+ export {
172
+ defineProject,
173
+ isProjectDefinition,
174
+ getDatasourceNames,
175
+ getPipeNames,
176
+ getDatasource,
177
+ getPipe,
178
+ Tinybird,
179
+ } from "./schema/project.js";
172
180
  export type {
173
181
  ProjectDefinition,
174
182
  ProjectConfig,
175
- ProjectClient,
176
- TinybirdClientConfig,
177
183
  DatasourcesDefinition,
178
184
  PipesDefinition,
179
185
  ConnectionsDefinition,
@@ -410,5 +410,33 @@ describe("Project Schema", () => {
410
410
 
411
411
  expect(() => client.client).toThrow("Client not initialized");
412
412
  });
413
+
414
+ it("does not allow datasource names to overwrite internal client state", () => {
415
+ const events = defineDatasource("events", {
416
+ schema: { id: t.string() },
417
+ });
418
+
419
+ const client = createTinybirdClient({
420
+ datasources: { _client: events },
421
+ pipes: {},
422
+ });
423
+
424
+ expect(client._client).toBeDefined();
425
+ expect(() => client.client).toThrow("Client not initialized");
426
+ });
427
+
428
+ it("does not allow datasource names to overwrite internal options state", () => {
429
+ const events = defineDatasource("events", {
430
+ schema: { id: t.string() },
431
+ });
432
+
433
+ const client = createTinybirdClient({
434
+ datasources: { _options: events },
435
+ pipes: {},
436
+ });
437
+
438
+ expect(client._options).toBeDefined();
439
+ expect(() => client.client).toThrow("Client not initialized");
440
+ });
413
441
  });
414
442
  });
@@ -216,8 +216,8 @@ export function defineProject<
216
216
  const pipes = (config.pipes ?? {}) as TPipes;
217
217
  const connections = (config.connections ?? {}) as TConnections;
218
218
 
219
- // Use the shared client builder
220
- const tinybird = buildProjectClient(datasources, pipes);
219
+ // Create the typed Tinybird client
220
+ const tinybird = new Tinybird({ datasources, pipes });
221
221
 
222
222
  return {
223
223
  [PROJECT_BRAND]: true,
@@ -241,220 +241,212 @@ export function isProjectDefinition(value: unknown): value is ProjectDefinition
241
241
  );
242
242
  }
243
243
 
244
+ const RESERVED_CLIENT_NAMES = new Set(["tokens", "datasources", "sql", "client"]);
245
+
246
+ /**
247
+ * Constructor interface for Tinybird class
248
+ * This allows TypeScript to infer the correct return type with typed accessors
249
+ */
250
+ interface TinybirdConstructor {
251
+ new <TDatasources extends DatasourcesDefinition, TPipes extends PipesDefinition>(
252
+ config: TinybirdClientConfig<TDatasources, TPipes>
253
+ ): ProjectClient<TDatasources, TPipes>;
254
+ }
255
+
244
256
  /**
245
- * Build a typed Tinybird client from datasources and pipes
257
+ * Typed Tinybird client
258
+ *
259
+ * Creates a client with typed pipe query and datasource methods based on
260
+ * the provided datasources and pipes.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * import { Tinybird } from '@tinybirdco/sdk';
265
+ * import { pageViews, events } from './datasources';
266
+ * import { topPages } from './pipes';
267
+ *
268
+ * export const tinybird = new Tinybird({
269
+ * datasources: { pageViews, events },
270
+ * pipes: { topPages },
271
+ * });
246
272
  *
247
- * This is an internal helper that builds pipe query and datasource methods.
273
+ * // Query a pipe (fully typed)
274
+ * const result = await tinybird.topPages.query({
275
+ * start_date: new Date('2024-01-01'),
276
+ * end_date: new Date('2024-01-31'),
277
+ * });
278
+ *
279
+ * // Ingest an event (fully typed)
280
+ * await tinybird.pageViews.ingest({
281
+ * timestamp: new Date(),
282
+ * pathname: '/home',
283
+ * session_id: 'abc123',
284
+ * });
285
+ * ```
248
286
  */
249
- function buildProjectClient<
250
- TDatasources extends DatasourcesDefinition,
251
- TPipes extends PipesDefinition
252
- >(
253
- datasources: TDatasources,
254
- pipes: TPipes,
255
- options?: { baseUrl?: string; token?: string; configDir?: string; devMode?: boolean }
256
- ): ProjectClient<TDatasources, TPipes> {
257
- const RESERVED_CLIENT_NAMES = new Set([
258
- "tokens",
259
- "datasources",
260
- "sql",
261
- "client",
262
- ]);
263
-
264
- // Lazy client initialization
265
- let _client: TinybirdClient | null = null;
266
-
267
- const getClient = async (): Promise<TinybirdClient> => {
268
- if (!_client) {
269
- // Dynamic imports to avoid circular dependencies
287
+ export const Tinybird: TinybirdConstructor = class Tinybird<
288
+ TDatasources extends DatasourcesDefinition = DatasourcesDefinition,
289
+ TPipes extends PipesDefinition = PipesDefinition
290
+ > {
291
+ #client: TinybirdClient | null = null;
292
+ readonly #options: {
293
+ baseUrl?: string;
294
+ token?: string;
295
+ configDir?: string;
296
+ devMode?: boolean;
297
+ };
298
+
299
+ constructor(config: TinybirdClientConfig<TDatasources, TPipes>) {
300
+ this.#options = {
301
+ baseUrl: config.baseUrl,
302
+ token: config.token,
303
+ configDir: config.configDir,
304
+ devMode: config.devMode,
305
+ };
306
+
307
+ // Build pipe accessors with query methods
308
+ for (const [name, pipe] of Object.entries(config.pipes)) {
309
+ if (name in config.datasources) {
310
+ throw new Error(
311
+ `Name conflict: "${name}" is defined as both datasource and pipe. ` +
312
+ `Rename one of them to expose both as top-level client properties.`
313
+ );
314
+ }
315
+ if (RESERVED_CLIENT_NAMES.has(name)) {
316
+ throw new Error(
317
+ `Name conflict: "${name}" is reserved by the client API. ` +
318
+ `Rename this pipe to expose it as a top-level client property.`
319
+ );
320
+ }
321
+
322
+ const endpointConfig = getEndpointConfig(pipe);
323
+
324
+ if (!endpointConfig) {
325
+ (this as Record<string, unknown>)[name] = {
326
+ query: async () => {
327
+ throw new Error(
328
+ `Pipe "${name}" is not exposed as an endpoint. ` +
329
+ `Set "endpoint: true" in the pipe definition to enable querying.`
330
+ );
331
+ },
332
+ };
333
+ continue;
334
+ }
335
+
336
+ const tinybirdName = pipe._name;
337
+ (this as Record<string, unknown>)[name] = {
338
+ query: async (params?: unknown) => {
339
+ const client = await this.#getClient();
340
+ return client.query(tinybirdName, (params ?? {}) as Record<string, unknown>);
341
+ },
342
+ };
343
+ }
344
+
345
+ // Build datasource accessors for top-level access
346
+ for (const [name, datasource] of Object.entries(config.datasources)) {
347
+ if (RESERVED_CLIENT_NAMES.has(name)) {
348
+ throw new Error(
349
+ `Name conflict: "${name}" is reserved by the client API. ` +
350
+ `Rename this datasource to expose it as a top-level client property.`
351
+ );
352
+ }
353
+
354
+ const tinybirdName = datasource._name;
355
+
356
+ (this as Record<string, unknown>)[name] = {
357
+ ingest: async (event: unknown) => {
358
+ const client = await this.#getClient();
359
+ return client.datasources.ingest(tinybirdName, event as Record<string, unknown>);
360
+ },
361
+ append: async (options: AppendOptions) => {
362
+ const client = await this.#getClient();
363
+ return client.datasources.append(tinybirdName, options);
364
+ },
365
+ replace: async (options: AppendOptions) => {
366
+ const client = await this.#getClient();
367
+ return client.datasources.replace(tinybirdName, options);
368
+ },
369
+ delete: async (options: DeleteOptions) => {
370
+ const client = await this.#getClient();
371
+ return client.datasources.delete(tinybirdName, options);
372
+ },
373
+ truncate: async (options: TruncateOptions = {}) => {
374
+ const client = await this.#getClient();
375
+ return client.datasources.truncate(tinybirdName, options);
376
+ },
377
+ };
378
+ }
379
+ }
380
+
381
+ async #getClient(): Promise<TinybirdClient> {
382
+ if (!this.#client) {
270
383
  const { createClient } = await import("../client/base.js");
271
384
  const { resolveToken } = await import("../client/preview.js");
272
385
 
273
- // Resolve the token (handles preview environment detection)
274
- const baseUrl = options?.baseUrl ?? process.env.TINYBIRD_URL ?? "https://api.tinybird.co";
275
- const token = await resolveToken({ baseUrl, token: options?.token });
386
+ const baseUrl =
387
+ this.#options.baseUrl ?? process.env.TINYBIRD_URL ?? "https://api.tinybird.co";
388
+ const token = await resolveToken({ baseUrl, token: this.#options.token });
276
389
 
277
- _client = createClient({
390
+ this.#client = createClient({
278
391
  baseUrl,
279
392
  token,
280
- devMode: options?.devMode ?? process.env.NODE_ENV === "development",
281
- configDir: options?.configDir,
393
+ devMode: this.#options.devMode ?? process.env.NODE_ENV === "development",
394
+ configDir: this.#options.configDir,
282
395
  });
283
396
  }
284
- return _client;
285
- };
397
+ return this.#client;
398
+ }
399
+
400
+ /** Execute raw SQL queries */
401
+ async sql<T = unknown>(sqlQuery: string, options: QueryOptions = {}): Promise<QueryResult<T>> {
402
+ const client = await this.#getClient();
403
+ return client.sql<T>(sqlQuery, options);
404
+ }
286
405
 
287
- // Build pipe accessors with query methods
288
- const pipeAccessors: Record<string, { query: (params?: unknown) => Promise<unknown> }> = {};
289
- for (const [name, pipe] of Object.entries(pipes)) {
290
- if (name in datasources) {
406
+ /** Token operations (JWT creation, etc.) */
407
+ get tokens(): TokensNamespace {
408
+ if (!this.#client) {
291
409
  throw new Error(
292
- `Name conflict in createTinybirdClient(): "${name}" is defined as both datasource and pipe. ` +
293
- `Rename one of them to expose both as top-level client properties.`
410
+ "Client not initialized. Call a query or ingest method first, or access client asynchronously."
294
411
  );
295
412
  }
296
- if (RESERVED_CLIENT_NAMES.has(name)) {
413
+ return this.#client.tokens;
414
+ }
415
+
416
+ /** Datasource operations (ingest/append/replace/delete/truncate) */
417
+ get datasources(): DatasourcesNamespace {
418
+ if (!this.#client) {
297
419
  throw new Error(
298
- `Name conflict in createTinybirdClient(): "${name}" is reserved by the client API. ` +
299
- `Rename this pipe to expose it as a top-level client property.`
420
+ "Client not initialized. Call a query or ingest method first, or access client asynchronously."
300
421
  );
301
422
  }
302
-
303
- const endpointConfig = getEndpointConfig(pipe);
304
-
305
- if (!endpointConfig) {
306
- // Non-endpoint pipes get a stub that throws a clear error
307
- pipeAccessors[name] = {
308
- query: async () => {
309
- throw new Error(
310
- `Pipe "${name}" is not exposed as an endpoint. ` +
311
- `Set "endpoint: true" in the pipe definition to enable querying.`
312
- );
313
- },
314
- };
315
- continue;
316
- }
317
-
318
- // Use the Tinybird pipe name (snake_case)
319
- const tinybirdName = pipe._name;
320
- pipeAccessors[name] = {
321
- query: async (params?: unknown) => {
322
- const client = await getClient();
323
- return client.query(tinybirdName, (params ?? {}) as Record<string, unknown>);
324
- },
325
- };
423
+ return this.#client.datasources;
326
424
  }
327
425
 
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
- > = {};
339
- for (const [name, datasource] of Object.entries(datasources)) {
340
- if (RESERVED_CLIENT_NAMES.has(name)) {
426
+ /** Raw client for advanced usage */
427
+ get client(): TinybirdClient {
428
+ if (!this.#client) {
341
429
  throw new Error(
342
- `Name conflict in createTinybirdClient(): "${name}" is reserved by the client API. ` +
343
- `Rename this datasource to expose it as a top-level client property.`
430
+ "Client not initialized. Call a query or ingest method first, or access client asynchronously."
344
431
  );
345
432
  }
346
-
347
- const tinybirdName = datasource._name;
348
-
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
- },
354
- append: async (options: AppendOptions) => {
355
- const client = await getClient();
356
- return client.datasources.append(tinybirdName, options);
357
- },
358
- replace: async (options: AppendOptions) => {
359
- const client = await getClient();
360
- return client.datasources.replace(tinybirdName, options);
361
- },
362
- delete: async (options: DeleteOptions) => {
363
- const client = await getClient();
364
- return client.datasources.delete(tinybirdName, options);
365
- },
366
- truncate: async (options: TruncateOptions = {}) => {
367
- const client = await getClient();
368
- return client.datasources.truncate(tinybirdName, options);
369
- },
370
- };
433
+ return this.#client;
371
434
  }
372
-
373
- // Create the typed client object
374
- return {
375
- ...datasourceAccessors,
376
- ...pipeAccessors,
377
- sql: async <T = unknown>(sql: string, options: QueryOptions = {}) => {
378
- const client = await getClient();
379
- return client.sql<T>(sql, options);
380
- },
381
- get tokens(): TokensNamespace {
382
- // Synchronous access - will throw if not initialized
383
- if (!_client) {
384
- throw new Error(
385
- "Client not initialized. Call a query or ingest method first, or access client asynchronously."
386
- );
387
- }
388
- return _client.tokens;
389
- },
390
- get datasources(): DatasourcesNamespace {
391
- // Synchronous access - will throw if not initialized
392
- if (!_client) {
393
- throw new Error(
394
- "Client not initialized. Call a query or ingest method first, or access client asynchronously."
395
- );
396
- }
397
- return _client.datasources;
398
- },
399
- get client(): TinybirdClient {
400
- // Synchronous client access - will throw if not initialized
401
- if (!_client) {
402
- throw new Error(
403
- "Client not initialized. Call a query or ingest method first, or access client asynchronously."
404
- );
405
- }
406
- return _client;
407
- },
408
- } as ProjectClient<TDatasources, TPipes>;
409
- }
435
+ } as unknown as TinybirdConstructor;
410
436
 
411
437
  /**
412
438
  * Create a typed Tinybird client
413
439
  *
414
- * Creates a client with typed pipe query and datasource methods based on
415
- * the provided
416
- * datasources and pipes. This is the recommended way to create a Tinybird client
417
- * when using the SDK's auto-generated client file.
440
+ * @deprecated Use `new Tinybird(...)` instead. This function is kept for backward compatibility.
418
441
  *
419
442
  * @param config - Client configuration with datasources and pipes
420
443
  * @returns A typed client with pipe query and datasource methods
421
- *
422
- * @example
423
- * ```ts
424
- * import { createTinybirdClient } from '@tinybirdco/sdk';
425
- * import { pageViews, events } from './datasources';
426
- * import { topPages } from './pipes';
427
- *
428
- * export const tinybird = createTinybirdClient({
429
- * datasources: { pageViews, events },
430
- * pipes: { topPages },
431
- * });
432
- *
433
- * // Query a pipe (fully typed)
434
- * const result = await tinybird.topPages.query({
435
- * start_date: new Date('2024-01-01'),
436
- * end_date: new Date('2024-01-31'),
437
- * });
438
- *
439
- * // Ingest an event (fully typed)
440
- * await tinybird.pageViews.ingest({
441
- * timestamp: new Date(),
442
- * pathname: '/home',
443
- * session_id: 'abc123',
444
- * });
445
- * ```
446
444
  */
447
445
  export function createTinybirdClient<
448
446
  TDatasources extends DatasourcesDefinition,
449
447
  TPipes extends PipesDefinition
450
- >(
451
- config: TinybirdClientConfig<TDatasources, TPipes>
452
- ): ProjectClient<TDatasources, TPipes> {
453
- return buildProjectClient(
454
- config.datasources,
455
- config.pipes,
456
- { baseUrl: config.baseUrl, token: config.token, configDir: config.configDir, devMode: config.devMode }
457
- );
448
+ >(config: TinybirdClientConfig<TDatasources, TPipes>): ProjectClient<TDatasources, TPipes> {
449
+ return new Tinybird(config);
458
450
  }
459
451
 
460
452
  /**