@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.
- package/README.md +50 -1
- package/dist/api/api.d.ts +66 -1
- package/dist/api/api.d.ts.map +1 -1
- package/dist/api/api.js +114 -0
- package/dist/api/api.js.map +1 -1
- package/dist/api/api.test.js +192 -0
- package/dist/api/api.test.js.map +1 -1
- package/dist/api/tokens.d.ts +79 -0
- package/dist/api/tokens.d.ts.map +1 -0
- package/dist/api/tokens.js +80 -0
- package/dist/api/tokens.js.map +1 -0
- package/dist/api/tokens.test.d.ts +2 -0
- package/dist/api/tokens.test.d.ts.map +1 -0
- package/dist/api/tokens.test.js +209 -0
- package/dist/api/tokens.test.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +2 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/client/base.d.ts +29 -1
- package/dist/client/base.d.ts.map +1 -1
- package/dist/client/base.js +44 -0
- package/dist/client/base.js.map +1 -1
- package/dist/client/base.test.js +25 -0
- package/dist/client/base.test.js.map +1 -1
- package/dist/client/tokens.d.ts +42 -0
- package/dist/client/tokens.d.ts.map +1 -0
- package/dist/client/tokens.js +67 -0
- package/dist/client/tokens.js.map +1 -0
- package/dist/client/tokens.test.d.ts +2 -0
- package/dist/client/tokens.test.d.ts.map +1 -0
- package/dist/client/tokens.test.js +79 -0
- package/dist/client/tokens.test.js.map +1 -0
- package/dist/client/types.d.ts +49 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/schema/project.d.ts +40 -12
- package/dist/schema/project.d.ts.map +1 -1
- package/dist/schema/project.js +67 -13
- package/dist/schema/project.js.map +1 -1
- package/dist/schema/project.test.js +63 -10
- package/dist/schema/project.test.js.map +1 -1
- package/package.json +1 -1
- package/src/api/api.test.ts +265 -0
- package/src/api/api.ts +196 -0
- package/src/api/tokens.test.ts +253 -0
- package/src/api/tokens.ts +169 -0
- package/src/cli/commands/init.ts +5 -3
- package/src/client/base.test.ts +32 -0
- package/src/client/base.ts +60 -0
- package/src/client/tokens.test.ts +103 -0
- package/src/client/tokens.ts +69 -0
- package/src/client/types.ts +54 -0
- package/src/index.ts +20 -0
- package/src/schema/project.test.ts +75 -10
- package/src/schema/project.ts +134 -27
package/src/client/base.test.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { TinybirdClient, createClient } from "./base.js";
|
|
3
|
+
import type { DatasourcesNamespace } from "./types.js";
|
|
3
4
|
|
|
4
5
|
describe("TinybirdClient", () => {
|
|
5
6
|
describe("constructor", () => {
|
|
@@ -137,4 +138,35 @@ describe("TinybirdClient", () => {
|
|
|
137
138
|
expect(context.baseUrl).toBe("https://api.tinybird.co");
|
|
138
139
|
});
|
|
139
140
|
});
|
|
141
|
+
|
|
142
|
+
describe("datasources", () => {
|
|
143
|
+
it("exposes datasources namespace", () => {
|
|
144
|
+
const client = createClient({
|
|
145
|
+
baseUrl: "https://api.tinybird.co",
|
|
146
|
+
token: "test-token",
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
expect(client.datasources).toBeDefined();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("datasources namespace has append method", () => {
|
|
153
|
+
const client = createClient({
|
|
154
|
+
baseUrl: "https://api.tinybird.co",
|
|
155
|
+
token: "test-token",
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(typeof client.datasources.append).toBe("function");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("datasources conforms to DatasourcesNamespace interface", () => {
|
|
162
|
+
const client = createClient({
|
|
163
|
+
baseUrl: "https://api.tinybird.co",
|
|
164
|
+
token: "test-token",
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const datasources: DatasourcesNamespace = client.datasources;
|
|
168
|
+
expect(datasources).toBeDefined();
|
|
169
|
+
expect(typeof datasources.append).toBe("function");
|
|
170
|
+
});
|
|
171
|
+
});
|
|
140
172
|
});
|
package/src/client/base.ts
CHANGED
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
|
+
AppendOptions,
|
|
7
|
+
AppendResult,
|
|
6
8
|
ClientConfig,
|
|
7
9
|
ClientContext,
|
|
10
|
+
DatasourcesNamespace,
|
|
8
11
|
QueryResult,
|
|
9
12
|
IngestResult,
|
|
10
13
|
QueryOptions,
|
|
@@ -12,6 +15,7 @@ import type {
|
|
|
12
15
|
} from "./types.js";
|
|
13
16
|
import { TinybirdError } from "./types.js";
|
|
14
17
|
import { TinybirdApi, TinybirdApiError } from "../api/api.js";
|
|
18
|
+
import { TokensNamespace } from "./tokens.js";
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* Resolved token info from dev mode
|
|
@@ -57,6 +61,14 @@ export class TinybirdClient {
|
|
|
57
61
|
private contextPromise: Promise<ClientContext> | null = null;
|
|
58
62
|
private resolvedContext: ClientContext | null = null;
|
|
59
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Datasources namespace for import operations
|
|
66
|
+
*/
|
|
67
|
+
readonly datasources: DatasourcesNamespace;
|
|
68
|
+
|
|
69
|
+
/** Token operations (JWT creation, etc.) */
|
|
70
|
+
public readonly tokens: TokensNamespace;
|
|
71
|
+
|
|
60
72
|
constructor(config: ClientConfig) {
|
|
61
73
|
// Validate required config
|
|
62
74
|
if (!config.baseUrl) {
|
|
@@ -71,6 +83,54 @@ export class TinybirdClient {
|
|
|
71
83
|
...config,
|
|
72
84
|
baseUrl: config.baseUrl.replace(/\/$/, ""),
|
|
73
85
|
};
|
|
86
|
+
|
|
87
|
+
// Initialize datasources namespace
|
|
88
|
+
this.datasources = {
|
|
89
|
+
append: (datasourceName: string, options: AppendOptions): Promise<AppendResult> => {
|
|
90
|
+
return this.appendDatasource(datasourceName, options);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Initialize tokens namespace
|
|
95
|
+
this.tokens = new TokensNamespace(
|
|
96
|
+
() => this.getToken(),
|
|
97
|
+
this.config.baseUrl,
|
|
98
|
+
this.config.fetch,
|
|
99
|
+
this.config.timeout
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Append data to a datasource from a URL or local file
|
|
105
|
+
*
|
|
106
|
+
* @param datasourceName - Name of the datasource
|
|
107
|
+
* @param options - Append options including url or file source
|
|
108
|
+
* @returns Append result
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* // Append from URL
|
|
113
|
+
* await client.datasources.append('events', {
|
|
114
|
+
* url: 'https://example.com/data.csv',
|
|
115
|
+
* });
|
|
116
|
+
*
|
|
117
|
+
* // Append from local file
|
|
118
|
+
* await client.datasources.append('events', {
|
|
119
|
+
* file: './data/events.ndjson',
|
|
120
|
+
* });
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
private async appendDatasource(
|
|
124
|
+
datasourceName: string,
|
|
125
|
+
options: AppendOptions
|
|
126
|
+
): Promise<AppendResult> {
|
|
127
|
+
const token = await this.getToken();
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
return await this.getApi(token).appendDatasource(datasourceName, options);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
this.rethrowApiError(error);
|
|
133
|
+
}
|
|
74
134
|
}
|
|
75
135
|
|
|
76
136
|
/**
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { TinybirdClient } from "./base.js";
|
|
3
|
+
|
|
4
|
+
const mockFetch = vi.fn();
|
|
5
|
+
global.fetch = mockFetch;
|
|
6
|
+
|
|
7
|
+
describe("TokensNamespace", () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
mockFetch.mockReset();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("uses client custom fetch for createJWT", async () => {
|
|
13
|
+
const customFetch = vi.fn().mockResolvedValueOnce({
|
|
14
|
+
ok: true,
|
|
15
|
+
json: () => Promise.resolve({ token: "jwt-token" }),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const client = new TinybirdClient({
|
|
19
|
+
baseUrl: "https://api.tinybird.co",
|
|
20
|
+
token: "p.admin-token",
|
|
21
|
+
fetch: customFetch as typeof fetch,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const result = await client.tokens.createJWT({
|
|
25
|
+
name: "user_token",
|
|
26
|
+
expiresAt: 1700000000,
|
|
27
|
+
scopes: [{ type: "PIPES:READ", resource: "analytics_pipe" }],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(result).toEqual({ token: "jwt-token" });
|
|
31
|
+
expect(customFetch).toHaveBeenCalledTimes(1);
|
|
32
|
+
expect(mockFetch).not.toHaveBeenCalled();
|
|
33
|
+
|
|
34
|
+
const [url, init] = customFetch.mock.calls[0] as [string, RequestInit];
|
|
35
|
+
const parsed = new URL(url);
|
|
36
|
+
expect(parsed.pathname).toBe("/v0/tokens/");
|
|
37
|
+
expect(parsed.searchParams.get("expiration_time")).toBe("1700000000");
|
|
38
|
+
expect(parsed.searchParams.get("from")).toBe("ts-sdk");
|
|
39
|
+
expect(init.method).toBe("POST");
|
|
40
|
+
const headers = new Headers(init.headers);
|
|
41
|
+
expect(headers.get("Authorization")).toBe("Bearer p.admin-token");
|
|
42
|
+
expect(headers.get("Content-Type")).toBe("application/json");
|
|
43
|
+
|
|
44
|
+
const body = JSON.parse(String(init.body)) as {
|
|
45
|
+
name: string;
|
|
46
|
+
scopes: Array<{ type: string; resource: string }>;
|
|
47
|
+
limits?: { rps?: number };
|
|
48
|
+
};
|
|
49
|
+
expect(body).toEqual({
|
|
50
|
+
name: "user_token",
|
|
51
|
+
scopes: [{ type: "PIPES:READ", resource: "analytics_pipe" }],
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("sends full JWT payload when limits and scope fields are provided", async () => {
|
|
56
|
+
const customFetch = vi.fn().mockResolvedValueOnce({
|
|
57
|
+
ok: true,
|
|
58
|
+
json: () => Promise.resolve({ token: "jwt-token" }),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const client = new TinybirdClient({
|
|
62
|
+
baseUrl: "https://api.tinybird.co",
|
|
63
|
+
token: "p.admin-token",
|
|
64
|
+
fetch: customFetch as typeof fetch,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await client.tokens.createJWT({
|
|
68
|
+
name: "tenant_token",
|
|
69
|
+
expiresAt: 1700000000,
|
|
70
|
+
scopes: [
|
|
71
|
+
{
|
|
72
|
+
type: "PIPES:READ",
|
|
73
|
+
resource: "analytics_pipe",
|
|
74
|
+
fixed_params: { tenant_id: 123 },
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
limits: { rps: 10 },
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const [, init] = customFetch.mock.calls[0] as [string, RequestInit];
|
|
81
|
+
const body = JSON.parse(String(init.body)) as {
|
|
82
|
+
name: string;
|
|
83
|
+
scopes: Array<{
|
|
84
|
+
type: string;
|
|
85
|
+
resource: string;
|
|
86
|
+
fixed_params?: Record<string, unknown>;
|
|
87
|
+
}>;
|
|
88
|
+
limits?: { rps?: number };
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
expect(body).toEqual({
|
|
92
|
+
name: "tenant_token",
|
|
93
|
+
scopes: [
|
|
94
|
+
{
|
|
95
|
+
type: "PIPES:READ",
|
|
96
|
+
resource: "analytics_pipe",
|
|
97
|
+
fixed_params: { tenant_id: 123 },
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
limits: { rps: 10 },
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token operations namespace for TinybirdClient
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CreateJWTOptions, CreateJWTResult } from "../api/tokens.js";
|
|
6
|
+
import { createJWT as apiCreateJWT, TokenApiError } from "../api/tokens.js";
|
|
7
|
+
import { TinybirdError } from "./types.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Token operations namespace for TinybirdClient
|
|
11
|
+
*/
|
|
12
|
+
export class TokensNamespace {
|
|
13
|
+
constructor(
|
|
14
|
+
private readonly getToken: () => Promise<string>,
|
|
15
|
+
private readonly baseUrl: string,
|
|
16
|
+
private readonly fetchFn?: typeof globalThis.fetch,
|
|
17
|
+
private readonly timeout?: number
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a JWT token
|
|
22
|
+
*
|
|
23
|
+
* Creates a short-lived JWT token with specific scopes for secure,
|
|
24
|
+
* time-limited access to pipes and datasources.
|
|
25
|
+
*
|
|
26
|
+
* @param options - JWT creation options
|
|
27
|
+
* @returns The created JWT token
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const result = await client.tokens.createJWT({
|
|
32
|
+
* name: "user_123_token",
|
|
33
|
+
* expiresAt: new Date(Date.now() + 3600 * 1000), // 1 hour
|
|
34
|
+
* scopes: [
|
|
35
|
+
* {
|
|
36
|
+
* type: "PIPES:READ",
|
|
37
|
+
* resource: "user_analytics",
|
|
38
|
+
* fixed_params: { user_id: 123 },
|
|
39
|
+
* },
|
|
40
|
+
* ],
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* console.log(result.token); // "eyJ..."
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
async createJWT(options: CreateJWTOptions): Promise<CreateJWTResult> {
|
|
47
|
+
const token = await this.getToken();
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
return await apiCreateJWT(
|
|
51
|
+
{
|
|
52
|
+
baseUrl: this.baseUrl,
|
|
53
|
+
token,
|
|
54
|
+
fetch: this.fetchFn,
|
|
55
|
+
timeout: this.timeout,
|
|
56
|
+
},
|
|
57
|
+
options
|
|
58
|
+
);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error instanceof TokenApiError) {
|
|
61
|
+
throw new TinybirdError(error.message, error.status, {
|
|
62
|
+
error: error.message,
|
|
63
|
+
status: error.status,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/client/types.ts
CHANGED
|
@@ -189,3 +189,57 @@ export interface TypedDatasourceIngest<TRow> {
|
|
|
189
189
|
/** Send multiple events in a batch */
|
|
190
190
|
sendBatch(events: TRow[], options?: IngestOptions): Promise<IngestResult>;
|
|
191
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Data format for append operations
|
|
195
|
+
*/
|
|
196
|
+
export type AppendFormat = "csv" | "ndjson" | "parquet";
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* CSV dialect options for customizing CSV parsing
|
|
200
|
+
*/
|
|
201
|
+
export interface CsvDialectOptions {
|
|
202
|
+
/** Field delimiter character (default: ',') */
|
|
203
|
+
delimiter?: string;
|
|
204
|
+
/** New line character(s) (default: '\n') */
|
|
205
|
+
newLine?: string;
|
|
206
|
+
/** Escape character for special characters */
|
|
207
|
+
escapeChar?: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Options for append operation
|
|
212
|
+
* Exactly one of `url` or `file` must be provided
|
|
213
|
+
*/
|
|
214
|
+
export interface AppendOptions {
|
|
215
|
+
/** Remote URL to import data from */
|
|
216
|
+
url?: string;
|
|
217
|
+
/** Local file path to import data from */
|
|
218
|
+
file?: string;
|
|
219
|
+
/** CSV dialect options (only applicable for csv format) */
|
|
220
|
+
csvDialect?: CsvDialectOptions;
|
|
221
|
+
/** Request timeout in milliseconds */
|
|
222
|
+
timeout?: number;
|
|
223
|
+
/** AbortController signal for cancellation */
|
|
224
|
+
signal?: AbortSignal;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Result of an append operation
|
|
229
|
+
*/
|
|
230
|
+
export interface AppendResult {
|
|
231
|
+
/** Number of rows successfully appended */
|
|
232
|
+
successful_rows: number;
|
|
233
|
+
/** Number of rows that failed to append (quarantined) */
|
|
234
|
+
quarantined_rows: number;
|
|
235
|
+
/** Import ID for tracking */
|
|
236
|
+
import_id?: string;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Datasources namespace interface for raw client
|
|
241
|
+
*/
|
|
242
|
+
export interface DatasourcesNamespace {
|
|
243
|
+
/** Append data to a datasource from a URL or file */
|
|
244
|
+
append(datasourceName: string, options: AppendOptions): Promise<AppendResult>;
|
|
245
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -202,8 +202,12 @@ export type {
|
|
|
202
202
|
export { TinybirdClient, createClient } from "./client/base.js";
|
|
203
203
|
export { TinybirdError } from "./client/types.js";
|
|
204
204
|
export type {
|
|
205
|
+
AppendOptions,
|
|
206
|
+
AppendResult,
|
|
205
207
|
ClientConfig,
|
|
206
208
|
ClientContext,
|
|
209
|
+
CsvDialectOptions,
|
|
210
|
+
DatasourcesNamespace,
|
|
207
211
|
QueryResult,
|
|
208
212
|
IngestResult,
|
|
209
213
|
QueryOptions,
|
|
@@ -226,7 +230,12 @@ export type {
|
|
|
226
230
|
TinybirdApiConfig,
|
|
227
231
|
TinybirdApiQueryOptions,
|
|
228
232
|
TinybirdApiIngestOptions,
|
|
233
|
+
TinybirdApiAppendOptions,
|
|
229
234
|
TinybirdApiRequestInit,
|
|
235
|
+
TinybirdApiTokenScope,
|
|
236
|
+
TinybirdApiCreateTokenRequest,
|
|
237
|
+
TinybirdApiCreateTokenOptions,
|
|
238
|
+
TinybirdApiCreateTokenResult,
|
|
230
239
|
} from "./api/api.js";
|
|
231
240
|
|
|
232
241
|
// ============ Preview Environment ============
|
|
@@ -246,6 +255,17 @@ export {
|
|
|
246
255
|
} from "./api/dashboard.js";
|
|
247
256
|
export type { RegionInfo } from "./api/dashboard.js";
|
|
248
257
|
|
|
258
|
+
// ============ Token API ============
|
|
259
|
+
export { createJWT, TokenApiError } from "./api/tokens.js";
|
|
260
|
+
export type {
|
|
261
|
+
TokenApiConfig,
|
|
262
|
+
JWTScope,
|
|
263
|
+
JWTScopeType,
|
|
264
|
+
JWTLimits,
|
|
265
|
+
CreateJWTOptions,
|
|
266
|
+
CreateJWTResult,
|
|
267
|
+
} from "./api/tokens.js";
|
|
268
|
+
|
|
249
269
|
// ============ Config Types ============
|
|
250
270
|
// Import from config-types.ts to avoid bundling esbuild in client code
|
|
251
271
|
export type { TinybirdConfig, DevMode } from "./cli/config-types.js";
|
|
@@ -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
|
|
73
|
+
it("creates tinybird client with pipe accessors and ingest methods", () => {
|
|
74
74
|
const events = defineDatasource("events", {
|
|
75
75
|
schema: { id: t.string() },
|
|
76
76
|
});
|
|
@@ -86,11 +86,43 @@ describe("Project Schema", () => {
|
|
|
86
86
|
pipes: { topEvents },
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
expect(project.tinybird.query).toBeDefined();
|
|
90
89
|
expect(project.tinybird.ingest).toBeDefined();
|
|
91
|
-
expect(typeof project.tinybird.query
|
|
90
|
+
expect(typeof project.tinybird.topEvents.query).toBe("function");
|
|
92
91
|
expect(typeof project.tinybird.ingest.events).toBe("function");
|
|
93
92
|
expect(typeof project.tinybird.ingest.eventsBatch).toBe("function");
|
|
93
|
+
expect((project.tinybird as unknown as Record<string, unknown>).query).toBeUndefined();
|
|
94
|
+
expect((project.tinybird as unknown as Record<string, unknown>).pipes).toBeUndefined();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("creates datasource accessors with append method", () => {
|
|
98
|
+
const events = defineDatasource("events", {
|
|
99
|
+
schema: { timestamp: t.dateTime() },
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const project = defineProject({
|
|
103
|
+
datasources: { events },
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(project.tinybird.events).toBeDefined();
|
|
107
|
+
expect(typeof project.tinybird.events.append).toBe("function");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("creates multiple datasource accessors", () => {
|
|
111
|
+
const events = defineDatasource("events", {
|
|
112
|
+
schema: { timestamp: t.dateTime() },
|
|
113
|
+
});
|
|
114
|
+
const pageViews = defineDatasource("page_views", {
|
|
115
|
+
schema: { pathname: t.string() },
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const project = defineProject({
|
|
119
|
+
datasources: { events, pageViews },
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
expect(project.tinybird.events).toBeDefined();
|
|
123
|
+
expect(project.tinybird.pageViews).toBeDefined();
|
|
124
|
+
expect(typeof project.tinybird.events.append).toBe("function");
|
|
125
|
+
expect(typeof project.tinybird.pageViews.append).toBe("function");
|
|
94
126
|
});
|
|
95
127
|
|
|
96
128
|
it("throws error when accessing client before initialization", () => {
|
|
@@ -113,7 +145,7 @@ describe("Project Schema", () => {
|
|
|
113
145
|
});
|
|
114
146
|
|
|
115
147
|
// Cast to any since the type system expects params but stub throws regardless
|
|
116
|
-
const queryFn = project.tinybird.query
|
|
148
|
+
const queryFn = project.tinybird.internalPipe.query as () => Promise<unknown>;
|
|
117
149
|
await expect(queryFn()).rejects.toThrow(
|
|
118
150
|
'Pipe "internalPipe" is not exposed as an endpoint'
|
|
119
151
|
);
|
|
@@ -246,7 +278,7 @@ describe("Project Schema", () => {
|
|
|
246
278
|
process.env.NODE_ENV = originalNodeEnv;
|
|
247
279
|
});
|
|
248
280
|
|
|
249
|
-
it("creates a client with
|
|
281
|
+
it("creates a client with pipe accessors and ingest methods", () => {
|
|
250
282
|
const events = defineDatasource("events", {
|
|
251
283
|
schema: { id: t.string() },
|
|
252
284
|
});
|
|
@@ -262,11 +294,47 @@ describe("Project Schema", () => {
|
|
|
262
294
|
pipes: { topEvents },
|
|
263
295
|
});
|
|
264
296
|
|
|
265
|
-
expect(client.query).toBeDefined();
|
|
266
297
|
expect(client.ingest).toBeDefined();
|
|
267
|
-
expect(
|
|
298
|
+
expect(client.sql).toBeDefined();
|
|
299
|
+
expect(typeof client.topEvents.query).toBe("function");
|
|
268
300
|
expect(typeof client.ingest.events).toBe("function");
|
|
269
301
|
expect(typeof client.ingest.eventsBatch).toBe("function");
|
|
302
|
+
expect(typeof client.sql).toBe("function");
|
|
303
|
+
expect((client as unknown as Record<string, unknown>).query).toBeUndefined();
|
|
304
|
+
expect((client as unknown as Record<string, unknown>).pipes).toBeUndefined();
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("creates datasource accessors with append method", () => {
|
|
308
|
+
const events = defineDatasource("events", {
|
|
309
|
+
schema: { id: t.string() },
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const client = createTinybirdClient({
|
|
313
|
+
datasources: { events },
|
|
314
|
+
pipes: {},
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
expect(client.events).toBeDefined();
|
|
318
|
+
expect(typeof client.events.append).toBe("function");
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("creates multiple datasource accessors", () => {
|
|
322
|
+
const events = defineDatasource("events", {
|
|
323
|
+
schema: { id: t.string() },
|
|
324
|
+
});
|
|
325
|
+
const pageViews = defineDatasource("page_views", {
|
|
326
|
+
schema: { pathname: t.string() },
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const client = createTinybirdClient({
|
|
330
|
+
datasources: { events, pageViews },
|
|
331
|
+
pipes: {},
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
expect(client.events).toBeDefined();
|
|
335
|
+
expect(client.pageViews).toBeDefined();
|
|
336
|
+
expect(typeof client.events.append).toBe("function");
|
|
337
|
+
expect(typeof client.pageViews.append).toBe("function");
|
|
270
338
|
});
|
|
271
339
|
|
|
272
340
|
it("accepts devMode option", () => {
|
|
@@ -281,7 +349,6 @@ describe("Project Schema", () => {
|
|
|
281
349
|
devMode: true,
|
|
282
350
|
});
|
|
283
351
|
|
|
284
|
-
expect(clientWithDevMode.query).toBeDefined();
|
|
285
352
|
expect(clientWithDevMode.ingest).toBeDefined();
|
|
286
353
|
|
|
287
354
|
const clientWithoutDevMode = createTinybirdClient({
|
|
@@ -290,7 +357,6 @@ describe("Project Schema", () => {
|
|
|
290
357
|
devMode: false,
|
|
291
358
|
});
|
|
292
359
|
|
|
293
|
-
expect(clientWithoutDevMode.query).toBeDefined();
|
|
294
360
|
expect(clientWithoutDevMode.ingest).toBeDefined();
|
|
295
361
|
});
|
|
296
362
|
|
|
@@ -309,7 +375,6 @@ describe("Project Schema", () => {
|
|
|
309
375
|
devMode: true,
|
|
310
376
|
});
|
|
311
377
|
|
|
312
|
-
expect(client.query).toBeDefined();
|
|
313
378
|
expect(client.ingest).toBeDefined();
|
|
314
379
|
});
|
|
315
380
|
|