@tinybirdco/sdk 0.0.36 → 0.0.38

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 (59) hide show
  1. package/README.md +50 -1
  2. package/dist/api/api.d.ts +66 -1
  3. package/dist/api/api.d.ts.map +1 -1
  4. package/dist/api/api.js +114 -0
  5. package/dist/api/api.js.map +1 -1
  6. package/dist/api/api.test.js +192 -0
  7. package/dist/api/api.test.js.map +1 -1
  8. package/dist/api/tokens.d.ts +79 -0
  9. package/dist/api/tokens.d.ts.map +1 -0
  10. package/dist/api/tokens.js +80 -0
  11. package/dist/api/tokens.js.map +1 -0
  12. package/dist/api/tokens.test.d.ts +2 -0
  13. package/dist/api/tokens.test.d.ts.map +1 -0
  14. package/dist/api/tokens.test.js +209 -0
  15. package/dist/api/tokens.test.js.map +1 -0
  16. package/dist/cli/commands/init.d.ts +2 -0
  17. package/dist/cli/commands/init.d.ts.map +1 -1
  18. package/dist/cli/commands/init.js +2 -3
  19. package/dist/cli/commands/init.js.map +1 -1
  20. package/dist/client/base.d.ts +29 -1
  21. package/dist/client/base.d.ts.map +1 -1
  22. package/dist/client/base.js +44 -0
  23. package/dist/client/base.js.map +1 -1
  24. package/dist/client/base.test.js +25 -0
  25. package/dist/client/base.test.js.map +1 -1
  26. package/dist/client/tokens.d.ts +42 -0
  27. package/dist/client/tokens.d.ts.map +1 -0
  28. package/dist/client/tokens.js +67 -0
  29. package/dist/client/tokens.js.map +1 -0
  30. package/dist/client/tokens.test.d.ts +2 -0
  31. package/dist/client/tokens.test.d.ts.map +1 -0
  32. package/dist/client/tokens.test.js +79 -0
  33. package/dist/client/tokens.test.js.map +1 -0
  34. package/dist/client/types.d.ts +49 -0
  35. package/dist/client/types.d.ts.map +1 -1
  36. package/dist/index.d.ts +4 -2
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/schema/project.d.ts +40 -12
  41. package/dist/schema/project.d.ts.map +1 -1
  42. package/dist/schema/project.js +67 -13
  43. package/dist/schema/project.js.map +1 -1
  44. package/dist/schema/project.test.js +63 -10
  45. package/dist/schema/project.test.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/api/api.test.ts +265 -0
  48. package/src/api/api.ts +196 -0
  49. package/src/api/tokens.test.ts +253 -0
  50. package/src/api/tokens.ts +169 -0
  51. package/src/cli/commands/init.ts +5 -3
  52. package/src/client/base.test.ts +32 -0
  53. package/src/client/base.ts +60 -0
  54. package/src/client/tokens.test.ts +103 -0
  55. package/src/client/tokens.ts +69 -0
  56. package/src/client/types.ts +54 -0
  57. package/src/index.ts +20 -0
  58. package/src/schema/project.test.ts +75 -10
  59. package/src/schema/project.ts +134 -27
@@ -8,8 +8,15 @@ import type { PipeDefinition, ParamsDefinition, OutputDefinition } from "./pipe.
8
8
  import type { ConnectionDefinition } from "./connection.js";
9
9
  import { getEndpointConfig } from "./pipe.js";
10
10
  import type { TinybirdClient } from "../client/base.js";
11
- import type { QueryResult } from "../client/types.js";
11
+ import type {
12
+ AppendOptions,
13
+ AppendResult,
14
+ DatasourcesNamespace,
15
+ QueryOptions,
16
+ QueryResult,
17
+ } from "../client/types.js";
12
18
  import type { InferRow, InferParams, InferOutputRow } from "../infer/index.js";
19
+ import type { TokensNamespace } from "../client/tokens.js";
13
20
 
14
21
  // Symbol for brand typing - use Symbol.for() for global registry
15
22
  // This ensures the same symbol is used across module instances
@@ -41,11 +48,14 @@ type QueryMethod<T extends PipeDefinition<ParamsDefinition, OutputDefinition>> =
41
48
  : never;
42
49
 
43
50
  /**
44
- * Type for query methods object
45
- * Note: At runtime, only pipes with endpoint: true are included
51
+ * Type for pipe entity accessors object
52
+ * Note: At runtime, all declared pipes are included. Non-endpoint pipes throw
53
+ * when queried with a clear error message.
46
54
  */
47
- type QueryMethods<T extends PipesDefinition> = {
48
- [K in keyof T]: QueryMethod<T[K]>;
55
+ type PipeEntityAccessors<T extends PipesDefinition> = {
56
+ [K in keyof T]: {
57
+ query: QueryMethod<T[K]>;
58
+ };
49
59
  };
50
60
 
51
61
  /**
@@ -72,20 +82,48 @@ type IngestMethods<T extends DatasourcesDefinition> = {
72
82
  };
73
83
 
74
84
  /**
75
- * Typed client interface for a project
85
+ * Type for a datasource accessor with append method
76
86
  */
77
- export interface ProjectClient<
78
- TDatasources extends DatasourcesDefinition,
79
- TPipes extends PipesDefinition
80
- > {
81
- /** Query endpoint pipes */
82
- query: QueryMethods<TPipes>;
87
+ type DatasourceAccessor = {
88
+ /** Append data from a URL or file */
89
+ append(options: AppendOptions): Promise<AppendResult>;
90
+ };
91
+
92
+ /**
93
+ * Type for datasource accessors object
94
+ * Maps each datasource to an accessor with append method
95
+ */
96
+ type DatasourceAccessors<T extends DatasourcesDefinition> = {
97
+ [K in keyof T]: DatasourceAccessor;
98
+ };
99
+
100
+ /**
101
+ * Base project client interface
102
+ */
103
+ interface ProjectClientBase<TDatasources extends DatasourcesDefinition> {
83
104
  /** Ingest events to datasources */
84
105
  ingest: IngestMethods<TDatasources>;
106
+ /** Token operations (JWT creation, etc.) */
107
+ readonly tokens: TokensNamespace;
108
+ /** Datasource operations (append from URL/file) */
109
+ readonly datasources: DatasourcesNamespace;
110
+ /** Execute raw SQL queries */
111
+ sql<T = unknown>(sql: string, options?: QueryOptions): Promise<QueryResult<T>>;
85
112
  /** Raw client for advanced usage */
86
113
  readonly client: TinybirdClient;
87
114
  }
88
115
 
116
+ /**
117
+ * Typed client interface for a project
118
+ * Includes datasource accessors as top-level properties
119
+ */
120
+ export type ProjectClient<
121
+ TDatasources extends DatasourcesDefinition,
122
+ TPipes extends PipesDefinition
123
+ > = ProjectClientBase<TDatasources> &
124
+ DatasourceAccessors<TDatasources> &
125
+ PipeEntityAccessors<TPipes>;
126
+
89
127
  /**
90
128
  * Configuration for createTinybirdClient
91
129
  */
@@ -218,7 +256,7 @@ export function isProjectDefinition(value: unknown): value is ProjectDefinition
218
256
  /**
219
257
  * Build a typed Tinybird client from datasources and pipes
220
258
  *
221
- * This is an internal helper that builds query/ingest methods.
259
+ * This is an internal helper that builds pipe query and datasource ingest methods.
222
260
  */
223
261
  function buildProjectClient<
224
262
  TDatasources extends DatasourcesDefinition,
@@ -228,6 +266,14 @@ function buildProjectClient<
228
266
  pipes: TPipes,
229
267
  options?: { baseUrl?: string; token?: string; configDir?: string; devMode?: boolean }
230
268
  ): ProjectClient<TDatasources, TPipes> {
269
+ const RESERVED_CLIENT_NAMES = new Set([
270
+ "ingest",
271
+ "tokens",
272
+ "datasources",
273
+ "sql",
274
+ "client",
275
+ ]);
276
+
231
277
  // Lazy client initialization
232
278
  let _client: TinybirdClient | null = null;
233
279
 
@@ -251,33 +297,57 @@ function buildProjectClient<
251
297
  return _client;
252
298
  };
253
299
 
254
- // Build query methods for pipes
255
- const queryMethods: Record<string, (params?: unknown) => Promise<unknown>> = {};
300
+ // Build pipe accessors with query methods
301
+ const pipeAccessors: Record<string, { query: (params?: unknown) => Promise<unknown> }> = {};
256
302
  for (const [name, pipe] of Object.entries(pipes)) {
303
+ if (name in datasources) {
304
+ throw new Error(
305
+ `Name conflict in createTinybirdClient(): "${name}" is defined as both datasource and pipe. ` +
306
+ `Rename one of them to expose both as top-level client properties.`
307
+ );
308
+ }
309
+ if (RESERVED_CLIENT_NAMES.has(name)) {
310
+ throw new Error(
311
+ `Name conflict in createTinybirdClient(): "${name}" is reserved by the client API. ` +
312
+ `Rename this pipe to expose it as a top-level client property.`
313
+ );
314
+ }
315
+
257
316
  const endpointConfig = getEndpointConfig(pipe);
258
317
 
259
318
  if (!endpointConfig) {
260
319
  // Non-endpoint pipes get a stub that throws a clear error
261
- queryMethods[name] = async () => {
262
- throw new Error(
263
- `Pipe "${name}" is not exposed as an endpoint. ` +
264
- `Set "endpoint: true" in the pipe definition to enable querying.`
265
- );
320
+ pipeAccessors[name] = {
321
+ query: async () => {
322
+ throw new Error(
323
+ `Pipe "${name}" is not exposed as an endpoint. ` +
324
+ `Set "endpoint: true" in the pipe definition to enable querying.`
325
+ );
326
+ },
266
327
  };
267
328
  continue;
268
329
  }
269
330
 
270
331
  // Use the Tinybird pipe name (snake_case)
271
332
  const tinybirdName = pipe._name;
272
- queryMethods[name] = async (params?: unknown) => {
273
- const client = await getClient();
274
- return client.query(tinybirdName, (params ?? {}) as Record<string, unknown>);
333
+ pipeAccessors[name] = {
334
+ query: async (params?: unknown) => {
335
+ const client = await getClient();
336
+ return client.query(tinybirdName, (params ?? {}) as Record<string, unknown>);
337
+ },
275
338
  };
276
339
  }
277
340
 
278
341
  // Build ingest methods for datasources
279
342
  const ingestMethods: Record<string, (data: unknown) => Promise<void>> = {};
280
343
  for (const [name, datasource] of Object.entries(datasources)) {
344
+ if (RESERVED_CLIENT_NAMES.has(name)) {
345
+ throw new Error(
346
+ `Name conflict in createTinybirdClient(): "${name}" is reserved by the client API. ` +
347
+ `Rename this datasource to expose it as a top-level client property.`
348
+ );
349
+ }
350
+
281
351
  // Use the Tinybird datasource name (snake_case)
282
352
  const tinybirdName = datasource._name;
283
353
 
@@ -294,10 +364,46 @@ function buildProjectClient<
294
364
  };
295
365
  }
296
366
 
367
+ // Build datasource accessors for top-level access
368
+ const datasourceAccessors: Record<string, DatasourceAccessor> = {};
369
+ for (const [name, datasource] of Object.entries(datasources)) {
370
+ const tinybirdName = datasource._name;
371
+
372
+ datasourceAccessors[name] = {
373
+ append: async (options: AppendOptions) => {
374
+ const client = await getClient();
375
+ return client.datasources.append(tinybirdName, options);
376
+ },
377
+ };
378
+ }
379
+
297
380
  // Create the typed client object
298
381
  return {
299
- query: queryMethods,
382
+ ...datasourceAccessors,
383
+ ...pipeAccessors,
300
384
  ingest: ingestMethods,
385
+ sql: async <T = unknown>(sql: string, options: QueryOptions = {}) => {
386
+ const client = await getClient();
387
+ return client.sql<T>(sql, options);
388
+ },
389
+ get tokens(): TokensNamespace {
390
+ // Synchronous access - will throw if not initialized
391
+ if (!_client) {
392
+ throw new Error(
393
+ "Client not initialized. Call a query or ingest method first, or access client asynchronously."
394
+ );
395
+ }
396
+ return _client.tokens;
397
+ },
398
+ get datasources(): DatasourcesNamespace {
399
+ // Synchronous access - will throw if not initialized
400
+ if (!_client) {
401
+ throw new Error(
402
+ "Client not initialized. Call a query or ingest method first, or access client asynchronously."
403
+ );
404
+ }
405
+ return _client.datasources;
406
+ },
301
407
  get client(): TinybirdClient {
302
408
  // Synchronous client access - will throw if not initialized
303
409
  if (!_client) {
@@ -313,12 +419,13 @@ function buildProjectClient<
313
419
  /**
314
420
  * Create a typed Tinybird client
315
421
  *
316
- * Creates a client with typed query and ingest methods based on the provided
422
+ * Creates a client with typed pipe query and datasource ingest methods based on
423
+ * the provided
317
424
  * datasources and pipes. This is the recommended way to create a Tinybird client
318
425
  * when using the SDK's auto-generated client file.
319
426
  *
320
427
  * @param config - Client configuration with datasources and pipes
321
- * @returns A typed client with query and ingest methods
428
+ * @returns A typed client with pipe query and datasource ingest methods
322
429
  *
323
430
  * @example
324
431
  * ```ts
@@ -332,7 +439,7 @@ function buildProjectClient<
332
439
  * });
333
440
  *
334
441
  * // Query a pipe (fully typed)
335
- * const result = await tinybird.query.topPages({
442
+ * const result = await tinybird.topPages.query({
336
443
  * start_date: new Date('2024-01-01'),
337
444
  * end_date: new Date('2024-01-31'),
338
445
  * });