@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.
- package/LICENSE +7 -0
- package/README.md +3 -3
- package/dist/cli/commands/init.js +2 -2
- package/dist/cli/commands/init.test.js +1 -1
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/config.d.ts +10 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +22 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/client/preview.js +1 -1
- package/dist/client/preview.js.map +1 -1
- package/dist/codegen/index.js +4 -4
- package/dist/codegen/index.js.map +1 -1
- package/dist/codegen/index.test.js +3 -3
- package/dist/codegen/index.test.js.map +1 -1
- package/dist/generator/client.js +3 -3
- package/dist/generator/client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +12 -0
- package/dist/index.test.js.map +1 -0
- package/dist/schema/project.d.ts +20 -9
- package/dist/schema/project.d.ts.map +1 -1
- package/dist/schema/project.js +127 -136
- package/dist/schema/project.js.map +1 -1
- package/dist/schema/project.test.js +22 -0
- package/dist/schema/project.test.js.map +1 -1
- package/package.json +2 -1
- package/src/cli/commands/init.test.ts +1 -1
- package/src/cli/commands/init.ts +2 -2
- package/src/cli/config.ts +26 -0
- package/src/client/preview.ts +1 -1
- package/src/codegen/index.test.ts +3 -3
- package/src/codegen/index.ts +4 -4
- package/src/generator/client.ts +3 -3
- package/src/index.test.ts +13 -0
- package/src/index.ts +9 -3
- package/src/schema/project.test.ts +28 -0
- 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 {
|
|
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
|
|
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("
|
|
389
|
+
expect(result.clientContent).toContain("new Tinybird");
|
|
390
390
|
});
|
|
391
391
|
});
|
package/src/codegen/index.ts
CHANGED
|
@@ -267,7 +267,7 @@ export function generateClientFile(
|
|
|
267
267
|
" * Generated from existing workspace resources.",
|
|
268
268
|
" */",
|
|
269
269
|
"",
|
|
270
|
-
'import {
|
|
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 =
|
|
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[] = ["
|
|
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 =
|
|
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,");
|
package/src/generator/client.ts
CHANGED
|
@@ -108,7 +108,7 @@ export function generateClientFile(options: GenerateClientOptions): GeneratedCli
|
|
|
108
108
|
sdkTypes.push("InferParams", "InferOutputRow");
|
|
109
109
|
}
|
|
110
110
|
importLines.push(
|
|
111
|
-
`import {
|
|
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
|
|
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 =
|
|
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 {
|
|
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
|
});
|
package/src/schema/project.ts
CHANGED
|
@@ -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
|
-
//
|
|
220
|
-
const tinybird =
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
250
|
-
TDatasources extends DatasourcesDefinition,
|
|
251
|
-
TPipes extends PipesDefinition
|
|
252
|
-
>
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
-
|
|
274
|
-
|
|
275
|
-
const token = await resolveToken({ baseUrl, token: options
|
|
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
|
-
|
|
390
|
+
this.#client = createClient({
|
|
278
391
|
baseUrl,
|
|
279
392
|
token,
|
|
280
|
-
devMode: options
|
|
281
|
-
configDir: options
|
|
393
|
+
devMode: this.#options.devMode ?? process.env.NODE_ENV === "development",
|
|
394
|
+
configDir: this.#options.configDir,
|
|
282
395
|
});
|
|
283
396
|
}
|
|
284
|
-
return
|
|
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
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
/**
|